Tracks
/
Factor
Factor
/
Ejercicios
/
¡Autos, ensamblen!
¡Autos, ensamblen!

¡Autos, ensamblen!

Ejercicio de aprendizaje

Introducción

Este ejercicio presenta los condicionales: elegir entre dos o más alternativas según un valor. Se apoya en los Boolean que viste en Infiltración de Annalyn y en la aritmética con enteros de Conversión de monedas.

Palabras de comparación

Todas estas viven 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 rango

between? (en math.order) comprueba si un valor cae dentro de un rango inclusivo. Es ú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 rango en lugar de por un único valor.

Quotations

Las palabras de comparación anteriores producen Boolean; para actuar sobre un Boolean le entregas al condicional una o más quotations. Una quotation es un fragmento de código entre corchetes, [ ... ]. Escribirla apila el código en la pila como un valor en lugar de ejecutarlo, y luego una palabra como if decide qué quotation ejecutar.

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

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

if, when, unless

if (en kernel) recibe un Boolean y dos quotations. Ejecuta la primera quotation cuando el Boolean 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 Boolean es verdadero; unless, solo cuando es falso:

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

if*, when* y unless*

Tres variantes de kernel tratan el Boolean como un valor que vale la pena conservar cuando es verdadero. Son útiles cuando una palabra devuelve «el valor, 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 la expresión canónica de «el valor o un valor por defecto». Si el valor es verdadero, se deja intacto; 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 del tipo «el valor, o f» a un valor acumulado sin molestarte en manejar 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 vale la pena tener en cuenta:

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

Instrucciones

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

A su velocidad mínima distinta de cero (1), se producen 221 autos cada hora. La producción aumenta de forma lineal con la velocidad, así que a velocidad 4 la línea produce 4 * 221 = 884 autos por hora. Sin embargo, las velocidades más altas aumentan la probabilidad de que se produzcan autos 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 línea de ensamblaje.

1. Indica si la línea está funcionando

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 una unidad 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 línea de ensamblaje, 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 que se devuelve es de punto flotante.

4. Calcula la cantidad de unidades funcionales producidas por minuto

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

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

¿Todo listo para empezar ¡Autos, ensamblen!?

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