Track
/
Factor
Factor
/
Esercizi
/
Auto, assemblatevi!
Auto, assemblatevi!

Auto, assemblatevi!

Esercizio di apprendimento

Introduzione

Questo esercizio introduce i condizionali, cioè la scelta tra due o più possibili linee d'azione in base a un valore. Si basa sui valori booleani che hai incontrato in L'infiltrazione di Annalyn e sull'aritmetica dei numeri interi di Conversione di valuta.

Parole di confronto

Si trovano tutte in math (e in kernel per =):

=  ( x y -- ? )    ! equal
<  ( x y -- ? )    ! less than
<= ( x y -- ? )    ! less than or equal
>  ( x y -- ? )    ! greater than
>= ( x y -- ? )    ! greater than or equal
3 3 = .     ! => t
2 3 < .     ! => t
3 3 <= .    ! => t
3 4 = not . ! => t    (inequality: combine = with not)

zero? (in math) è una scorciatoia per il test più comune, 0 =: consuma il numero e impila sullo stack un valore che indica se era zero:

zero? ( n -- ? )    ! t when n is 0

Verifiche di intervallo

between? (in math.order) verifica se un valore cade all'interno di un intervallo inclusivo. È comodo quando un'azione dipende dalla fascia in cui finisce un numero:

between? ( x lo hi -- ? )    ! lo <= x <= hi (inclusive)
5 1 10 between? .    ! => t
0 1 10 between? .    ! => f
10 1 10 between? .   ! => t   (inclusive at both ends)

Lo vedrai spesso usato come predicato di cond (dup 1 4 between?) per scegliere un ramo in base all'intervallo invece che a un singolo valore.

Quotations

Le parole di confronto qui sopra producono valori booleani; per agire su un valore booleano passi al condizionale una o più quotation. Una quotation è un frammento di codice racchiuso tra parentesi quadre, [ ... ]. Scriverla impila il codice sullo stack come valore invece di eseguirlo: una parola come if decide poi quale quotation eseguire.

[ neg ]   ! a quotation that negates the top of the stack
[ ]       ! the empty quotation — does nothing

Un esercizio successivo tratta le quotation in modo completo; per ora, leggi [ ... ] come «il codice da eseguire per questo ramo».

if, when, unless

if (in kernel) prende un valore booleano e due quotation. Esegue la prima quotation quando il booleano è veritiero e la seconda quando è falso:

if ( ? then-quot else-quot -- )
: abs ( x -- y ) dup 0 < [ neg ] [ ] if ;

when esegue la sua quotation solo quando il booleano è veritiero; unless solo quando è falso:

when   ( ? quot -- )
unless ( ? quot -- )

if*, when*, e unless*

Tre varianti di kernel trattano il booleano come un valore che vale la pena conservare quando è veritiero. Sono utili quando una parola restituisce «la cosa, oppure f»:

if*     ( ? true false -- )    ! truthy: true is called WITH ? on stack
when*   ( ? true       -- )    ! truthy: true is called WITH ? on stack
unless* ( ? false      -- )    ! falsy: false runs and pushes a default

if* è la forma a due rami. Il ramo veritiero viene chiamato con il valore ancora sullo stack; il ramo falso viene chiamato senza:

42 [ ] [ "nothing" ] if* .   ! prints 42
f  [ ] [ "nothing" ] if* .   ! prints "nothing"

unless* è l'idioma canonico del «valore o valore predefinito». Se il valore è veritiero, viene lasciato com'è; se è f, il valore viene eliminato e la quotation viene eseguita per impilare un sostituto:

"hello" [ "anonymous" ] unless* .   ! => "hello"
f       [ "anonymous" ] unless* .   ! => "anonymous"

when* è la forma a un ramo di if*: esegue la sua quotation (con il valore ancora sullo stack) solo quando il valore è veritiero, e quando è f si limita a eliminare il valore. Usalo per integrare un risultato del tipo «la cosa, oppure f» in un valore accumulato, senza doverti preoccupare di gestire il caso f:

0 41 [ + ] when* .   ! => 41   (truthy: 41 added to the running total)
0 f  [ + ] when* .   ! => 0    (falsy: f dropped, total left untouched)

cond

Quando hai diverse azioni alternative tra cui scegliere, cond (in combinators) è la scelta naturale. Prende un array di coppie { predicate body } ed esegue il corpo del primo predicato che produce un valore veritiero:

USING: combinators ;

: classify ( n -- label )
    {
        { [ dup 0 <  ] [ drop "negative" ] }
        { [ dup 0 =  ] [ drop "zero"     ] }
        [ drop "positive" ]
    } cond ;

Qualche dettaglio da tenere presente:

  • Le coppie vengono provate in ordine. Vince la prima corrispondenza.
  • Una voce senza predicato (solo una singola quotation) alla fine funge da caso predefinito.
  • Ogni predicato esamina l'input ma dovrebbe lasciare lo stack dei dati come l'ha trovato: dup ... <test> è l'idioma abituale.
  • Il corpo della coppia scelta riceve lo stesso stack che aveva visto il predicato, quindi di solito inizia con un drop dell'input per poi impilare il risultato.

Istruzioni

In questo esercizio scriverai del codice per analizzare la produzione di una catena di montaggio in una fabbrica di automobili. La velocità della catena di montaggio può andare da 0 (spenta) a 10 (massima).

Alla sua velocità minima diversa da zero (1), vengono prodotte 221 automobili ogni ora. La produzione aumenta in modo lineare con la velocità, quindi alla velocità 4 la linea produce 4 * 221 = 884 automobili all'ora. Tuttavia, velocità più alte aumentano la probabilità che vengano prodotte automobili difettose, che poi devono essere scartate.

Hai quattro compiti. Ognuno preleva dallo stack un singolo parametro intero (la velocità della catena di montaggio).

1. Indica se la linea è in funzione

Definisci production-status in modo che restituisca "stopped" quando la velocità è 0 e "running" per qualsiasi altra velocità:

0 production-status .
! => "stopped"
3 production-status .
! => "running"

2. Calcola il tasso di successo

Definisci success-rate in modo che restituisca la probabilità che un pezzo venga prodotto senza errori:

  • 0: 0.0
  • da 1 a 4: 1.0
  • da 5 a 8: 0.9
  • 9: 0.8
  • 10: 0.77
10 success-rate .
! => 0.77

3. Calcola il tasso di produzione oraria

Definisci production-rate-per-hour in modo che restituisca il tasso di produzione oraria della catena di montaggio, tenendo conto del tasso di successo.

Dovrai prima definire base-speed, la costante 221.

6 production-rate-per-hour .
! => 1193.4

Il valore restituito è un numero in virgola mobile.

4. Calcola il numero di pezzi funzionanti prodotti al minuto

Definisci working-items-per-minute in modo che restituisca quante automobili funzionanti vengono prodotte al minuto. Il risultato è un numero intero: le automobili incomplete non vengono conteggiate.

6 working-items-per-minute .
! => 19
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Factor Exercism

Vuoi iniziare Auto, assemblatevi!?

Iscriviti a Exercism per imparare e padroneggiare Factor con 47 concetti163 esercizi e il mentoring di persone reali, tutto gratis.