Rutas
/
Factor
Factor
/
Ejercicios
/
¡Coches, ensamblad!
¡Coches, ensamblad!

¡Coches, ensamblad!

Ejercicio de aprendizaje

Introducción

Este ejercicio presenta los condicionales, es decir, la elección entre dos o más cursos de acción en función de un valor. Se apoya en los booleanos que conociste en La infiltración de Annalyn y en la aritmética con números enteros de Conversión de divisas.

Palabras de comparación

Todas ellas se encuentran en math (y en kernel para =):

=  ( 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? (en math) es una forma abreviada de la prueba habitual 0 =: consume el número y apila si era cero:

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

Comprobaciones de intervalos

between? (en math.order) comprueba si un valor cae dentro de un intervalo inclusivo. Resulta útil cuando una acción depende de la franja en la que cae un número:

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)

A menudo lo verás como predicado de cond (dup 1 4 between?) para elegir una rama por intervalo en lugar de por un único valor.

Quotations

Las palabras de comparación anteriores producen booleanos; para actuar sobre un booleano, le pasas al condicional una o varias quotations. Una quotation es un fragmento de código encerrado entre corchetes, [ ... ]. Al escribirla, se apila el código como un valor en lugar de ejecutarlo, y una palabra como if decide después qué quotation ejecutar.

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

Un ejercicio posterior trata las quotations en detalle; por ahora, lee [ ... ] como «el código que hay que ejecutar para esta rama».

if, when, unless

if (en kernel) recibe un booleano y dos quotations. Ejecuta la primera quotation cuando el booleano es verdadero y la segunda cuando es falso:

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

when ejecuta su quotation solo cuando el booleano es verdadero; unless, solo cuando es falso:

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

if*, when* y unless*

Tres variantes de kernel tratan el booleano como un valor que merece conservarse cuando es verdadero, algo útil cuando una palabra devuelve «la cosa, o 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* es la forma de dos ramas. La rama verdadera se llama con el valor todavía en la pila; la rama falsa se llama sin él:

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

unless* es el modismo canónico de «valor o predeterminado». Si el valor es verdadero, se deja tal cual; si es f, el valor se descarta y la quotation se ejecuta para apilar un sustituto:

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

when* es la forma de una sola rama de if*: ejecuta su quotation (con el valor todavía en la pila) solo cuando el valor es verdadero, y simplemente descarta el valor cuando es f. Úsala para incorporar un resultado de tipo «la cosa, o f» a un valor acumulado sin molestarte en gestionar el caso f:

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

cond

Cuando tienes varias acciones alternativas entre las que elegir, cond (en combinators) es la opción natural. Recibe un array de pares { predicate body } y ejecuta el cuerpo del primer predicado que produzca un valor verdadero:

USING: combinators ;

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

Algunos detalles que conviene tener en cuenta:

  • Los pares se prueban en orden. Gana la primera coincidencia.
  • Una entrada sin predicado (una única quotation) al final actúa como valor predeterminado.
  • Cada predicado inspecciona la entrada, pero debe dejar la pila de datos tal como la encontró; dup ... <test> es el modismo habitual.
  • El cuerpo del par elegido recibe la misma pila que vio el predicado, así que normalmente empieza haciendo drop de la entrada y apilando el resultado.

Instrucciones

En este ejercicio vas a escribir código para analizar la producción de una cadena de montaje en una fábrica de coches. La velocidad de la cadena de montaje puede ir de 0 (apagada) a 10 (máxima).

A su velocidad más baja distinta de cero (1), se producen 221 coches cada hora. La producción aumenta de forma lineal con la velocidad, así que a velocidad 4 la cadena produce 4 * 221 = 884 coches por hora. Sin embargo, las velocidades más altas aumentan la probabilidad de que se produzcan coches defectuosos, que después hay que desechar.

Tienes cuatro tareas. Cada una toma de la pila un único parámetro entero: la velocidad de la cadena de montaje.

1. Indica si la cadena está en marcha

Define production-status para que devuelva "stopped" cuando la velocidad sea 0 y "running" para cualquier otra velocidad:

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

2. Calcula la tasa de éxito

Define success-rate para que devuelva la probabilidad de que un artículo se produzca sin errores:

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

3. Calcula la tasa de producción por hora

Define production-rate-per-hour para que devuelva la tasa de producción por hora de la cadena de montaje, teniendo en cuenta la tasa de éxito.

Primero tendrás que definir base-speed, la constante 221.

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

El valor devuelto es un número de coma flotante.

4. Calcula el número de artículos en buen estado producidos por minuto

Define working-items-per-minute para que devuelva cuántos coches en buen estado se producen por minuto. El resultado es un número entero: los coches incompletos no se cuentan.

6 working-items-per-minute .
! => 19
Editar en GitHub El enlace se abre en una ventana o pestaña nueva
Factor Exercism

¿Listo para empezar ¡Coches, ensamblad!?

Regístrate en Exercism para aprender y dominar Factor con 47 conceptos163 ejercicios y mentoría humana real, todo gratis.