Échange de cadeaux des Fêtes

11

Un autre problème de notre golf interne ... celui-ci autour des vacances l'année dernière.

PROBLÈME

Andy, Barb, Carl, Didi, Earl et Fran s'achètent des cadeaux. Dessinez des noms pour un échange de cadeaux.

  1. Chaque personne achète un cadeau et reçoit un cadeau.
  2. Personne n'achète son propre cadeau.
  3. L'exécution de la solution plusieurs fois devrait produire des résultats différents (la paire donneur-récepteur ne doit pas être prévisible ou identique d'une exécution à l'autre).

CONTRIBUTION

Aucun.

PRODUCTION

Formaté comme dans cet exemple:

Andy achète pour Barb
Barb achète pour Carl
Carl achète pour Didi
Didi achète pour Earl
Earl achète pour Fran
Fran achète pour Andy

Steve
la source
La sortie doit-elle être triée par nom?
Eelvex
@Eelvex Nope, pas nécessaire.
Steve
1
Cela a été dupliqué par une question aujourd'hui et le mot-clé que j'ai recherché ne l'a pas trouvé, donc pour les recherches futures: dérangement.
Peter Taylor

Réponses:

4

J, 57

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

par exemple

   (,.' 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
la source
Je ne sais pas [J], mais est-ce que cela fonctionnerait si les noms avaient des longueurs différentes?
zx8754
Non. Le code exploite le fait que tous les noms comportent 4 caractères. Cela fonctionnera pour différentes longueurs avec très peu de changements.
Eelvex
Cela exploite également qu'il y a un nombre pair de personnes. Notez que si X donne à Y, Y donnera toujours à X aussi.
Adám
3

c99 - 252 caractères

#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]);}

Légère amélioration en profitant du caractère circulaire de la permutation. Cette version construit toujours une stratégie d'achat en boucle, elle est donc moins aléatoire que la version précédente (271 caractères), mais je pense qu'elle répond toujours aux spécifications.

Nécessite une plateforme qui fonctionne /dev/random. Je devrais être en mesure de supprimer environ 8 en omettant le \0s dans la grande chaîne, mais ma libc ne semble pas traiter %4sles spécificateurs d'impression comme le dit la page de manuel.

Le shuffle est mauvais, mais le faire de cette façon m'empêche d'avoir à vérifier les conditions "Foo achète pour Foo" .

Lisible:

#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 --- chaton ex-modérateur
la source
3

Windows PowerShell, 83

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

Histoire:

  • 2011-02-11 22:01 (136) - Première tentative.
  • 2011-02-11 22:05 (130) - A souligné quelques choses. Mélanger les noms maintenant, pas les index.
  • 2011-02-13 16:13 (128) - Je n'ai pas besoin du module car $iil sera recréé à chaque fois.
  • 2011-02-13 16:20    (87) - A emprunté l'idée à Anon. est la solution C # . Générez simplement un décalage aléatoire, puis laissez-les simplement tourner en rond.
  • 2011-02-13 16:26    (83) - Génération et indexation de nombres aléatoires modifiés. Tiré $_dans la chaîne pour enregistrer le +.
Joey
la source
3

Haskell, 241189 caractères

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")!!)

Sortie entièrement aléatoire (qui satisfait toujours la spécification).

Cela génère toutes les permutations de la liste des noms, en choisit un au hasard (je pense que c'est le moyen le plus court à Haskell de mélanger une liste - si quelqu'un a quelque chose de plus petit, je l'apprécierais), puis chaque personne achète ensuite un présent pour la prochaine personne dans la liste.

Anon.
la source
J'ai essayé cette ad-hoc, je ne sais pas si cela fonctionne: paste.ubuntuusers.de/399798
FUZxxl
@Anon: permutations$words"Andy Barb Carl Didi Earl Fran"et quelques autres astuces que j'ai essayées dans ma version améliorée. J'ai oublié, ce permutationsn'est pas inclus dans le 98 List, vous devez donc utiliser le nom long non plus. Jetez-y un œil.
FUZxxl
Et pour votre but spécial: r=tail.cycle. et que l'inline.
FUZxxl
Je l'ai descendu à 202 caractères. Jetez un œil: paste.ubuntuusers.de/399799
FUZxxl
1
Et pour 189 caractères, remplacez la troisième ligne de mon exemple par:main=randomRIO(0,719)>>=mapM_ putStrLn.f
FUZxxl
3

Golfscript: 72 64 57 caractères

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

Les tests

$ 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
  • Merci gnibbler pour "AndyBarbCarlDidiEarlFran"4/, mis à jour et obtenu 7 caractères de moins
  • La solution à 57 caractères est essentiellement de Nabb: D, et a également remarqué que ;9randc'est plus aléatoire que mon6rand*
TU
la source
1
"AndyBarbCarlDidiEarlFran"4/
gnibbler
ah ha, merci @gnibbler, cool, va le mettre à jour.
VOUS le
Je ne sais pas pourquoi vous utilisez 6rand*- 0=randou c'est peut ;9rand- être préférable. Pour la boucle, {.n+\' buys for '}%(c'est plus court ..
Nabb
il h; est devenu le même nombre de caractères avec J maintenant: D et merci @Nabb, je l'ai utilisé 6rand*parce que je pensais qu'il randomiserait également le tableau des 6 éléments (je pense que j'avais tort, car il a l' ;9randair vraiment aléatoire que le mien)
VOUS
3

Japt -R, 41 octets

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

-2 octets grâce à @Oliver!

Essayez!

C'est l'approche que j'ai adoptée à un haut niveau:

  • décompresser une chaîne contenant les noms des participants
  • diviser la chaîne en un tableau
  • mélanger
  • attribuer chaque personne à la personne ayant l'indice suivant le plus élevé
  • la dernière personne du tableau est affectée à la première

J'ai un peu d'histoire avec ce problème car j'ai créé un programme de "père Noël secret" pour mon travail il y a des années. Nous avons fini par demander à quelques candidats de travailler aussi :)

dana
la source
@Oliver - merci pour les conseils! Il semble que le ãne retourne pas une paire qui relie le premier au dernier élément. Je travaille sur un moyen de faire en sorte que cela fonctionne, mais j'ai pensé que je vous le ferais savoir. Merci encore! ethproductions.github.io/japt/…
dana
43 ?
dana
1
Ah, tu as raison. Je pense que cela fonctionnerait pour 42
Oliver
1
41 octets
Oliver
Attendez ce que fait le "q"dans le .ö("q")do
ASCII seulement
2

Python - 118 caractères

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 caractères

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]
grignoteur
la source
2

R - 85 caractères

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

Python - 154 caractères

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
grignoteur
la source
Toutes mes excuses, mon Python fait cruellement défaut ... la boucle while est-elle essentiellement en boucle jusqu'à ce qu'elle trouve une solution qui évite "X achète pour X"?
Steve
@Steve: C'est à peu près ce qu'il fait. mapappelle str.__eq__chaque paire de valeurs correspondantes dans L et M, et la boucle continue jusqu'à ce qu'aucune d'entre elles ne soit vraie.
Anon.
@Steve, oui. bien qu'il soit probablement plus court de déplacer les enregistrements d'un montant aléatoire de 1 à 5, je pense que ce n'est pas dans l'esprit de la question
gnibbler
Lorsque j'ai posé la question pour la première fois au travail, vous avez tout à fait raison. Mes collègues ont rapidement souligné que cela n'était pas exclu par mes définitions ... alors je l'ai laissé tel quel lors de la publication ici.
Steve
1

D: 233 caractères

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]);}

Plus lisiblement:

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
la source
1

Python (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
la source
1

Schéma, 173

Donne l'une des deux solutions.

(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)))

la source
1

C #, 210 183 caractères

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]);}}

Des tas de passe-partout :(

Cette solution n'est pas totalement aléatoire - il y a toujours une ou plusieurs "boucles" de personnes, par exemple A-> C-> E-> A, et les décalages sont toujours les mêmes dans les boucles. Cependant, il n'est pas possible de prédire la sortie d'une exécution particulière à moins d'avoir une partie de cette sortie.

Anon.
la source
C'est l'interprétation que je souhaitais (et, fondamentalement, la solution sur laquelle nous avons atterri également).
Steve
Doit être 210. comptez-vous la nouvelle ligne à la fin du fichier?
gnibbler
@gnibbler: J'étais probablement. Je viens de copier le fichier en wc, je ne vais pas vraiment le compter à la main.
Anon.
1
Et alors var n="Andy Barb Carl Didi Earl Fran".Split()? Enregistre 16 octets. Vous pouvez ignorer l'argument de Main(), ce qui économise encore 9 octets. Et vous pouvez combiner la déclaration de cet i: int c,i=...;for(c=0;...ce qui économise deux autres.
Joey
@Joey: l'ajusté selon vos suggestions, merci.
Anon.
0

Rubis - 89 caractères

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

Production:

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
la source
1
Vous pouvez utiliser à la mapplace de each.
Dogbert
1
le problème avec cette solution est que si vous avez un nombre impair de personnes, la personne du milieu se fera un cadeau Earl achète pour Mark Fran achète pour Andy Barb achète pour Carl Didi achète pour Didi Carl achète pour Barb Andy achète pour Fran Mark achète pour Earl
StudleyJr
0

MathGolf , 41 octets

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

Essayez-le en ligne!

Explication

Cela n'est pas garanti pour produire chaque cas avec une probabilité égale, mais cela produit des résultats différents à chaque exécution. Un octet pourrait être supprimé si j'avais un opérateur de lecture aléatoire, mais c'est pour un autre jour.

"δ%è╘+µ√♂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
la source