Resolviendo el #TuentiContest: Problema 13 – The other clock

Esta vez, el reloj ha vuelto. En el problema 13 empezamos a economizar leds. Nos piden exactamente lo mismo que antes pero aclarando que ahora tenemos un reloj “más ecológico”. La solución está en C++ y no es más que una modificación al reloj anterior. Recuerda que también tengo publicadas mis soluciones a los otros problemas del evento. Este problema sirvió para darme cuenta que había cometido un error en el problema 6. Aparte de eso, no aporta mucho para analizar, así que será una entrada más bien corta.

Análisis del problema

Nos piden calcular cuántas luces se encienden luego de un tiempo determinado. La diferencia con el problema anterior es que los leds no se apagan todos cada vez que pasa un segundo, sino que ahora solo se apagan los leds necesarios. ¿Qué significa esta diferencia? Que ahora nuestro arreglo de leds cambia. Un poco de lápiz y papel nos ayuda de nuevo a empezar: Del 0 al 9 la cantidad de luces que cambian son, respectivamente: 1,0,4,1,1,2,1,1,4,0. Sin embargo, nos falta agregar unos detalles más. La cantidad de luces que encienden en el cero dependen de la cifra anterior. Así, pasar del 9 al 0 es 1 (las unidades), del 5 al 0 es 2 (cuando se cumple un nuevo minuto o una nueva hora) y del 2 ó el 3 al 0 también es 2 (cuando cambiamos de día). Por últimos podemos considerar el encendido del reloj (todos los leds a 0 en el primer instante) como un caso especial que solo ocurre una vez, y asignarle directamente 36. Solución enviada Si para el reloj anterior me dio pereza calcular la fórmula para tener la respuesta en tiempo constante, imagina en este con el código un 90% listo. Lo que hice fue simplemente crear los arreglos adicionales en función de los límites de las casillas ([0,2], [0,5] y [0,9]) y considerar el primer instante como un caso especial.

#include <iostream>
using namespace std;

int main() {
  int seconds; // 110912
  int digitsBDF[10] = {1,0,4,1,1,2,1,1,4,0};
  int digitsACE[6] = {2,0,4,1,1,2};
  while(cin >> seconds) {
    unsigned long result=0;
    bool first = true;
    bool cambiodia = false;
    while(seconds >= 0) {
      for(int a=0;a<3 && seconds>=0;a++){
        result += digitsACE[a];
        for(int b=0;b<10 && seconds>=0;b++){
          if(a==2 && b==4) {cambiodia=true; break;}
          else {
            if(cambiodia) { result += 2; cambiodia=false; }
            else result += digitsBDF[b];
          }
          for(int c=0;c<6 && seconds>=0;c++){
            result += digitsACE1;
            for(int d=0;d<10 && seconds>=0;d++){
              result += digitsBDF[d];
              for(int e=0;e<6 && seconds>=0;e++){
                result += digitsACE[e];
                for(int f=0;f<10 && seconds>=0;f++){
                  result += digitsBDF[f];
                  if(first) result = 36;
                  first = false;
                  seconds--;
                }
              }
            }
          }
        }
      }
    }

    cout << result << endl;
  }
  return 0;
}

Solución mejorada Toda la leña que se podía cortar en el reloj anterior, puede volverse a cortar aquí ¡y más!. Para empezar, los dos arreglos son idénticos con excepción de una posición (precisamente por los cambios a cero). Podría utilizarse uno solo aunque eso involucraría más ifs, con lo que habría más posibilidades de cometer errores (como si ya fueran pocas en este código). Ya he visto varias implementaciones de la solución O(1) del problema 6. Me gustaría ver ahora esta también. Debe ser bastante similar en realidad. Me pregunto si es exactamente la misma, solo que cambiando los valores iniciales. Y tú ¿cómo lo resolviste?

One thought on “Resolviendo el #TuentiContest: Problema 13 – The other clock

Deja un comentario