Świąteczna wymiana prezentów

11

Kolejny problem związany z naszym wewnętrznym golfem ... tym wokół wakacji w zeszłym roku.

PROBLEM

Andy, Barb, Carl, Didi, Earl i Fran kupują sobie prezenty. Narysuj nazwy do wymiany prezentów.

  1. Każda osoba kupuje jeden prezent i otrzymuje jeden prezent.
  2. Nikt nie kupuje własnego prezentu.
  3. Wielokrotne uruchomienie rozwiązania powinno dawać różne wyniki (para odbiorca-odbiornik nie powinna być przewidywalna ani identyczna dla poszczególnych uruchomień).

WEJŚCIE

Żaden.

WYNIK

Sformatowany jak w tym przykładzie:

Andy kupuje dla Barb
Barb kupuje dla Carl
Carl kupuje dla Didi
Didi kupuje dla Earl
Earl kupuje dla Fran
Fran kupuje dla Andy

Steve
źródło
Czy dane wyjściowe powinny być sortowane według nazwy?
Eelvex
@Eelvex Nie, nie jest konieczne.
Steve,
1
To pytanie zostało dziś zduplikowane, a słowo kluczowe, którego szukałem, nie zostało wyświetlone, więc w przypadku przyszłych wyszukiwań: wykolejenie.
Peter Taylor

Odpowiedzi:

4

J, 57

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

na przykład

   (,.' 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
źródło
Nie wiem [J], ale czy to zadziałałoby, gdyby nazwy miały różne długości?
zx8754,
Nie. Kod wykorzystuje fakt, że wszystkie nazwy mają 4 znaki. Będzie działać na różnych długościach z niewielkimi zmianami.
Eelvex
Wykorzystuje to również fakt, że istnieje parzysta liczba osób. Zauważ, że jeśli X daje Y, Y zawsze również da X.
Adám
3

c99 - 252 znaków

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

Niewielka poprawa dzięki wykorzystaniu okrągłego charakteru permutacji. Ta wersja zawsze buduje strategię kupowania podobną do pętli, więc jest mniej losowa niż poprzednia wersja (271 znaków), ale wierzę, że nadal spełnia specyfikację.

Wymaga platformy, która ma sprawny /dev/random. Powinienem być w stanie zrzucić około 8, pomijając literę \0s w dużym łańcuchu, ale moja biblioteka nie wydaje się zajmować %4sspecyfikacjami drukowania tak, jak mówi strona podręcznika.

Losowanie jest złe, ale robienie tego w ten sposób zapobiega sprawdzaniu warunków „Foo kupuje za Foo” .

Czytelny:

#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 --- były kot moderator
źródło
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) - Pierwsza próba.
  • 2011-02-11 22:05 (130) - Wstawiłem kilka rzeczy. Teraz przetasuj nazwy, a nie indeksy.
  • 2011-02-13 16:13 (128) - Nie potrzebuję modułu, ponieważ $ibędzie za każdym razem odtwarzany.
  • 2011-02-13 16:20    (87) - Wypożyczyłem pomysł od Anona. „y Do roztworu # . Po prostu wygeneruj losowe przesunięcie, a następnie pozwól im prezentować się w kółko.
  • 2011-02-13 16:26    (83) - Zmieniono generowanie i indeksowanie liczb losowych. Wciągnięty $_do sznurka, aby zapisać +.
Joey
źródło
3

Haskell, 241 189 znaków

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

W pełni losowe wyjście (które nadal spełnia specyfikację).

To generuje wszystkie permutacje z listy nazwisk, wybiera jedną losowo (myślę, że jest to najkrótsza droga w Haskell do przetasowania listy - jeśli ktoś ma coś mniejszego, doceniłbym to), a następnie każda osoba kupuje obecny dla następnej osoby na liście.

Zaraz.
źródło
Próbowałem tego ad-hoc, nie jestem pewien, czy to działa: paste.ubuntuusers.de/399798
FUZxxl
@Anon: permutations$words"Andy Barb Carl Didi Earl Fran"i kilka innych sztuczek, które wypróbowałem w ulepszonej wersji. Zapomniałem, że permutationsnie ma go w 98 List, więc musisz użyć długiej nazwy. Spójrz na to.
FUZxxl,
I do celów specjalnych: r=tail.cycle. i niż wstawić to.
FUZxxl,
Sprowadziłem do 202 znaków. Zobacz: paste.ubuntuusers.de/399799
FUZxxl
1
I dla 189 znaków zamień trzecią linię w moim przykładzie na:main=randomRIO(0,719)>>=mapM_ putStrLn.f
FUZxxl
3

Golfscript: 72 64 57 znaków

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

Testy

$ 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
  • Dzięki gnibbler za "AndyBarbCarlDidiEarlFran"4/ , zaktualizowałem i dostałem 7 znaków mniej
  • Rozwiązanie 57 znaków jest w zasadzie autorstwa Nabb: D, i zauważyłem, że ;9randjest bardziej losowe niż moje6rand*
TY
źródło
1
"AndyBarbCarlDidiEarlFran"4/
gnibbler
ach, dziękuję @gnibbler, fajnie, zamierzam go zaktualizować.
TY
Nie jestem pewien, dlaczego używasz 6rand*- 0=randa może ;9randlepiej. Pętla {.n+\' buys for '}%(jest krótsza.
Nabb,
heh; stały się takie same znaki liczą teraz z J: D i dziękuję @Nabb, użyłem, 6rand*ponieważ myślałem, że równomiernie losuje tablicę 6 elementów (myślę, że się myliłem, ponieważ ;9randwygląda naprawdę losowo niż mój)
TY
3

Japt -R, 41 bajtów

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

-2 bajty dzięki @Oliver!

Spróbuj!

Takie podejście przyjęłam na wysokim poziomie:

  • rozpakuj ciąg zawierający nazwiska uczestników
  • podziel ciąg na tablicę
  • potasuj to
  • przypisz każdą osobę do osoby o kolejnym najwyższym indeksie
  • ostatnia osoba w tablicy zostaje przypisana do pierwszej

Mam trochę historii z tym problemem, ponieważ wiele lat temu stworzyłem program „tajnego Świętego Mikołaja” dla mojej pracy. Skończyło się też na tym, że poprosiliśmy kilku kandydatów do pracy :)

dana
źródło
@Oliver - dzięki za wskazówki! Wygląda na ãto, że nie zwraca pary, która łączy pierwszy z ostatnim elementem. Pracuję nad sposobem, aby to zadziałało, ale pomyślałem, że dam ci znać. Jeszcze raz dziękuję! ethproductions.github.io/japt/…
dana
43 ?
dana
1
Ach, masz rację. Myślę, że to zadziałałoby dla 42
Oliver
1
41 bajtów
Oliver
Poczekaj, co robi "q"in- .ö("q")do
tylko ASCII
2

Python - 118 znaków

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 znaków

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
źródło
2

R - 85 znaków

paste(n<-sample(c('Andy','Barb','Carl','Didi','Earl','Fran')),'buys for',n[c(6,1:5)])
świeczki i pomarańcze
źródło
1

Python - 154 znaków

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
źródło
Przepraszam, mój Python poważnie brakuje ... czy pętla while zasadniczo zapętla się, dopóki nie znajdzie rozwiązania, które pozwoli uniknąć „X kupuje za X”?
Steve
@ Steve: Tak właśnie się dzieje. mapwywołuje str.__eq__każdą parę odpowiednich wartości w L i M, a pętla działa, dopóki żadna z nich nie jest prawdziwa.
Anon.
@ Steve, tak. chociaż prawdopodobnie krótsze jest przesunięcie rekordów losowo z 1 na 5, myślę, że nie jest to zgodne z duchem pytania
gnibbler
Kiedy po raz pierwszy zadałem pytanie w pracy, masz całkowitą rację. Moi współpracownicy szybko zauważyli, że moje definicje tego nie wykluczają ... więc zostawiłem to tak, jak tu, pisząc tutaj.
Steve
1

D: 233 znaków

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

Bardziej czytelnie:

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
źródło
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)
Jan
źródło
1

Schemat, 173

Daje jedno z dwóch rozwiązań.

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

źródło
1

C #, 210 183 znaków

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

Sterty płyty kotłowej :(

To rozwiązanie nie jest całkowicie losowe - zawsze istnieje jedna lub więcej „pętli” ludzi, np. A-> C-> E-> A, a przesunięcia są zawsze takie same w pętlach. Jednak nie można przewidzieć wyniku określonego przebiegu, chyba że masz jego część.

Zaraz.
źródło
Taką interpretację zamierzałem (i w zasadzie rozwiązanie, na którym wylądowaliśmy).
Steve
Powinno być 210. czy liczysz nowy wiersz na końcu pliku?
gnibbler
@gnibbler: Prawdopodobnie byłem. Właśnie umieściłem plik w wc, tak naprawdę nie liczę tego ręcznie.
Anon.
1
Co var n="Andy Barb Carl Didi Earl Fran".Split()? Oszczędza 16 bajtów. Możesz pominąć argument Main(), który oszczędza kolejne 9 bajtów. Możesz połączyć deklarację ci i: int c,i=...;for(c=0;...co oszczędza kolejne dwa.
Joey,
@Joey: Poprawiłem go zgodnie z twoimi sugestiami, dzięki.
Anon.
0

Rubin - 89 znaków

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

Wynik:

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
źródło
1
Możesz użyć mapzamiast each.
Dogbert
1
problem z tym rozwiązaniem polega na tym, że jeśli masz nieparzystą liczbę osób, środkowa osoba podaruje się Earl kupuje dla Marka Frana kupuje dla Andy'ego Barb kupuje dla Carl Didi kupuje dla Didi Carl kupuje dla Barb Andy kupuje dla Franka Mark kupuje dla Earl
StudleyJr
0

MathGolf , 41 bajtów

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

Wypróbuj online!

Wyjaśnienie

Nie gwarantuje się, że każdy przypadek zostanie wygenerowany z jednakowym prawdopodobieństwem, ale daje różne wyniki dla każdego przebiegu. Jeden bajt mógłby zostać usunięty, gdybym miał operatora tasowania, ale to na inny dzień.

"δ%è╘+µ√♂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
źródło