CUPCAM 05

LOc0

Hola. Para los que no sepan qué es, se trata de un concurso de programación universitario que organiza la Comunidad de Madrid. La edición de este año ya ha terminado y como en las anteriores, han colgado en la página los enunciados de los 8 problemas propuestos (los ganadores "sólo" consiguieron sacar 5). Se trata de problemas complejos (en inglés) que podían resolver usando C, C++, Java o Pascal (se dejaban libros y manuales como material de consulta). El tiempo total era de 5 horas (aunque por lo visto se amplió).

Los enunciados:

Problema 1 Solitary Domino -> http://www.fdi.ucm.es/cupcam/Prob1.pdf SOLUCIONADO (by me el 6-6-05 con C)->http://personales.ya.com/tonilope/domino.zip

Problema 2 Visible Squares-> http://www.fdi.ucm.es/cupcam/Prob2.pdf SOLUCIONADO (Algoritmo planteado SIN codificar) (by Alco el 15-6-05)

Problema 3 The Biggest House->http://www.fdi.ucm.es/cupcam/Prob3.pdf SOLUCIONADO (by kaoD2 el 23-6-05 con C++)-> http://usuarios.lycos.es/clanics/house.zip

Problema 4 Biased Robot->http://www.fdi.ucm.es/cupcam/Prob4.pdf

Problema 5 Equivalent Programs->http://www.fdi.ucm.es/cupcam/Prob5.pdf

Problema 6 Pentagrams->http://www.fdi.ucm.es/cupcam/Prob6.pdf

Problema 7 Treasure Hunt->http://www.fdi.ucm.es/cupcam/Prob7.pdf

Problema 8 Subexpressions->http://www.fdi.ucm.es/cupcam/Prob8.pdf
SOLUCIONADO (by Soy_Heaton el 14-6-05 con PERL)

Lo que yo propongo, ya sin tiempo (ni por supuesto premios ;) ), es que a modo de reto personal (y/o colectivo), intentemos entre la gente del Foro de Desarrollo resolver el mayor número de problemas y de paso aprender cosas nuevas. ¿Qué os parece?

Salu2 ;)

guiye

Superapasionante

LOc0

Tenemos un "súperapasionante" de #2, ¿alguien da más señores?

Salu2 ;)

Whose

¿Te refieres a resolver problemas que nosotros propongamos o los expuestos en el post?

maRc

Estaría bien, pero ahora mismo muchos estamos de exámenes :)

LOc0

Y yo (mañana empiezo). Esto no es algo con fecha de entrega ni nada por el estilo. Los enunciados están ahí para cuando haya un rato libre.

Salu2 ;)

PD: ¿Te refieres a resolver problemas que nosotros propongamos o los expuestos en el post?

Para empezar creo que tendremos entretenimiento d sobra con esos xD.

Kansei

pues tambien me apunto al carro, ya veremos cuantos hago.... :P

por cierto no sería mala idea como dicen por ahí arriba utilizar este thread para poner retos de programación por que me consta que hay bastante nivel de programadores por aqui.

editado:
creo que deberiamos de poner un lenguaje comun para todos, ¿que os parece java?

Hannibax

Yo fui representando a la carlos III que por cierto somos lo puto peor.... ¬¬ siempre suele ganar, alcala, o la complu jejej Nosotros el mejor año creo que fuimos 5 o algo asi o 9 este año no estoy seguro.

Lo de resolver los problemas no esta mal... pero es que es muy facil despues de que se hayan publicado las soluciones. Yo propongo que la gente proponga problemas practicas que ha tenido que hacer y que los demas los resuelvan.

El primero, tomaros vuestro tiempo que los examenes estan aqui encima.

Conoceis el juego Rush-Hour??

http://www.g5.dk/bilspil/cargame.asp

Lo que teneis que hacer es un programa que pasandole un problema del Rush-Hour lo resuelva de forma automatica, el problema lo podeis introducir desde teclado o pasarselo por fichero, y para resolverlo lo puede por medio de BackTracking o por heuristica como querais.

Esto ha sido una parte de mi practica fin de asignatura de programacion en java.

PD: Lo del lenguaje comun no me parece bien del todo por que no todos tenemos que saber los mismos lenguajes o ni siquiera que nos gusten los mismos. (a mi que fuese java me vendria de perlas :D:D:D pero habra gente que no lo sepa y lo odie... y prefiera hacerlo en C o en su puta madre.)

Maca

me parece bien cuando tenga un ratillo me pongo con el primero.

LOc0

Lo de resolver los problemas no esta mal... pero es que es muy facil despues de que se hayan publicado las soluciones. Yo propongo que la gente proponga problemas practicas que ha tenido que hacer y que los demas los resuelvan.

Hombre, la gracia está en no mirar las soluciones ;). Yo sólo he podido dedicarle una horilla hace dos días al del dominó, y salvando el tema de la memoria RAM que chuparía, tengo ya un algoritmillo en papel. A lo mejor esta tarde (para desconectar del examen de esta mañana) subo algo.

Salu2 ;)

PD: Al que le parezcan sencillos esos problemas o ya ls haya hecho, pues que plantee otros. La idea de esto es APRENDER (quizás más de algoritmia que de programación pura y dura...)

Hannibax

No te preocupes por la RAM no chupa nada.. amos no se como sera tu algoritmo, nosotros lo intentamos en la CUPCAM con teoria de grafos y es como ellos lo resolvieron despues.

Como es tu algoritmo mas o menos??? por que chupa tanta ram? proboca desbordamiento de la pila??? Las pruebas que pasaban ally eran de 6 fichas como mucho creo recordar y aunq lo hagas con algoritmos recursivos no deberia producir Stack Overflow.

PD: Estudias informatica no? en que curso y uni?

LOc0

Pues todavía no lo tengo terminado. Lo que pensaba hacer es usar un algoritmo para generar las {1, 2, 3,...,n} permutaciones en orden lexicográfico de las piezas dadas e ir comprobando hasta dar con una válida (según las reglas del dominó). El problema de este sistema es que intuyo que será muy lento para valores elevados de n. ( P(n, n)=n! ).

Salu2 ;)

PD: Al principio temía por la memoria porque pensaba almacenar todas las permutaciones, pero enseguida me he dado cuenta de que es una tontería. Simplemente tengo que ir generando una a una y en el peor de los casos serán n! permutaciones...

LOc0

Aquí tenéis --> www.elcopias.com/domino.zip

#include <stdio.h>
#include <conio.h>

typedef struct ficha{

int laficha[2];

}
FICHA;

int crea_permutacion(int[], long double, int, long double);

void crea_jugada(int[], FICHA[], int[], int);

int comprueba_jugada(int[], int);

long double factorial(int);

int main(){

int n, k, p;
long double contador, fact_n;

printf("\n\t\t\t- SOLITARY DOMINO (by LoC0) -");

printf("\n\n\n\tIntroduce el numero de fichas:   ");
scanf("%d", &n);



FICHA fichas[n];
int permutacion[n];
int jugada[2*n], jugada_correcta, quedan_permutaciones;




for(k=0; k<n; k++)
{
	do{
		system("cls");
		printf("\n\t\t\t- SOLITARY DOMINO (by LoC0) -");
		printf("\n\n\n-Introduce el elemento (1) de la [ficha %d]: ", k+1);
		scanf("%d", &fichas[k].laficha[0]);

	}
	while(fichas[k].laficha[0]<0 || fichas[k].laficha[0]>6);

	do{
		system("cls");
		printf("\n\t\t\t- SOLITARY DOMINO (by LoC0) -");
		printf("\n\n\n-Introduce el elemento (2) de la [ficha %d]: ", k+1);
		scanf("%d", &fichas[k].laficha[1]);
	}
	while(fichas[k].laficha[1]<0 || fichas[k].laficha[1]>6);


}

for(k=0; k<n; k++)
	printf("\n\t%d %d", fichas[k].laficha[0], fichas[k].laficha[1]);




fact_n=factorial(n);

jugada_correcta=0;
quedan_permutaciones=1;
contador=0;

printf("\n\n\n\tEchando unas cuentecillas, por favor espere...");

while(quedan_permutaciones && !jugada_correcta)
	{

	quedan_permutaciones = crea_permutacion(permutacion, contador, n, fact_n);

	crea_jugada(permutacion, fichas, jugada, n);

	jugada_correcta = comprueba_jugada(jugada, n);

	contador++;

    }

if(jugada_correcta)		printf("\n\n\n\tSI, hay al menos una jugada posible con esas piezas");
else
    printf("\n\n\n\tNO, no se puede hacer ninguna jugada válida con esas piezas");


getch();

}

int crea_permutacion(int permutacion[], long double contador, int n, long double fact_n){
int valido=1, j, k, r, s, aux;

if(contador<=fact_n)
	{
		if(contador==0)
		{

			for(k=0; k<n; k++)
				permutacion[k]=k+1;
		}
		else
	    {
			j=n-1;

			while(permutacion[j-1]>permutacion[j])
				j--;

			k=n;

			while(permutacion[j-1]>permutacion[k-1])
				k--;

			aux=permutacion[j-1];
			permutacion[j-1]=permutacion[k-1];
			permutacion[k-1]=aux;

			r=n;
			s=j+1;

			while(r>s)    {
				aux=permutacion[r-1];
				permutacion[r-1]=permutacion[s-1];
				permutacion[s-1]=aux;

				r--;
				s++;

			}
		}

}
else
	valido=0;

return valido;

}

void crea_jugada(int permutacion[], FICHA fichas[], int jugada[], int n){

int h, c;

for(h=0, c=0; c<n; h=h+2, c++)
{
	jugada[h]=fichas[permutacion[c]-1].laficha[0];
	jugada[h+1]=fichas[permutacion[c]-1].laficha[1];

}

}

int comprueba_jugada(int jugada[], int n){
int valido=1, j, h;

j=0;
h=0;
while(j<n-1 && valido)    {
	if(jugada[h+1]!=jugada[h+2])                valido=0;

	j++;
	h=h+2;
}

return valido;

}

long double factorial(int numero){
long double res;

if(numero==0)        res = 1;
else
	res = numero*factorial(numero-1);

return res;

}

En resumen lo que hace el programa es ir generando permutaciones de fichas hasta que da con una judada correcta o hasta que haya probado las n! permutaciones.

Ej: Si se introducen las fichas 6-6, 6-5 y 1-6 por ejemplo, iría probando: 6-6 6-5 1-6, 6-5 1-6 6-6, etc... hasta dar con una jugada válida como: 1-6 6-6 6-5

Salu2 ;)

Hannibax

No se anima nadie mas a intentar algun problema, o proponer otros para que los intentemos.

Alguien ha intentado el que puse yo?? el del Rush-Hour?

Loco tu lo habras intentado no? mas que nada por que tendras la misma practica que yo ejejej

Cuando entregue la practica ya pondre como lo he hecho yo... aunq no funciona bien en todos los casos :(

PD: He mirado el del domino de Loco... y funciona bien... pero por que pides el numero de fichas que va a introducir al principio? se supone que hay que leer hasta que no encuentres fichas no? vamos asi lo entiendo yo en el enunciado, lees del teclado hasta que no recibas mas datos.

LOc0

Juas. Este hilo no ha tenido mucho éxito (espero que sea por el tema exámenes...) Yo de momento no he tenido tiempo de intentar ningún otro.

En cuanto al problema 1, la parte de introducir las fichas la he hecho así por comodidad y para que quedara más "bonito", porque realmente tendría que leer (de un fichero o de la entrada de teclado) todo el "tocho" de datos.

En fin, en cuanto termine de faena me pondré con los siguientes y espero que todos esos grandes programadores de media-vida den la cara ;)

Salu2 ;)

GeeK

pena, pero ando de examenes, a ver si termino y les hecho un vistazo

S

Solución al problema 8. Elijo Perl porque me parece absurdo que den a elegir 4 lenguajes que, para estos menesteres, son iguales (de incómodos). La gracia está en saber qué herramienta utilizar :P

#!/usr/bin/perl

while (<STDIN>) {
&nbsp;&nbsp;&nbsp;$cadena = <STDIN>;
&nbsp;&nbsp;&nbsp;chomp; chomp $cadena; quotemeta;
&nbsp;&nbsp;&nbsp;$count = 0;
&nbsp;&nbsp;&nbsp;while ($cadena =~ /$/) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$cadena =~ s/$
//;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$count++;
&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;print "$count\n";
}

LOc0

Elijo Perl porque me parece absurdo que den a elegir 4 lenguajes que, para estos menesteres, son iguales (de incómodos).

Hombre, está claro que si te restringen a esos 4 lenguajes (y sin poder usar librerías "extrañas") es para que crees el algoritmo "desde cero". Para mi es más un concurso de algoritmia que de programación...

Salu2 ;)

S

#18 No es necesaria la orientación a objetos, todos tienen punteros (o referencias), y todos son imperativos. Ninguno destaca respecto a los otros (quizá C por bajo nivel). Para eso que lo dejen en C++ y a correr.

Y si fuera algorítmica habría para elegir lenguajes funcionales y/o lógicos, dejarlo en imperativos es mermar la importancia del ingenio y la elegancia de la solución.

Pero bueno, a mí me da igual con Perl, perlcc te lo traduce a C xD

Para el que tenga curiosidad: http://pastebin.com/299518
PD: No sale entero.

Hannibax

Es que es un concurso de algoritmia... pero lo de las librerias se podian usar todas las que quisieras... las tenias disponibles en los ordenadores... lo unico que no se podia usar eran calculadoras (por que sera??) moviles ni inet, claro esta.

LOc0

No es necesaria la orientación a objetos, todos tienen punteros (o referencias), y todos son imperativos. Ninguno destaca respecto a los otros (quizá C por bajo nivel). Para eso que lo dejen en C++ y a correr.
Yo creo que C a secas sobra xD

Y si fuera algorítmica habría para elegir lenguajes funcionales y/o lógicos, dejarlo en imperativos es mermar la importancia del ingenio.
Estoy de acuerdo ;)

Salu2 ;)

TeTu

L0c0 estudias en la compluntese de Madrid?

maRc

aLc0, yo también estuve mirando el segundo el otro día.

Se me ocurrió hacerlo así: solo tienes que mirar si son visibles dos puntos en alguno de los lados que estén mirando al origen (no se si habrías pensado lo mismo, pero por el dibujo parece que no). Para ver si un punto (x0,y0) es visible, calculas la pendiente de ese punto (m=y0/x0), y recorres todas las posiciones hasta x0, calculando que valor tiene y para cada valor de x, y vas comparando con el resto de cuadrados si esta posición entra dentro de los valores de sus lados (otra vez, solo de los lados miran al origen).

Mañana si me apetece haré algo :P.

Edito: No había leido tu post entero. Es más o menos lo mismo :)

8 días después
K

Bueno, me he puesto con el 3 y creo que podría solucionarlo, eso sí con un algoritmo de lo más cutre y feo (Bucles, brute-forcing... Así que comerá CPU como un perro.) Supongo que habrá mucho mejores, pero sé pocas matemáticas (4º de la ESO >< Asco), y son las 5 de la mañana xD Mañana si saco tiempo lo hago en C o pienso algún algoritmo mejor :) Me contento con solucionarlo.

Y el próximo en Python y así aprendo algo de él, que le tengo ganas :D Animáos a hacerlos en lenguajes no tan comunes, premio para el que lo haga en brainfuck o befunge xD

EDIT : Son las 7 y me he puesto a hacerlo... Hay algún bug y no lo encuentro... Quiero dormir pero no puedo xD

EDIT 2 : No tira mucho de CPU, son pocos cálculos, pero me da el resultado mal :( El código se está empezando a volver feo... Variables con nombres sin sentido, malas colocaciones de las cosas, etc. etc.

EDIT 3 : Ok, bug encontrado... Luego lo arreglo si eso :)

K

Pues me acabo de despertar (Me acaban de despertar) despues de haberme dormido a las 8 y media tras desesperarme con el puto algoritmo... Creí que lo tenía, pero algo falló cruelmente :( Ya veré luego.

EDIT: Soy el amo, arreglado en cinco minutos xD Muchas veces la clave es dormir y despejarse cuando se te pega el código...

Adecento un poco esto y lo subo

EDIT2: http://usuarios.lycos.es/clanics/house.zip (Tienes que entrar primero a http://usuarios.lycos.es/clanics/) Testeado varias veces y funciona al 100%

EDIT3: Nop preguenteis por los bucles var < var2 + 1 xDD ¡¡Y .NET APESTA!!

LOc0

Jejejeje, el 3 lo empecé yo el día que Alco sacó el segundo, con un planteamiento MUy parecido al de Kaod aunque lo deseché porque me parecía demasiado ineficiente (por el tema de probar en todos los puntos todos los posibles rectángulos)... El caso es que he probado el algoritmo de ka0d2 en mi P-II 450 y va muy rápido :)

En fin, como esperaba la comunidad está respondiendo de p.m. (y de manera proporcionada xD) Sólo espero que quede alguno para cuando tenga un ratillo libre...

Salu2 ;)