Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ATM Coding kata

ATM Machine Kata

El siguiente es un ejercicio para codificar, refactorizar y hacer pruebas, en el cual puedes invertir de 15 a 30 minutos para resolverlo gradualmente.

Antes de que empieces

  • Intenta no adelantar la lectura.
  • Realiza una tarea a la vez. El truco para aprender es el trabajo incremental.
  • Asegurate de hacer las pruebas para las entradas correctas. No hay necesidad de probar entradas inválidas.
  • De vez en cuando haz un refactor de tu código.

¿De qué trata?

Vamos a resolver un problema que muy probablemente ya tiene una solución, y una muy buena (¿qué kata no la tiene?), sin embargo, el propósito es conocer y explorar alternativas en el diseño del algoritmo que despacha los billetes en un ATM.

El propósito final en el diseño de la solución es optimizar la forma en que se pueden atender la mayor cantidad de solicitantes posibles con un flujo de efectivo inicial cargado en el ATM.

Despachar simple con suficiente efectivo

Inicia un ATM con suficiente flujo de efectivo(billetes de una sola denominación) y con un método/función de la forma Collection{int denomination: int quantity} withdraw_cash(int amount). El ATM debería de poder despachar casos simples como los siguientes:

  • Por ejemplo: ATM([200: 10]), significa que el cajero cuenta con $ 2,000 (en efectivo), y cuando llamamos withdraw_cash(800) entonces deberíamos de obtener algo como {200 => 4} ó [200: 4] (dependiendo el lenguaje).
  • Otro caso sería: ATM([100: 1000]), significa que el cajero cuenta con $ 100,000 (en efectivo), y cuando llamamos withdraw_cash(4700) entonces deberíamos de obtener algo como {100 => 47} ó [100: 47].

Despachar con dos denominaciones

Iniciar un ATM con suficiente flujo de efectivo, pero en esta ocasión usa dos denominaciones. Deberías de considerar ahora lo siguiente:

  • Un nuevo ATM([100: 10, 200: 10]), quiere decir que el cajero cuenta con $3,000, y si llamas withdraw_cash(800) entonces deberías de obtener {200 => 4}, llamando withdraw_cash(900) entonces obtendrías {200 => 4, 100 => 1}.
  • Otro caso sería: ATM([200: 300, 500: 100]), quiere decir que el cajero cuenta con $110,000, y si llamas withdraw_cash(4200) entonces deberías de obtener {200 => 1, 500 => 8}; llamando withdraw_cash(3800) entonces obtendrías {200 => 4, 500 => 6}.

Adicional

  • Un nuevo ATM([100: 10, 200: 10]), quiere decir que el cajero cuenta con $3,000, y si llamas withdraw_cash(2400) entonces deberías de obtener {200 => 10, 100 => 4}, llamando withdraw_cash(2600) entonces obtendrías {200 => 10, 100 => 6}.

El ATM no puede despachar

Iniciar un ATM con cierto flujo de efectivo, tal que la solicitud sobrepase lo que contiene, envíe un error indicando "ATM con fondos insuficientes".

  • Un ejemplo es ATM([100: 10, 200: 10]), quiere decir que el cajero cuenta con $3,000, y llamando withdraw_cash(3100) deberíamos de obtener un error.

El ATM no puede atender la combinación solicitada.

Iniciar un cajero con efectivo suficiente, sin embargo, las denominaciones contenidas no pueden despachar la cantidad requerida, es decir, no es que el cajero no tenga los fondos, más bien, no es capaz de atender la combinación de billetes, y por lo tanto, debe de enviar un mensaje indicando que denominaciones tiene para poder retirar.

  • Un 'ATM(200: 10)' tiene $2,000 en efectivo, y al llamar withdraw_cash(700) debe de enviar un error indicando: "No puedo atender tu solicitud, sólo cuento con denominaciones de $200"
  • Un 'ATM(500: 300)' tiene 150,000 en efectivo, y al llamar withdraw_cash(4700) debe de enviar un error indicando: "No puedo atender tu solicitud, sólo cuento con denominaciones de $500"

Caso adicional

  • Un 'ATM(500: 300, 200:2)' tiene 150,400 en efectivo, y al llamar withdraw_cash(4600) debe de enviar un error indicando: "No puedo atender tu solicitud, sólo cuento con denominaciones de $500, $200"

Billetes y saldo en el ATM

Iniciar un cajero con efectivo suficiente, llamar múltiples veces a withdraw_cash(_); al final corroborar que la cantidad de billetes en el ATM ha disminuido. Para esto se puede exponer una función/método adicional get_current_state que exponga el estado interno del ATM.

  • Por ejemplo: ATM([200: 30, 500: 10]), contamos inicialmente con $11,000, haciendo las siguientes llamadas:

    • withdraw_cash(700), entrega 1 billete de $500 y 1 de $200
    • withdraw_cash(3000), entrega 6 billetes de $500
    • withdraw_cash(1400), entrega 2 billetes de $500 y 2 de $200
    • get_current_state, debería de indicar algo como: {200 => 27, 500 => 1}
  • Otro caso sería: ATM([200: 30, 500: 10]), cuenta con $11,000, y haciendo las siguientes llamadas:

    • withdraw_cash(6000), entrega 10 billete de $500 y 5 de $200
    • withdraw_cash(3000), entrega 15 billetes de $200
    • withdraw_cash(1400), entrega 7 billetes de $200
    • get_current_state, debería de indicar algo como: {200 => 3, 500 => 0}

Agregar....

3 ó más denominaciones

Aplicar comisión por transacción (Mocks)

No hay fondos en la cuenta (Error)

Mejores Combinaciones y probabilidades(probailidad de un billete) para atender a la mayor cantidad de clientes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment