Austausch von Weihnachtsgeschenken

11

Ein weiteres Problem von unserem internen Golf ... dieses um die Feiertage im letzten Jahr.

PROBLEM

Andy, Barb, Carl, Didi, Earl und Fran kaufen sich gegenseitig Geschenke. Zeichnen Sie Namen für einen Geschenkaustausch.

  1. Jede Person kauft ein Geschenk und erhält ein Geschenk.
  2. Niemand kauft sein eigenes Geschenk.
  3. Das mehrmalige Ausführen der Lösung sollte zu unterschiedlichen Ergebnissen führen (das Geber-Empfänger-Paar sollte von Lauf zu Lauf nicht vorhersehbar oder identisch sein).

EINGANG

Keiner.

AUSGABE

Formatiert wie in diesem Beispiel:

Andy kauft für Barb
Barb kauft für Carl
Carl kauft für Didi
Didi kauft für Earl
Earl kauft für Fran
Fran kauft für Andy

Steve
quelle
Sollte die Ausgabe nach Namen sortiert werden?
Eelvex
@Eelvex Nein, nicht notwendig.
Steve
1
Dies wurde heute durch eine Frage dupliziert, und das Schlüsselwort, nach dem ich gesucht habe, ist nicht aufgetaucht, also für zukünftige Suchvorgänge: Störung.
Peter Taylor

Antworten:

4

J, 57

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

z.B

   (,.' 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
quelle
Ich weiß nicht [J], aber würde das funktionieren, wenn die Namen unterschiedlich lang wären?
zx8754
Nein. Der Code nutzt die Tatsache aus, dass alle Namen 4 Zeichen lang sind. Es funktioniert mit sehr wenigen Änderungen für verschiedene Längen.
Eelvex
Dies nutzt auch aus, dass es eine gerade Anzahl von Menschen gibt. Beachten Sie, dass wenn X Y gibt, Y immer auch X gibt.
Adám
3

c99 - 252 Zeichen

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

Leichte Verbesserung durch Ausnutzung der kreisförmigen Natur der Permutation. Diese Version entwickelt immer eine schleifenartige Kaufstrategie, daher ist sie weniger zufällig als die vorherige Version (271 Zeichen), aber ich glaube, sie entspricht immer noch der Spezifikation.

Benötigt eine funktionierende Plattform /dev/random. Ich sollte in der Lage sein, ungefähr 8 auszuschalten, indem ich das \0s in der großen Zeichenfolge weglasse , aber meine libc scheint sich nicht mit Druckspezifizierern zu befassen, %4swie es auf der Manpage steht.

Das Mischen ist schlecht, aber wenn ich es so mache, muss ich nicht nach den Bedingungen für "Foo kauft für Foo" suchen.

Lesbar:

#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 --- Ex-Moderator Kätzchen
quelle
3

Windows PowerShell, 83

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

Geschichte:

  • 2011-02-11 22:01 (136) - Erster Versuch.
  • 2011-02-11 22:05 (130) - Einige Dinge wurden hervorgehoben. Mischen Sie jetzt die Namen, nicht die Indizes.
  • 2011-02-13 16:13 (128) - Ich brauche den Modul nicht, da er $ijedes Mal neu erstellt wird.
  • 2011-02-13 16:20    (87) - Entlehnt die Idee von Anon. ‚s C # Lösung . Generieren Sie einfach einen zufälligen Versatz und lassen Sie sie dann im Kreis verschenken.
  • 2011-02-13 16:26    (83) - Zufallsgenerierung und Indizierung geändert. Zog $_in die Zeichenfolge die zu speichern +.
Joey
quelle
3

Haskell, 241 189 Zeichen

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

Vollständig zufällige Ausgabe (die immer noch die Spezifikation erfüllt).

Dies erzeugt alle Permutationen der Liste der Namen, wählt zufällig eine aus (ich denke, dies ist der kürzeste Weg in Haskell, um eine Liste zu mischen - wenn jemand etwas Kleineres hat, würde ich es schätzen), und dann kauft jede Person eine anwesend für die nächste Person in der Liste.

Anon.
quelle
Ich habe dieses Ad-hoc- Verfahren
ausprobiert.
@Anon: permutations$words"Andy Barb Carl Didi Earl Fran"und einige andere Tricks, die ich in meiner verbesserten Version ausprobiert habe. Ich habe vergessen, dass permutationsdas nicht in der 98 enthalten ist List, also musst du auch den langen Namen verwenden. Schau es dir an.
FUZxxl
Und für Ihren besonderen Zweck : r=tail.cycle. und dann inline.
FUZxxl
Habe es auf 202 Zeichen reduziert. Schauen Sie mal
rein
1
Und für 189 Zeichen ersetzen Sie die dritte Zeile in meinem Beispiel durch:main=randomRIO(0,719)>>=mapM_ putStrLn.f
FUZxxl
3

Golfscript: 72 64 57 Zeichen

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

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
  • Danke gnibbler für "AndyBarbCarlDidiEarlFran"4/, aktualisiert und 7 Zeichen weniger bekommen
  • 57 Zeichen Lösung ist im Grunde von Nabb: D, und auch bemerkt, dass ;9randdas zufälliger ist als meine6rand*
SIE
quelle
1
"AndyBarbCarlDidiEarlFran"4/
Gnibbler
ah ha, danke @gnibbler, cool, werde es aktualisieren.
SIE
Nicht sicher, warum Sie verwenden 6rand*- 0=randoder vielleicht ;9randist vorzuziehen. Für die Schleife {.n+\' buys for '}%(ist kürzer ..
Nabb
heh; wurde jetzt die gleiche Zeichenanzahl mit J: D und danke @Nabb, ich habe verwendet, 6rand*weil ich dachte, es wird das 6-Elemente-Array gleichermaßen randomisieren (ich denke, ich habe mich geirrt, da es ;9randwirklich zufällig aussieht als meins)
DU
3

Japt -R, 41 Bytes

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

-2 Bytes dank @Oliver!

Versuch es!

Dies ist der Ansatz, den ich auf hohem Niveau gewählt habe:

  • Dekomprimieren Sie eine Zeichenfolge mit Teilnehmernamen
  • String in ein Array teilen
  • mische es
  • Ordnen Sie jede Person der Person mit dem nächsthöheren Index zu
  • Die letzte Person im Array wird der ersten zugewiesen

Ich habe eine kleine Geschichte mit diesem Problem, als ich vor Jahren ein "Secret Santa" -Programm für meine Arbeit erstellt habe. Am Ende haben wir ein paar Bewerber gebeten, das auch durchzuarbeiten :)

Dana
quelle
@Oliver - danke für die Tipps! Es sieht so aus, ãals würde kein Paar zurückgegeben, das das erste mit dem letzten Element verknüpft. Ich arbeite daran, dies zum Laufen zu bringen, dachte aber, ich würde es Sie wissen lassen. Nochmals vielen Dank! ethproductions.github.io/japt/...
dana
43 ?
Dana
1
Ah, du hast recht. Ich denke, das würde für 42 funktionieren
Oliver
1
41 Bytes
Oliver
Warten Sie, was das "q"in der .ö("q")do
ASCII-only
2

Python - 118 Zeichen

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 Zeichen

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
quelle
2

R - 85 Zeichen

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

Python - 154 Zeichen

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
quelle
Entschuldigung, mein Python fehlt stark ... wird die while-Schleife dort im Grunde genommen wiederholt, bis eine Lösung gefunden wird, die "X kauft für X" vermeidet?
Steve
@Steve: Das ist ziemlich genau das, was es tut. mapruft str.__eq__jedes Paar entsprechender Werte in L und M auf, und die Schleife läuft weiter, bis keiner von ihnen wahr ist.
Anon.
@Steve, ja. Obwohl es wahrscheinlich kürzer ist, die Datensätze um einen zufälligen Betrag von 1 auf 5 zu verschieben, denke ich, dass dies nicht im Sinne der Frage ist
Gnibbler
Als ich die Frage bei der Arbeit zum ersten Mal stellte, haben Sie genau Recht. Meine Kollegen wiesen schnell darauf hin, dass dies durch meine Definitionen nicht ausgeschlossen wurde ... also habe ich es so belassen, wie es beim Posten hier war.
Steve
1

D: 233 Zeichen

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

Lesbarer:

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
quelle
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
quelle
1

Schema, 173

Gibt eine von zwei Lösungen.

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

quelle
1

C #, 210 183 Zeichen

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

Haufenweise Boilerplate :(

Diese Lösung ist nicht völlig zufällig - es gibt immer eine oder mehrere "Schleifen" von Personen, z. B. A-> C-> E-> A, und die Offsets sind in den Schleifen immer gleich. Es ist jedoch nicht möglich, die Ausgabe eines bestimmten Laufs vorherzusagen, es sei denn, Sie haben einen Teil dieser Ausgabe.

Anon.
quelle
Das ist die Interpretation, die ich beabsichtigt hatte (und im Grunde auch die Lösung, auf die wir gelandet sind).
Steve
Sollte 210 sein. Zählen Sie den Zeilenumbruch am Ende der Datei?
Gnibbler
@gnibbler: Das war ich wahrscheinlich. Ich habe die Datei nur in wc catted, ich werde das nicht wirklich von Hand zählen.
Anon.
1
Was ist mit var n="Andy Barb Carl Didi Earl Fran".Split()? Spart 16 Bytes. Sie können das Argument weglassen Main(), wodurch weitere 9 Bytes gespeichert werden. Und Sie können die Deklaration von cund i: kombinieren, int c,i=...;for(c=0;...wodurch zwei weitere gespeichert werden.
Joey
@ Joey: Optimiert es gemäß Ihren Vorschlägen, danke.
Anon.
0

Ruby - 89 Zeichen

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

Ausgabe:

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
quelle
1
Sie können mapanstelle von verwenden each.
Wile E. Coyote
1
Das Problem bei dieser Lösung ist, dass sich die mittlere Person bei einer ungeraden Anzahl von Personen schenkt. Earl kauft für Mark Fran kauft für Andy Barb kauft für Carl Didi kauft für Didi Carl kauft für Barb Andy kauft für Fran Mark kauft für Earl
StudleyJr
0

MathGolf , 41 Bytes

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

Probieren Sie es online aus!

Erläuterung

Dies garantiert nicht jeden Fall mit gleicher Wahrscheinlichkeit, führt jedoch bei jedem Lauf zu unterschiedlichen Ergebnissen. Ein Byte könnte entfernt werden, wenn ich einen Shuffle-Operator hätte, aber das ist für einen anderen Tag.

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