2014-10-27 14 views
8

Sto cercando un modo intelligente per incrementare e quindi decrementare una variabile contatore. Voglio che la variabile contatore inizi a un valore basso e incrementa, verso un valore più alto. Una volta raggiunto il valore più alto, il contatore diminuisce fino a raggiungere il valore più basso. Una volta raggiunto il valore più basso, il contatore incrementa nuovamente il valore più alto ... Penso che tu abbia capito il punto.Come possiamo incrementare e quindi decrementare un contatore senza condizionali?

Sto lavorando su un un canvas animation dove mi piacerebbe di impiegare un po 'di furbizia, senza l'utilizzo di if o altri test condizionali:

Ecco la logica condizionale che gestisce la variabile contatore:

incrementing = true 

foo = -> 

    length += 1 if incrementing 
    length -= 1 if not incrementing 

    incrementing = false if length > 100 
    incrementing = true if length < 1 

Inizialmente, pensavo di poter usare il modulo. Tuttavia, la divisione modulo reimposta solo il contatore sul valore inferiore - non decrementa il contatore una volta raggiunto il valore massimo.

0 % 10 = 0 
1 % 10 = 1 
2 % 10 = 2 
3 % 10 = 3 
4 % 10 = 4 
5 % 10 = 5 
6 % 10 = 6 
7 % 10 = 7 
8 % 10 = 8 
9 % 10 = 9 
10 % 10 = 0 
11 % 10 = 1 
12 % 10 = 2 
13 % 10 = 3 

Sono sicuro che ci deve essere un modo per farlo senza usare test condizionali. Supponendo un valore inferiore di 0 e un valore massimo di 10, il metodo dovrebbe produrre quanto segue.

? = 0 
? = 1 
? = 2 
? = 3 
? = 4 
? = 5 
? = 6 
? = 7 
? = 8 
? = 9 
? = 8 
? = 7 
? = 6 
? = 5 
+1

'+ 1' per aver bisogno di una soluzione per un non-problema totale, puramente per rendere il codice più bello. Questo è il motivo per cui apprendiamo CoffeeScript. –

risposta

15

Prima diamo un'occhiata ad alcune onde!

Ciao onde!

types of waves

Potete identificare quello che soddisfa le vostre esigenze?

Se hai indovinato Triangle Wave, hai ragione!

L'onda triangolare oscilla con una pendenza uniforme finché non raggiunge un valore minimo o massimo, quindi la pendenza viene invertita.

due cose per lavorare qui:

  • l'origine della funzione inizierà a metà dell'onda
  • l'onda oscilla da x a -x

Vogliamo per avviare l'output su 0 e includere solo i valori positivi

function triangle(t, a) { 
    return Math.abs(((t + a/2) % a) - a/2); 
} 

Proviamo fuori

for (var i=0; i<20; i++) { 
    console.log(i, triangle(i, 10)); 
} 

uscita

0 0 
1 1 
2 2 
3 3 
4 4 
5 5 
6 4 
7 3 
8 2 
9 1 
10 0 
11 1 
12 2 
13 3 
14 4 
15 5 
16 4 
17 3 
18 2 
19 1 

Così, quando chiamiamo triangle(i, 10) il 10 è il "periodo". Questo ci dice quanti passi vogliamo avere nella nostra funzione prima che si ripeta.

Un periodo di 6 ci darebbe 6 valori, 0, 1, 2, 3, 2, 1

Un periodo di 4 ci darebbe 4 valori, 0, 1, 2, 1 ecc

Se si vuole andare da 0-9, si avrebbe bisogno di un periodo di 20

+0

Ecco la versione a dente di sega. Utile per il ripristino a 0 'function sawtooth (t, a) { return Math.abs (((t + a)% a)); } ' – veganista

2

Eccone uno:

(x&8)+(x&7)*((~x&8)/4-1) 

che vi darà

0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1,0,1,... 

Naturalmente c'è in realtà è un condizionale in là, appena nascosto come un'operazione bit per bit.

Un'altra possibilità è un contatore un'onda triangolare:

(x^((x&8)/-8))&7 

che fa

0,1,2,3,4,5,6,7,7,6,5,4,3,2,1,0,0,... 

nuovamente c'è un condizionale nascosto che capovolge i bit quando diventa metà.

Problemi correlati