El blog de Juan Palómez

22 octubre 2008

Timoconcurso «cerillas»

Filed under: programming, Uncategorized — Etiquetas: , , , — thisisoneball @ 23:32

Este es un programa en C que resuelve uno de los problemas de los «timoconcursos» de los canales de la TDT. En concreto el que aparece un número de 4 cifras hecho con cerillas y hay que conseguir el número más alto posible moviendo dos cerillas.

Realmente este programa es algo más genérico: se puede especificar el número de cerillas que habría que mover, se pueden hacer con números de cualquier número de cifras, y devuelve todas las soluciones, no sólo el más alto.

Esto es una curiosidad, no es para llamar al programa y tener la solución, porque el timo por lo visto está en que te tienen media hora al teléfono esperando para dar la solución, y eso en el caso de que cojan la llamada.

NO LLAMES AL TIMOCONCURSO.

#define	TRUE	1
#define	FALSE	0
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

/*	tipo de datos "segmentos":
		vector de 7 shorts, almacena un dígito en forma de segmentos, de la siguiente forma:
			|-0-|
			1   2
			|-3-|
			4   5
			|-6-|
		por ejemplo el 0 se almacenaría como:
			segmentos numero0 = {1,1,1,0,1,1,1};

	conjuntos de segmentos:
		permiten almacenar un número completo compuesto de varios dígitos, por ejemplo para almacenar números de 4 dígitos:
			segmentos numero[4];
		para hacer lo mismo en tiempo de ejecución:
			segmentos *numero;
			numero = (segmentos *) calloc(4, sizeof(segmentos));
*/
typedef short segmentos[7];

//	especificación de los dígitos del 0 al 9 en forma de segmentos (vector de 10x7 shorts)
segmentos digitos[10] = {
	{1,1,1,0,1,1,1},
	{0,0,1,0,0,1,0},
	{1,0,1,1,1,0,1},
	{1,0,1,1,0,1,1},
	{0,1,1,1,0,1,0},
	{1,1,0,1,0,1,1},
	{1,1,0,1,1,1,1},
	{1,0,1,0,0,1,0},
	{1,1,1,1,1,1,1},
	{1,1,1,1,0,1,1}
};

//	copia los 7 segmentos de un dígito
void CopiarSegmentos(segmentos destino, segmentos origen)
{
	memcpy(destino, origen, 7 * sizeof(destino[0]));
}

//	transforma un entero "origen" a un vector de segmentos "destino" (no un solo dígito sino un número completo compuesto de "tam" dígitos)
void IntSegmento(segmentos *destino, int origen, int tam)
{
	while (tam >= 1) {
		tam--;
		CopiarSegmentos(destino[tam], digitos[origen % 10]);
		origen = origen / 10;
	}
}

/*	compara dos números de "tam" dígitos
	devuelve TRUE si entre los dos se han movido "ndiferencias" segmentos
*/
int CompararSegmentos(segmentos *origen, segmentos *destino, int tam, int ndiferencias)
{
	int i;
	int diferencias = 0, total = 0;

	for (i=0; i < tam*7; i++) {
		total += (*origen)[i] - (*destino)[i];
		if ((*origen)[i] != (*destino)[i])
			diferencias++;
	}

	// total es la diferencia en el total de segmentos, y debe ser 0 (mismo nº de cerillas en los dos casos)
	// diferencias es el total de segmentos cambiados (es el doble del nº de cerillas movidas)
	if (diferencias == ndiferencias*2 && total == 0)
		return TRUE;
	else
		return FALSE;
}

/*	parámetros del programa: el número inicial y el número de cerillas que hay que mover

	retorno:
		0	sin errores
		1	error en el número de parámetros pasados
		2	error en el formato de los parámetros
*/
int main(int argc, char *argv[])
{
	int inicial, ndiferencias, tam; segmentos *s_inicial;
	int candidato; segmentos *s_candidato;

	// gestión de parámetros de entrada
	if (argc != 3) {
		fprintf(stderr, "Uso: %s\nEjemplo: %s 5912 2\n", argv[0], argv[0]);
		return 1;
	}

	inicial = atoi(argv[1]);		// ej: 5912
	ndiferencias = atoi(argv[2]);		// ej: 2
	if (inicial == 0 || ndiferencias == 0) {
		fprintf(stderr, "Los parámetros tienen que ser numéricos y distintos de 0\nEjemplo: %s 5912 2\n", argv[0]);
		return 2;
	}

	tam = strlen(argv[1]);			// ej: 4
	candidato = (int) pow(10,tam) - 1;	// ej: 9999

	s_inicial = (segmentos *) calloc(tam, sizeof(segmentos));
	s_candidato = (segmentos *) calloc(tam, sizeof(segmentos));

	// pasar el nº inicial a segmentos y comparar con cada nº candidato decrecientemente
	IntSegmento(s_inicial, inicial, tam);
	while (candidato >= 0) {
		IntSegmento(s_candidato, candidato, tam);
		if (CompararSegmentos(s_inicial, s_candidato, tam, ndiferencias))
			printf("%d\n", candidato);
		candidato--;
	}

	return 0;
}

19 comentarios »

  1. Hola,

    Me dio por probar el programa y hay algo incorrecto, ten en cuenta que de un 4 en forma de cerillas puedes sacar dos unos ( | | ).

    Teniendo esto en cuenta, de 6485 moviendo 2 cerillas se puede formar 61185, pero la cifra más alta que el programa encuentra es 9499.

    ¿Como se podría hacer para que lo calculase de la forma correcta?

    Saludos!

    Comentarios por RedStripes — 13 enero 2009 @ 05:02

  2. PD: De 6485 moviendo 1 cerilla se puede formar 61185 quería decir.

    Comentarios por RedStripes — 13 enero 2009 @ 05:02

  3. Muy agudo… fijo que en el programa utilizan eso para dar la respuesta como incorrecta.

    Tengo que mirarlo pero parece bastante difícil, cambia mucho la forma de generar los números de esa manera. Posiblemente haya que hacer reglas específicas para cada caso como ese que me comentas.

    Comentarios por thisisoneball — 13 enero 2009 @ 11:32

  4. Y si fuera solo eso, otro «truco» de los teletimos es utilizar números romanos en la posible solución o incluso elevar un número a una potencia, por ejemplo:

    Tenemos el número 6485, moviendo las 2 cerillas de la parte superior del 6 y colocándolas debajo formando un 9, quedaría 9^485.

    Comentarios por RedStripes — 13 enero 2009 @ 17:00

  5. Ayer tuve este programa puesto mientras trasteaba por internet y creo que dieron como valido un resultado no correcto, aunque despues del mareo de hora y pico no se si me entere muy bien. Con el numero 6485 habia que construir el mayor posible moviendo 2 cerillas, gano un tio que dio como cifra 91199

    Comentarios por charli — 14 enero 2009 @ 02:28

  6. En ese caso tiene que ser lo que ha dicho RedStripes, el 4 lo habran pasado a 11 moviendo 1 cerilla.
    Con otra cerilla transformas el 6 inicial en un 9, y con otra transformas el 85 en 99.
    A mi me salen 3 cerillas movidas.

    De todas formas el programa esa solucion tambien te la daria incorrecta aunque le pases 3 como segundo parámetro, porque no tiene en cuenta lo de 4 -> 11.

    Comentarios por thisisoneball — 15 enero 2009 @ 17:04

  7. Es 99119.

    el 6485 hay que voltearlo del reves, entonces con el palo del 8 puedes convertir el 5 volteado en un 9 , i dejas el 8 convertido en 9.

    luego conviertes el 4 a 11 moviendo un palo, i queda el 6 volteado como ultimo numero.

    asi que obtenemos 99119

    Comentarios por eimo — 27 enero 2009 @ 04:43

  8. Esto es una estafa, yo lo tenia puesto hasta ahora que acaban de dar la solución y no consigo entenderlo, a ver si la sacais.

    El número era el 8017 y el resultado que les da es 500502.

    Comentarios por masm — 8 septiembre 2009 @ 05:06

    • Les paso la solucion, a pesar que han pasado varios años: Sacas el palito del medio del ocho, y lo pones horizontalmente encima. Luego sacas el palito horizontal del 7 final, y lo pones nuevamente de forma horizontal encima del primer palito que moviste. Ahora tienes que leerlo en numeros romanos. El primer numero te quedó como un 0, que al ser cuadrado hay que interpretarlo como la D. al tener 2 palitos horizontales encima, por cada uno se multiplica por 1000. Luego tienes otra D, y luego I y I.

      Comentarios por Lastor — 8 julio 2016 @ 23:45

  9. Yo habia llegado al 91011, pero no se de donde se pueden sacar 500502 solo moviendo dos cerillas del número 8017

    Comentarios por masm — 8 septiembre 2009 @ 05:08

  10. HOLA CUAL OS SALE DEL NUMERO,2185 POR QUE EL MAS ALTO A MI ME SALE 21135.GRACIAS

    Comentarios por MONTSE — 12 enero 2010 @ 20:41

  11. Y como activas el programa? no lo entendí, quiero hacer la prueba con el nñumero 1939. Que conocimientos debo tener para usarlo o activarlo, es un scrip? gracias

    Comentarios por sebaenvivo — 31 julio 2010 @ 06:42

  12. Debes grabarlo en un fichero .c y compilarlo. Necesitas conocimientos de lenguaje C.
    De todas formas lo calculo yo en mi ordenador: del 1939 moviendo dos cerillas puedes llegar al 7994

    Comentarios por thisisoneball — 19 agosto 2010 @ 16:34

  13. quiero saber el numero maximo que se puede sacar con el numero. 3421, yo digo que es 91121 moviendo el 4 a 11 y el tres a 9. ayudar si se puede

    Comentarios por alejo — 30 agosto 2010 @ 06:47

  14. me podrías decir cual es el numero mas alto moviendo dos cerillas del 3421?

    gracias!

    Comentarios por martin — 31 agosto 2010 @ 05:55

  15. Con el Numero 3421 cual seria el mas grande? porque el que se me ocurrio es 91121 pero era incorrecto :S

    Comentarios por Lisandro — 31 agosto 2010 @ 07:33

  16. yo tengo oro numero si me pueden resolver.. trate con varios pero ninguno es…! a ver si uds me lo pueden sacar…!

    el numero es 3421 y hay qe formar el mayor posible moviendo dos cerillas…!

    Comentarios por Matias — 1 septiembre 2010 @ 06:48

  17. ME CALCULAS EL 3421….YO NO PUEDO SACAR MAS DE 91121.
    GRACIAS

    Comentarios por CELESTE — 2 septiembre 2010 @ 18:33

  18. cual es el mayor numero que puedes obtener de 4568

    Comentarios por MAXIMILIANO (@MAX_CHILE) — 15 septiembre 2011 @ 06:04


RSS feed for comments on this post. TrackBack URI

Crea un blog o un sitio web gratuitos con WordPress.com.