Scambio di regali per le vacanze


11

Un altro problema del nostro golf interno ... questo durante le vacanze dell'anno scorso.

PROBLEMA

Andy, Barb, Carl, Didi, Earl e Fran si stanno comprando dei regali. Disegna i nomi per uno scambio di regali.

  1. Ogni persona compra un regalo e riceve un regalo.
  2. Nessuno compra il proprio regalo.
  3. L'esecuzione della soluzione più volte dovrebbe produrre risultati diversi (la coppia donatore-destinatario non deve essere prevedibile o identica da corsa a corsa).

INGRESSO

Nessuna.

PRODUZIONE

Formattato come in questo esempio:

Andy acquista per Barb
Barb acquista per Carl
Carl acquista per Didi
Didi acquista per Earl
Earl acquista per Fran
Fran acquista per Andy


L'output deve essere ordinato per nome?
Eelvex,

@Eelvex No, non necessario.
Steve,

1
Questo è stato duplicato oggi da una domanda e la parola chiave che ho cercato non l'ha trovata, quindi per ricerche future: derangement.
Peter Taylor,

Risposte:


4

J, 57

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

per esempio

   (,.' 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

Non conosco [J], ma funzionerebbe se i nomi avessero lunghezze diverse?
zx8754,

No. Il codice sfrutta il fatto che tutti i nomi sono lunghi 4 caratteri. Funzionerà per lunghezze diverse con pochissime modifiche.
Eelvex,

Ciò sfrutta anche il fatto che esiste un numero pari di persone. Nota che se X dà a Y, anche Y darà sempre a X.
Adám,

3

c99 - 252 caratteri

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

Leggero miglioramento sfruttando la natura circolare della permutazione. Questa versione sviluppa sempre una strategia di acquisto simile a un loop, quindi è meno casuale rispetto alla versione precedente (271 caratteri), ma credo che soddisfi ancora le specifiche.

Richiede una piattaforma che ha un funzionamento /dev/random. Dovrei essere in grado di battere circa 8 omettendo le \0s nella stringa grande, ma la mia libc non sembra avere a che fare con gli identificatori di %4sstampa come dice la pagina man.

Lo shuffle è cattivo, ma farlo in questo modo mi impedisce di controllare le condizioni "Foo compra per Foo" .

Leggibile:

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

3

Windows PowerShell, 83

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

Storia:

  • 2011-02-11 22:01 (136) - Primo tentativo.
  • 2011-02-11 22:05 (130) - Inline alcune cose. Mescolando i nomi ora, non gli indici.
  • 13/02/2011 16:13 (128) - Non ho bisogno del modulo poiché $iverrà ricreato ogni volta.
  • 13/02/2011 16:20    (87) - Prese in prestito l'idea da Anon. la soluzione C # . Basta generare uno scostamento casuale e poi lasciarli fare un regalo in cerchio.
  • 13/02/2011 16:26    (83) - Modificata generazione e indicizzazione di numeri casuali. Tirato $_nella stringa per salvare il file +.

3

Haskell, 241 189 caratteri

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

Uscita completamente casuale (che soddisfa ancora le specifiche).

Questo genera tutte le permutazioni dell'elenco dei nomi, ne sceglie uno a caso (penso che questo sia il modo più breve in Haskell di mescolare un elenco - se qualcuno ha qualcosa di più piccolo, lo apprezzerei), e quindi ogni persona acquista un presente per la persona successiva nell'elenco.


Ho provato questo ad-hoc, non so se funziona: paste.ubuntuusers.de/399798
FUZxxl,

@Anon: permutations$words"Andy Barb Carl Didi Earl Fran"e alcuni altri trucchi che ho provato nella mia versione migliorata. Ho dimenticato che permutationsnon è incluso nel 98 List, quindi è necessario utilizzare anche il nome lungo. Date un'occhiata a questo.
FUZxxl,

E per il vostro scopo speciale: r=tail.cycle. e che inline.
FUZxxl,

Sono arrivato a 202 caratteri. Dai
FUZxxl,

1
E per 189 caratteri, sostituisci la terza riga nel mio esempio con:main=randomRIO(0,719)>>=mapM_ putStrLn.f
FUZxxl

3

Golfscript: 72 64 57 caratteri

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

test

$ 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
  • Grazie gnibbler per "AndyBarbCarlDidiEarlFran"4/, aggiornato e ottenuto 7 caratteri in meno
  • La soluzione di 57 caratteri è fondamentalmente di Nabb: D e ha anche notato che ;9randè più casuale della mia6rand*

1
"AndyBarbCarlDidiEarlFran"4/
Gnibbler,

ah ah, grazie @gnibbler, bello, andando ad aggiornarlo.
TU

Non sono sicuro del motivo per cui stai usando 6rand*- 0=rando forse ;9randè preferibile. Per il ciclo, {.n+\' buys for '}%(è più breve ..
Nabb,

eh; è diventato lo stesso conteggio dei caratteri con J ora: D e grazie @Nabb, l'ho usato 6rand*perché pensavo che avrebbe ugualmente randomizzato l'array di 6 elementi (penso di aver sbagliato, dato che ;9randsembra davvero casuale del mio)
TU

3

Japt -R, 41 byte

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

-2 byte grazie a @Oliver!

Provalo!

Questo è l'approccio che ho adottato ad alto livello:

  • decomprimere una stringa contenente i nomi dei partecipanti
  • dividere la stringa in un array
  • mescolalo
  • assegnare ogni persona alla persona con il successivo indice più alto
  • l'ultima persona dell'array viene assegnata alla prima

Ho un po 'di storia con questo problema mentre ho creato un programma "Babbo Natale segreto" per il mio lavoro anni fa. Alla fine abbiamo chiesto ad alcuni candidati di lavoro di lavorarci anche :)


@Oliver - grazie per i suggerimenti! Sembra che ãnon stia restituendo una coppia che collega il primo all'ultimo elemento. Sto lavorando a un modo per farlo funzionare, ma ho pensato di farti sapere. Grazie ancora! ethproductions.github.io/japt/…
dana


1
Ah, hai ragione. Penso che funzionerebbe per 42 anni
Oliver


Aspettare che cosa fa l' "q"in .ö("q")do
ASCII-solo

2

Python - 118 caratteri

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 caratteri

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]

2

R - 85 caratteri

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

1

Python - 154 caratteri

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

Mi scuso, il mio Python è gravemente carente ... il ciclo while è praticamente in loop fino a quando non trova una soluzione che evita "X acquista per X"?
Steve,

@Steve: è praticamente quello che fa. mapchiama str.__eq__ciascuna coppia di valori corrispondenti in L e M e il ciclo continua fino a quando nessuno di essi è vero.
Anon.

@Steve, sì. anche se probabilmente è più breve spostare jsut di un numero casuale da 1 a 5, penso che non sia nello spirito della domanda
gnibbler,

Quando ho posto la domanda per la prima volta al lavoro, hai esattamente ragione. I miei colleghi hanno rapidamente sottolineato che non era escluso dalle mie definizioni ... quindi l'ho lasciato com'è quando ho pubblicato qui.
Steve,

1

D: 233 personaggi

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

Più leggibilmente:

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

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)

1

Schema, 173

Fornisce una delle due soluzioni.

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

1

C #, 210 183 caratteri

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

Cumuli di boilerplate :(

Questa soluzione non è del tutto casuale - ci sono sempre uno o più "loop" di persone, ad esempio A-> C-> E-> A, e gli offset sono sempre gli stessi nei loop. Tuttavia, non è possibile prevedere l'output di una determinata esecuzione a meno che non si disponga di tale output.


Questa è l'interpretazione che intendevo (e sostanzialmente anche la soluzione su cui siamo arrivati).
Steve,

Dovrebbe essere 210. stai contando la nuova riga alla fine del file?
Gnibbler,

@gnibbler: probabilmente lo ero. Ho appena trasferito il file in wc, non ho intenzione di contarlo a mano.
Anon.

1
Che dire var n="Andy Barb Carl Didi Earl Fran".Split()? Salva 16 byte. È possibile tralasciare l'argomento in Main(), che consente di risparmiare altri 9 byte. E puoi combinare la dichiarazione di ce i: int c,i=...;for(c=0;...che ne salva altri due.
Joey,

@Joey: ottimizzato secondo i tuoi suggerimenti, grazie.
Anon.

0

Rubino - 89 caratteri

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

Produzione:

Andy buys for Didi
Barb buys for Earl
Fran buys for Carl
Carl buys for Fran
Earl buys for Barb
Didi buys for Andy

1
Puoi usare mapinvece di each.
Dogbert,

1
il problema con questa soluzione è che se hai un numero dispari di persone la persona di mezzo si regalerà Earl compra per Mark Fran compra per Andy Barb compra per Carl Didi compra per Didi Carl compra per Barb Andy compra per Fran Mark compra per Earl
StudleyJr

0

MathGolf , 41 byte

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

Provalo online!

Spiegazione

Questo non è garantito per produrre ogni caso con uguale probabilità, ma produce risultati diversi ad ogni corsa. Un byte potrebbe essere rimosso se avessi un operatore shuffle, ma è per un altro giorno.

"δ%è╘+µ√♂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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.