Comunidad de diseño web y desarrollo en internet online

[Reto] Programa al amigo secreto

Citar            
MensajeEscrito el 25 Nov 2008 02:36 am
Ok este reto consiste en programar de una manera rapida (la primera solución que se te venga a la cabeza), un programa para para jugar el amigo secreto.

Para quien no conozca el juego, normalmente se escribe el numero de todos los participantes en pequeños papelitos y se sacan los papelitos al azar. asi cada uno tiene que dar un regalo a la persona que le sale. No deberia ni salir uno mismo ni salir repetidos.

(La idea en realidad es que mande un mail informandole a cada persona quien le toco =P)

Este es mi codigo, es PHP (no imporat el lenguaje).

con cronometro en mano, incluyendo el depureo me tomo 7 minutos.

(de preferencia escriban su codigo primero y luego leen el mio =) )
PHP:

Código PHP :

//lista de players.
$players = array(
   'Desy' => '[email protected]',
   'Anto' => '[email protected]',
   'Jorge' => '[email protected]',
   'Leo' => '[email protected]',
   'Mano' => '[email protected]',
   'Fio' => '[email protected]');

$result = array(); //un array con el resultado del sorteo
$players_keys = array_keys($players); //el indice del array no es numerico! U_U

foreach($players as $name => $mail){ //por cada jugador buscamos su amigo secreto
   do{
      $rand = rand(0, (count( $players )-1) ); // sacamos un numero del 0 al numero de participantes.
      $result[$name] = $players_keys[$rand]; // y colocamos el resultado.
   }while(!$players_keys[$rand] || ( $name == $players_keys[$rand] )); //pero si ese amigo ya fue elejido, o es el mismo concursante volvemos a hacer la pirueta

   unset($players_keys[$rand]); // y botamos al concursante elejido.
}

//luego imprimimos.. (esto en realidad es para probar, yo mandaba un email)
foreach ($result as $key => $value){
   echo "A <b>$key</b> le toca <b>$value</b><br/>";
}

?>


Personalmente me parece demasiado cargado mi do while, sobretodo por el rand, supongo que deberia sacar un numero aleatorio de los que estan fuera, pero fue lo primero que se me ocurrio...

Por neohunter

Claber

563 de clabLevel

1 tutorial

 

Bogota, Colombia

firefox
Citar            
MensajeEscrito el 25 Nov 2008 03:16 am
Me quedo gustando esto (optimize mi script) y me di cuenta que hay un caso en el que si al ultimo jugador solo le puede tocar a el mismo a un bucle de la versh! a ver como lo hacen ustedes.

Por neohunter

Claber

563 de clabLevel

1 tutorial

 

Bogota, Colombia

firefox
Citar            
MensajeEscrito el 25 Nov 2008 05:18 am

Código PHP :

$players = array();
array_push($players, array('Desy' => '[email protected]'));
array_push($players, array('Anto' => '[email protected]'));
array_push($players, array('Jorge' => '[email protected]'));
array_push($players, array('Leo' => '[email protected]'));
array_push($players, array('Mano' => '[email protected]')); 
array_push($players, array('Fio' => '[email protected]'));
 

$the_friends = array();
$total = count($players);
for($i=$total-1; $i>=0; $i--)
{
 $prev_friend = $the_friend = array_splice($players,$i,1);
 $the_lover = rand(0,count($players)-1);
 $the_friend[0]['InLoveWith'] = $players[$the_lover];
  array_splice($players,$i,$the_lover);
 array_push($the_friends, $the_friend[0]);
 array_push($players, $prev_friend[0]);
} 
echo "<pre>"; print_r($the_friends); echo "</pre>";

Por Dano

BOFH

4273 de clabLevel

14 tutoriales
4 articulos
10 ejemplos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Lugar estratégico para vigilarte

firefox
Citar            
MensajeEscrito el 25 Nov 2008 05:22 am

Código PHP :

<?php

$players = array
                ( 
                  'Desy' => '[email protected]', 
                  'Anto' => '[email protected]', 
                  'Jorge' => '[email protected]', 
                  'Leo' => '[email protected]', 
                  'Mano' => '[email protected]', 
                  'Fio' => '[email protected]'
                );

$dan = array_fill_keys(array_keys($players), '');
$reciben = $dan;

$results;

foreach($dan as $da => $emptyValue)
{
   $isset = isset($reciben[$da]);
   if($isset)
   {
      unset($reciben[$da]);
   }
   
   $recibe = array_rand($reciben);
   
   $results[$da] = $recibe;
   
   unset($reciben[$recibe]);
   
   if($isset)
   {
      $reciben[$da] = '';
   }
}

print_r($players);

print_r($results);

?>



lol...

esta fue la primera solución que se me ocurrió, pero me da el mismo error que a ti, solo que al final no me da un bucle sino que simplemente el ultimo se queda sin regalos XD

habría que hacer algo al respecto pero ya se ensucia mi solución y paso de ella XD

mañana lo veo ^^

y conste que lo hice por mi mania de resolver cosas =(

Por Duilio

Claber

2590 de clabLevel

25 tutoriales
1 articulo

Genero:Masculino   Premio_Secretos

Venezuela

firefox
Citar            
MensajeEscrito el 25 Nov 2008 07:30 am
Gracias a un MP de Duilio, me dí cuenta de un error en mi código, lo mejor que se me ocurrio fue crear un utilería para ordenar de forma aleatoria y sin repetir posiciones, array_rand no servía porque puede dejar un elemento en su posición actual:

Código :

function getRandomList($total)
{
   $elem = array();
   for($i=0; $i<$total; $i++)
   {
      do
      {
         $new_elem = rand(0,$total-1);
         if($new_elem == $i && $i == $total -1)
         {
            $new_elem = $elem[$i-1];
            $elem[$i-1] = $i;
         }
      }while(in_array($new_elem, $elem) || $new_elem == $i);
     array_push($elem,$new_elem);
   }
   return $elem;
}

$players = array(); 
array_push($players, array('Desy' => '[email protected]')); 
array_push($players, array('Anto' => '[email protected]')); 
array_push($players, array('Jorge' => '[email protected]')); 
array_push($players, array('Leo' => '[email protected]')); 
array_push($players, array('Mano' => '[email protected]'));  
array_push($players, array('Fio' => '[email protected]')); 
  

  
$the_friends = getRandomList(count($players)); 
$players_rel = $players;
$total = count($players); 
for($i=0; $i<$total; $i++) 
{ 
  $players_rel[$i]['InLoveWith'] = $players[ $the_friends[$i] ]; 
}  
echo "<pre>"; print_r($players_rel); echo "</pre>";

Por Dano

BOFH

4273 de clabLevel

14 tutoriales
4 articulos
10 ejemplos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Lugar estratégico para vigilarte

firefox
Citar            
MensajeEscrito el 25 Nov 2008 08:15 am
No lo he "testeado" pero mi cerebro me indica que debe funcionar y que es una solución brillante

Además que queda la library :)

Claro, al no dejar elementos en la misma posición evita que alguien se obsequie a si mismo..

Sólo quedaría intentar conseguir otra solución u optimizar esta... o...

dormir :zzz:


me voy por la c


exit();

Por Duilio

Claber

2590 de clabLevel

25 tutoriales
1 articulo

Genero:Masculino   Premio_Secretos

Venezuela

firefox
Citar            
MensajeEscrito el 25 Nov 2008 01:53 pm
errrr ¿de que me sirve un programa para elegir el amigo secreto sin una DB de usuarios ???
ahora no tengo tiempo de hacer el ejemplo, pero debieran haber 2 tablas principalmente:

  1. user
  2. user2user

Por Inyaka

Claber

3176 de clabLevel

9 tutoriales
2 articulos

Genero:Masculino   Desarrollador de GAIA

Programador y fotógrafo

firefox
Citar            
MensajeEscrito el 25 Nov 2008 03:05 pm
En tal caso, creo que 1 sola tabla porque cada quien le da a una sola persona :P

Pero teniendo el algoritmo, puedes meterla en bd, xml, enviarla por email, imprimirla en pdf,... :P

Por Duilio

Claber

2590 de clabLevel

25 tutoriales
1 articulo

Genero:Masculino   Premio_Secretos

Venezuela

firefox
Citar            
MensajeEscrito el 25 Nov 2008 03:39 pm
1 tabla para guardar los usuarios y otra para guardar las relaciones

Por Inyaka

Claber

3176 de clabLevel

9 tutoriales
2 articulos

Genero:Masculino   Desarrollador de GAIA

Programador y fotógrafo

firefox
Citar            
MensajeEscrito el 25 Nov 2008 04:57 pm
eso es indiferente.

Por neohunter

Claber

563 de clabLevel

1 tutorial

 

Bogota, Colombia

firefox
Citar            
MensajeEscrito el 25 Nov 2008 07:20 pm
¿en serio?

Código :

SELECT 
 us.user,
(SELECT RAND(u.user) FROM user u WHERE u.user != us.user)
FROM user us 
LEFT JOIN user2user u2u
ON u2u.user = us.user_id
WHERE u2u.user IS NULL

Por Inyaka

Claber

3176 de clabLevel

9 tutoriales
2 articulos

Genero:Masculino   Desarrollador de GAIA

Programador y fotógrafo

firefox
Citar            
MensajeEscrito el 25 Nov 2008 07:54 pm

Inyaka escribió:

¿en serio?

Código :

SELECT 
 us.user,
(SELECT RAND(u.user) FROM user u WHERE u.user != us.user)
FROM user us 
LEFT JOIN user2user u2u
ON u2u.user = us.user_id
WHERE u2u.user IS NULL

El problema con ese algoritmo Inyaka, es que te puede asignar varias veces el mismo usuario y otros se quedarían sin regalos.

Por ejemplo Si tenemos a Juan, Duilio, Dolis y Alfonso, a Juan le podrían regalar Duilio y Dolis, y Alfonso quedarse sin regalos. :wink:

Por Dano

BOFH

4273 de clabLevel

14 tutoriales
4 articulos
10 ejemplos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Lugar estratégico para vigilarte

firefox
Citar            
MensajeEscrito el 25 Nov 2008 09:57 pm
lo que decia es que es indiferente cual sea la fuente de los datos, pero estaria muy bien ver un codigo en mysql que lo haga solo, a ver inyanka, quedas desafiado!

Por neohunter

Claber

563 de clabLevel

1 tutorial

 

Bogota, Colombia

firefox
Citar            
MensajeEscrito el 26 Nov 2008 06:00 am
A la utilería le hice un par de cambios y mejoró considerablemente la velocidad. Con la optimización que le hice, la utilería reordena de forma aleatoria a 4,000 números, en tan solo 1.7 segundos, sin repetición de posición, ni margen de error. Antes de optimizarla tomaba 2.7 segundos en reordenar los mismos 4,000 números. Ganamos un segundo. ^^

Código PHP :

function getRandomList($total)
{
   $options = range(0,$total-1);
   $elem = array();
   for($i=0; $i<$total; $i++)
   {
      do
      {
         $pos = rand(0,count($options)-1);
         $new_elem = $options[ $pos ];
         if($new_elem == $i && $i == $total -1)
         {
            $new_elem = $elem[$i-1];
            $elem[$i-1] = $i;
         }
      }while(in_array($new_elem, $elem) || $new_elem == $i);
     array_push($elem,$new_elem);
     array_splice($options, $pos,1);
   }
   return $elem;
}
      $mtime = microtime();
      $mtime = explode(" ",$mtime);
      $mtime = $mtime[1] + $mtime[0];
      $StartTime = $mtime;    
$list = getRandomList(4000);
      $mtime = microtime();
      $mtime = explode(" ",$mtime);
      $mtime = $mtime[1] + $mtime[0];
      $EndTime = $mtime;
      $TotalTime = ($EndTime - $StartTime);      
      echo $TotalTime;
echo "<pre>";print_r($list);echo "</pre>";


Nota de BOFH: Los campeones usan etiquetas [php] paa colorear código.

Por Dano

BOFH

4273 de clabLevel

14 tutoriales
4 articulos
10 ejemplos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Lugar estratégico para vigilarte

firefox
Citar            
MensajeEscrito el 27 Nov 2008 05:31 am
Y si hacemos que una persona no le pueda obsequiar a la persona de la cual recibe regalos?

ej:

A -> B
B -> A
C -> D
D -> C

estaría mal, mientras que


A -> B
B -> D
C -> A
D -> C

estaría bien

Por Duilio

Claber

2590 de clabLevel

25 tutoriales
1 articulo

Genero:Masculino   Premio_Secretos

Venezuela

firefox
Citar            
MensajeEscrito el 27 Nov 2008 07:19 am

Dano escribió:

Nota de BOFH: Los campeones usan etiquetas [php] paa colorear código.


Los bicampeones agregan al editor RTF un botón "PHP Code". U_U


En set.js solo agrega esto:
{name:'Php Code', openWith:'[php]', closeWith:'[/php]'},
Y en la carpeta de imágenes un ícono llamada php.png y listo. Así clab estará lleno de puros campeones. ^^

------------------------------------

Si se puede eso que dices Duilio, no es tan complejo, pero ahora hazlo tu, yo hoy use mi tiempo de ocio en el billar. ^^

Por Dano

BOFH

4273 de clabLevel

14 tutoriales
4 articulos
10 ejemplos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Lugar estratégico para vigilarte

firefox
Citar            
MensajeEscrito el 27 Nov 2008 07:25 am

dano escribió:

Si se puede eso que dices Duilio, no es tan complejo, pero ahora hazlo tu, yo hoy use mi tiempo de ocio en el billar. ^^


Yo en cambiar mi avatar :lol:

luego, luego...

Por Duilio

Claber

2590 de clabLevel

25 tutoriales
1 articulo

Genero:Masculino   Premio_Secretos

Venezuela

firefox

 

Cristalab BabyBlue v4 + V4 © 2011 Cristalab
Powered by ClabEngines v4, HTML5, love and ponies.