Troca de presentes de feriado


11

Outro problema do nosso golfe interno ... esse nos feriados do ano passado.

PROBLEMA

Andy, Barb, Carl, Didi, Earl e Fran estão comprando presentes um para o outro. Desenhe nomes para uma troca de presentes.

  1. Cada pessoa compra um presente e recebe um presente.
  2. Ninguém compra seu próprio presente.
  3. A execução da solução várias vezes deve produzir resultados diferentes (o par doador-receptor não deve ser previsível ou idêntico de uma corrida para outra).

ENTRADA

Nenhum.

RESULTADO

Formatado como neste exemplo:

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


A saída deve ser classificada por nome?
Eelvex

@ Eelvex Não, não é necessário.
1211 Steve Steve

1
Isso foi duplicado por uma pergunta hoje e a palavra-chave que eu procurei não apareceu, portanto, para pesquisas futuras: desarranjo.
Peter Taylor

Respostas:


4

J, 57

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

por exemplo

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

Eu não sei [J], mas isso funcionaria se os nomes tivessem comprimentos diferentes?
Zx8754

Não. O código explora o fato de que todos os nomes têm 4 caracteres. Funcionará para diferentes comprimentos, com muito poucas alterações.
Eelvex

Isso também explora que há um número par de pessoas. Note que se X der a Y, Y também dará a X também.
Adám 5/03/19

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

Ligeira melhoria, aproveitando a natureza circular da permutação. Essa versão sempre cria uma estratégia de compra semelhante a um loop, por isso é menos aleatória que a versão anterior (271 caracteres), mas acredito que ainda atende às especificações.

Requer uma plataforma que funcione /dev/random. Eu deveria ser capaz de eliminar cerca de 8 omitindo os \0s na string grande, mas minha libc não parece lidar com %4sespecificadores de impressão da maneira que a página de manual diz.

O embaralhamento é ruim, mas fazê-lo dessa maneira me impede de verificar as condições "Foo compra para Foo" .

Legível:

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

História:

  • 11-02-2011 22:01 (136) - Primeira tentativa.
  • 11-02-2011 22:05 (130) - Inline algumas coisas. Baralhar os nomes agora, não os índices.
  • 13-02-2011 16:13 (128) - Não preciso do módulo, pois $iele será recriado todas as vezes.
  • 13-02-2011 16:20    (87) - Emprestou a idéia da Anon. 's C # solução . Apenas gere um deslocamento aleatório e deixe-os presentear em círculos.
  • 13-02-2011 16:26    (83) - Mudança na geração e indexação de números aleatórios. Puxado $_na corda para salvar o +.

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

Saída totalmente aleatória (que ainda satisfaz as especificações).

Isso gera todas as permutações da lista de nomes, escolhe uma aleatoriamente ( acho que essa é a maneira mais curta de Haskell de embaralhar uma lista - se alguém tiver algo menor, eu apreciaria) e, em seguida, cada pessoa comprará um presente para a próxima pessoa na lista.


Eu tentei isso ad-hoc, eu não sou shure se ele funciona: paste.ubuntuusers.de/399798
FUZxxl

@ Anon: permutations$words"Andy Barb Carl Didi Earl Fran"e alguns outros truques que tentei na minha versão melhorada. Esqueci que isso permutationsnão está incluído no 98 List, então você também deve usar o nome longo. Dê uma olhada nisso.
FUZxxl

E para o seu propósito especial: r=tail.cycle. e que inline.
FUZxxl

Reduzi para 202 caracteres. Dê uma olhada: paste.ubuntuusers.de/399799
FUZxxl

1
E para 189 caracteres, substitua a terceira linha no meu exemplo por:main=randomRIO(0,719)>>=mapM_ putStrLn.f
FUZxxl

3

Golfscript: 72 64 57 caracteres

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

Testes

$ 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
  • Obrigado gnibbler por "AndyBarbCarlDidiEarlFran"4/, atualizado e tem 7 caracteres a menos
  • A solução de 57 caracteres é basicamente da Nabb: D, e também notei que ;9randé mais aleatória do que a minha6rand*

1
"AndyBarbCarlDidiEarlFran"4/
Gnibbler

ah ha, obrigado @gnibbler, legal, vou atualizá-lo.
VOCÊ

Não sei por que você está usando 6rand*- 0=randou talvez ;9randseja preferível. Para o circuito, {.n+\' buys for '}%(é mais curto ..
Nabb

heh; ficou mesmos caracteres contar com J agora: D e obrigado @Nabb, eu usei 6rand*porque eu pensei que vai igualmente embaralhar a matriz 6 itens (eu acho que eu estava errado, já que ;9randparece realmente aleatório do que a minha)
VOCÊ

3

Japt -R, 41 bytes

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

-2 bytes graças a @Oliver!

Tente!

Esta é a abordagem que adotei em alto nível:

  • descompacte uma sequência contendo os nomes dos participantes
  • dividir string em uma matriz
  • embaralhe
  • atribuir cada pessoa à pessoa com o próximo índice mais alto
  • a última pessoa na matriz é atribuída à primeira

Tenho um pouco de história com esse problema, pois criei um programa "segredo santa" para o meu trabalho anos atrás. Acabamos pedindo a alguns candidatos que trabalhem com isso também :)


@ Oliver - obrigado pelas dicas! Parece que ãnão está retornando um par que vincula o primeiro ao último elemento. Estou trabalhando em uma maneira de fazer isso funcionar, mas pensei em avisar. Mais uma vez obrigado! ethproductions.github.io/japt/…
dana

43 ?
dana

1
Ah, você está certo. Eu acho que isso funcionaria para 42
Oliver


Esperar o que faz o "q"no .ö("q")fazer
ASCII-only

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]

2

R - 85 caracteres

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

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

Desculpas, meu Python está gravemente ausente ... o loop while está basicamente em loop até encontrar uma solução que evite "X compra para X"?
113711 Steve Steve

@ Steve: Isso é muito bonito o que faz. mapchama str.__eq__cada par de valores correspondentes em L e M, e o loop continua até que nenhum deles seja verdadeiro.
Anon.

@ Steve, sim. embora seja provavelmente mais curto para jsut mudar os registros por um período aleatório de 1 a 5, eu acho que não é no espírito da questão
gnibbler

Quando fiz a pergunta no trabalho, você está exatamente certo. Meus colegas de trabalho rapidamente apontaram que não estava descartada pelas minhas definições ... então deixei como está ao postar aqui.
1111 Steve 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]);}

Mais legivelmente:

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

Esquema, 173

Oferece uma das duas soluções.

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

Montes de clichê :(

Essa solução não é totalmente aleatória - sempre há um ou mais "loops" de pessoas, por exemplo, A-> C-> E-> A, e as compensações são sempre as mesmas nos loops. No entanto, não é possível prever a saída de uma execução específica, a menos que você tenha parte dessa saída.


Essa é a interpretação que eu pretendia (e basicamente a solução em que pousamos).
1111 Steve Steve

Deve ser 210. você está contando a nova linha no final do arquivo?
Gnibbler

@gnibbler: eu provavelmente estava. Acabei de colocar o arquivo no wc, não vou contar isso à mão.
Anon.

1
Que tal var n="Andy Barb Carl Didi Earl Fran".Split()? Salva 16 bytes. Você pode deixar de fora o argumento para Main(), que salva outros 9 bytes. E você pode combinar a declaração de ce i: int c,i=...;for(c=0;...que salva outros dois.
Joey

@ Joey: Tweaked conforme suas sugestões, obrigado.
Anon.

0

Ruby - 89 caracteres

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

Resultado:

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
Você pode usar em mapvez de each.
Wile E. Coyote

1
o problema dessa solução é que, se você tiver um número ímpar de pessoas, a pessoa do meio se oferecerá Earl compra para Mark Fran compra para Andy Barb compra para Carl Didi compra para Carl Didi compra para Didi Carl compra para Barb Andy compra para Barb Andy compra para Fran Mark compra para Earl
Postado por Unknown

0

MathGolf , 41 bytes

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

Experimente online!

Explicação

Não é garantido que produza cada caso com igual probabilidade, mas produz resultados diferentes a cada execução. Um byte poderia ser removido se eu tivesse um operador de reprodução aleatória, mas isso é para outro dia.

"δ%è╘+µ√♂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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.