Intercambio de regalos navideños

11

Otro problema de nuestro golf interno ... este alrededor de las vacaciones del año pasado.

PROBLEMA

Andy, Barb, Carl, Didi, Earl y Fran están comprando regalos el uno para el otro. Dibuja nombres para un intercambio de regalos.

  1. Cada persona compra un regalo y recibe un regalo.
  2. Nadie compra su propio regalo.
  3. La ejecución de la solución varias veces debería producir resultados diferentes (el par donante-receptor no debe ser predecible o idéntico de una ejecución a otra).

ENTRADA

Ninguna.

SALIDA

Formateado como en este ejemplo:

Andy compra para Barb
Barb compra para Carl
Carl compra para Didi
Didi compra para Earl
Earl compra para Fran
Fran compra para Andy

Steve
fuente
¿Se debe ordenar la salida por nombre?
Eelvex
@Eelvex No, no es necesario.
Steve
1
Esto fue duplicado por una pregunta hoy y la palabra clave que busqué no apareció, así que para futuras búsquedas: desorden.
Peter Taylor

Respuestas:

4

J, 57

(,.' buys for ',"1|.)(?~6){6 4$'AndyBarbCarlDidiEarlFran'

p.ej

   (,.' buys for ',"1|.)(?~6){6 4$'AndyBarbCarlDidiEarlFran'
Carl buys for Earl
Andy buys for Barb
Fran buys for Didi
Didi buys for Fran
Barb buys for Andy
Earl buys for Carl
Eelvex
fuente
No sé [J], pero ¿funcionaría esto si los nombres tuvieran diferentes longitudes?
zx8754
No. El código explota el hecho de que todos los nombres tienen 4 caracteres de longitud. Funcionará para diferentes longitudes con muy pocos cambios.
Eelvex
Esto también explota que hay un número par de personas. Tenga en cuenta que si X le da a Y, Y siempre le dará a X también.
Adám
3

c99 - 252 caracteres

#include <stdio.h>
#define G for(i=0;i<6;i++)
char*n="Andy\0Barb\0Carl\0Didi\0Earl\0Fran",*p[7];int i,j;int main()
{FILE*r=fopen("/dev/random","r");G p[i]=n+5*i;G{j=fgetc(r)%6;p[7]=p[j]
;p[j]=p[i];p[i]=p[7];}G printf("%s buys for %s\n",p[i],p[(i+1)%6]);}

Ligera mejora al aprovechar la naturaleza circular de la permutación. Esta versión siempre construye una estrategia de compra similar a un bucle, por lo que es menos aleatoria que la versión anterior (271 caracteres), pero creo que aún cumple con las especificaciones.

Requiere una plataforma que tenga un funcionamiento /dev/random. Debería poder eliminar aproximadamente 8 omitiendo los \0s en la cadena grande, pero mi libc no parece estar lidiando con los %4sespecificadores de impresión como dice la página del manual.

La combinación es mala, pero hacerlo de esa manera me impide tener que verificar las condiciones de "Foo compra para Foo" .

Legible:

#include <stdio.h>

char *n="Andy\0Barb\0Carl\0Didi\0Earl\0Fran",
  *p[7]; /* 7th cell for temp */
int i,j;

int main(){
  FILE*r=fopen("/dev/random","r");
  for(i=0;i<6;i++)
    p[i]=n+5*i;   /* Initialize the pointers */
  for(i=0;i<6;i++){
    j=fgetc(r)%6; /* Poor numeric properties. Cest le Code Golf */
    p[7]=p[j];
    p[j]=p[i];
    p[i]=p[7];
  }
  for(i=0;i<6;i++)
    printf("%s buys for %s\n",p[i],p[(i+1)%6]);
}
dmckee --- gatito ex moderador
fuente
3

Windows PowerShell, 83

$i=random 5
($n=-split'Andy Barb Carl Didi Earl Fran')|%{"$_ buys for "+$n[++$i%6]}

Historia:

  • 2011-02-11 22:01 (136) - Primer intento.
  • 2011-02-11 22:05 (130) - En línea algunas cosas. Barajar los nombres ahora, no los índices.
  • 2011-02-13 16:13 (128) - No necesito el módulo, ya $ique se recreará cada vez.
  • 2011-02-13 16:20    (87) - Tomó prestada la idea de Anon. La solución de C # . Simplemente genere un desplazamiento aleatorio y luego simplemente déjelos en círculos.
  • 2011-02-13 16:26    (83) - Se modificó la generación e indexación de números aleatorios. Tirado de $_la cuerda para salvar el +.
Joey
fuente
3

Haskell, 241 189 caracteres

import Data.List
import Random
main=randomRIO(0,719)>>=mapM_ putStrLn.f
f n=map(\(x,y)->x++" buys for "++y).zip(l n).tail$cycle$l n
l=(permutations(words"Andy Barb Carl Didi Earl Fran")!!)

Salida completamente aleatoria (que aún satisface la especificación).

Esto genera todas las permutaciones de la lista de nombres, elige uno al azar (creo que esta es la forma más corta en Haskell de barajar una lista; si alguien tiene algo más pequeño, lo agradecería), y luego cada persona compra un presente para la siguiente persona en la lista.

Luego.
fuente
Probé
FUZxxl
@Anon: permutations$words"Andy Barb Carl Didi Earl Fran"y algunos otros trucos que probé en mi versión mejorada. Olvidé que eso permutationsno está incluido en el 98 List, por lo que también debes usar el nombre largo. Échale un vistazo.
FUZxxl
Y para su uso especial: r=tail.cycle. y que en línea
FUZxxl
Lo bajé a 202 caracteres. Echa un vistazo: paste.ubuntuusers.de/399799
FUZxxl
1
Y para 189 caracteres, reemplace la tercera línea en mi ejemplo con:main=randomRIO(0,719)>>=mapM_ putStrLn.f
FUZxxl
3

Golfscript: 72 64 57 caracteres

"AndyBarbCarlDidiEarlFran"4/{;9rand}${.n+\' buys for '}%(

Pruebas

$ golfscript codegolf-838.gs 
Fran buys for Carl
Carl buys for Andy
Andy buys for Barb
Barb buys for Didi
Didi buys for Earl
Earl buys for Fran

$ golfscript codegolf-838.gs 
Didi buys for Earl
Earl buys for Andy
Andy buys for Barb
Barb buys for Carl
Carl buys for Fran
Fran buys for Didi
  • Gracias gnibbler por "AndyBarbCarlDidiEarlFran"4/, actualizado y tengo 7 caracteres menos
  • La solución de 57 caracteres es básicamente de Nabb: D, y también noté que ;9randes más aleatorio que mi6rand*

fuente
1
"AndyBarbCarlDidiEarlFran"4/
gnibbler
ah ja, gracias @gnibbler, genial, voy a actualizarlo.
TU
No estoy seguro de por qué lo está utilizando 6rand*, 0=rando tal vez ;9randsea ​​preferible. Para el bucle, {.n+\' buys for '}%(es más corto ..
Nabb
je se convirtió en el mismo personaje que ahora cuenta con J: D y gracias @Nabb, lo usé 6rand*porque pensé que aleatorizaría igualmente la matriz de 6 elementos (creo que estaba equivocado, ya que ;9randparece realmente aleatorio que el mío)
USTED
3

Japt -R, 41 bytes

`AÌ)B¼C¤E¤FÎÂDi¹`qe ö¬ê1 ò mq` ¿ys f 

-2 bytes gracias a @Oliver!

¡Intentalo!

Este es el enfoque que tomé a un alto nivel:

  • descomprimir una cadena que contiene los nombres de los participantes
  • dividir la cadena en una matriz
  • barajarlo
  • asignar a cada persona a la persona con el siguiente índice más alto
  • la última persona en la matriz se asigna a la primera

Tengo un poco de historia con este problema, ya que creé un programa "secreto de santa" para mi trabajo hace años. Terminamos pidiendo a algunos solicitantes de empleo que trabajen también :)

dana
fuente
@Oliver: ¡gracias por los consejos! Parece que ãno está devolviendo un par que vincula el primero al último elemento. Estoy trabajando en una forma de hacer que esto funcione, pero pensé que te lo haría saber. Gracias de nuevo sin embargo! ethproductions.github.io/japt/…
dana
43 ?
dana
1
Ah, tienes razon. Creo que esto funcionaría para 42
Oliver
1
41 bytes
Oliver
Espera, ¿qué hace el "q"in the .ö("q")do
Solo ASCII
2

Python - 118 caracteres

from random import*;L="Andy Barb Carl Didi Earl Fran".split()
for i in sample(range(6),6):print L[i-1],"buys for",L[i]

Python - 120 caracteres

import random as R;L="Andy Barb Carl Didi Earl Fran".split();R.shuffle(L)
for i in range(6):print L[i-1],"buys for",L[i]
gnibbler
fuente
2

R - 85 caracteres

paste(n<-sample(c('Andy','Barb','Carl','Didi','Earl','Fran')),'buys for',n[c(6,1:5)])
velas_y_naranjas
fuente
1

Python - 154 caracteres

import random as R;L="Andy Barb Carl Didi Earl Fran".split();M=L[:]
while any(map(str.__eq__,L,M)):R.shuffle(M) 
for i in zip(L,M):print"%s buys for %s"%i
gnibbler
fuente
Disculpas, mi Python carece severamente ... ¿el ciclo while está básicamente girando hasta que encuentra una solución que evita "X compra por X"?
Steve
@ Steve: Eso es más o menos lo que hace. mapllama str.__eq__a cada par de valores correspondientes en L y M, y el ciclo continúa hasta que ninguno de ellos sea verdadero.
Anon
@ Steve, sí. aunque probablemente sea más corto cambiar los registros en una cantidad aleatoria de 1 a 5, creo que eso no está en el espíritu de la pregunta
gnibbler
Cuando planteé la pregunta por primera vez en el trabajo, tienes toda la razón. Mis compañeros de trabajo rápidamente señalaron que no estaba descartado por mis definiciones ... así que lo dejé como está cuando publiqué aquí.
Steve
1

D: 233 caracteres

import std.random,std.stdio;void main(){auto p=["Andy","Barb","Carl","Didi","Earl","Fran"];auto q=p.dup;o:while(1){for(int i;i<6;++i)if(p[i]==q[i]){randomShuffle(q);continue o;}break;}foreach(i,a;p)writefln("%s buys for %s",a,q[i]);}

Más legible:

import std.random, std.stdio;

void main()
{
    auto p = ["Andy", "Barb", "Carl", "Didi", "Earl", "Fran"];
    auto q = p.dup;

    o:while(1)
    {
        for(int i; i < 6; ++i)
            if(p[i] == q[i])
            {
                randomShuffle(q);
                continue o;
            }

        break;
    }

    foreach(i, a; p)
        writefln("%s buys for %s", a, q[i]);
}
Jonathan M Davis
fuente
1

Pitón (175)

import random as r
n=['Andy','Barb','Carl','Didi','Earl','Fran']
m=n[:]
r.shuffle(m)
b=' buys for '
for i in n:
 h=m.pop()
 while h==i:
  m.append(h)
  h=m.pop()
 print(i+b+h)
John
fuente
1

Esquema 173

Da una de dos soluciones.

(define(m lst)
    (printf"~v buys for ~v~n"(car lst)(cadr lst))
    (if(eq?(cadr lst)'Andy)0(m(cdr lst)))
)
(m((if(odd?(random 2))reverse values)'(Andy Barb Carl Didi Earl Fran Andy)))

fuente
1

C #, 210 183 caracteres

using System;class a{static void Main(){var n="Andy Barb Carl Didi Earl Fran".Split();var c=0,i=new Random().Next(1,6);for(;c<6;c++)Console.WriteLine(n[c]+" buys for "+n[(c+i)%6]);}}

Montones de repeticiones :(

Esta solución no es totalmente aleatoria: siempre hay uno o más "bucles" de personas, por ejemplo, A-> C-> E-> A, y los desplazamientos son siempre los mismos en los bucles. Sin embargo, no es posible predecir el resultado de una ejecución particular a menos que tenga parte de ese resultado.

Luego.
fuente
Esa es la interpretación que tenía la intención (y básicamente la solución a la que también llegamos).
Steve
Debería ser 210. ¿Está contando la nueva línea al final del archivo?
gnibbler
@gnibbler: Probablemente lo estaba. Acabo de poner el archivo en wc, realmente no voy a contar eso a mano.
Anon
1
¿Qué hay de var n="Andy Barb Carl Didi Earl Fran".Split()? Ahorra 16 bytes. Puede omitir el argumento Main(), que ahorra otros 9 bytes. Y puede combinar la declaración de cy i: int c,i=...;for(c=0;...que ahorra otros dos.
Joey
@Joey: Ajustado según sus sugerencias, gracias.
Anon
0

Ruby - 89 caracteres

(a=%w(Andy Barb Carl Didi Earl Fran).shuffle).zip(a.reverse).each{|e|puts e*' buys for '}

Salida:

Andy buys for Didi
Barb buys for Earl
Fran buys for Carl
Carl buys for Fran
Earl buys for Barb
Didi buys for Andy
steenslag
fuente
1
Puedes usar en maplugar de each.
Dogbert
1
el problema con esta solución es que si tienes un número impar de personas, la persona intermedia se regalará Earl compra para Mark Fran compra para Andy Barb compra para Carl Didi compra para Didi Carl compra para Barb Andy compra para Fran Mark compra para Earl
StudleyJr
0

MathGolf , 41 bytes

"δ%è╘+µ√♂JÇ"2/$╦╕ää▐δáw_╪" buys for "+m+n

Pruébalo en línea!

Explicación

No se garantiza que produzca cada caso con la misma probabilidad, pero sí produce resultados diferentes en cada ejecución. Un byte podría eliminarse si tuviera un operador aleatorio, pero eso es para otro día.

"δ%è╘+µ√♂JÇ"                                push the string "δ%è╘+µ√♂JÇ"
            2/                              split into segments of two characters
              $                             transform to ordinals using base 256
               ╦                            fetch dictionary words (['Andy', 'barb', 'Carl', 'Earl', 'Fran'])
                ╕ää                         Push "didi"
                   ▐                        append to end of list
                    δ                       capitalize all strings in list
                     áw                     sort by random character in each string (shuffle)
                       _                    duplicate TOS
                        ╪                   right-rotate bits in int, list, str
                         " buys for "       push the string " buys for "
                                     +      Add to all strings in list
                                      m+    zip add the two arrays
                                        n   join array with newline
maxb
fuente