휴일 선물 교환


11

우리 내부 골프의 또 다른 문제는 작년 연말 연시입니다.

문제

Andy, Barb, Carl, Didi, Earl 및 Fran은 서로를위한 선물을 구매하고 있습니다. 선물 교환의 이름을 그리십시오.

  1. 각 사람은 하나의 선물을 사고 하나의 선물을받습니다.
  2. 아무도 자신의 선물을 사지 않습니다.
  3. 솔루션을 여러 번 실행하면 다른 결과가 생성됩니다 (여러-수신자 쌍은 실행마다 예측 가능하거나 동일하지 않아야 함).

입력

없음

산출

이 예와 같이 형식이 지정되었습니다.

바브에 대한 앤디의 구매
칼에 대한 바브 구매
디디에 대한 칼의 구매
얼에 대한 디디 구매
프랜에 대한 얼 구매
앤디에 대한 프랜의 구매


출력을 이름별로 정렬해야합니까?
Eelvex

@Eelvex Nope는 필요하지 않습니다.
Steve

1
이것은 오늘 질문에 의해 복제되었으며 내가 검색 한 키워드가 그것을 켜지지 않았으므로 나중에 검색 할 때 : derangement.
피터 테일러

답변:


4

J, 57

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

예 :

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

[J]를 모르지만 이름의 길이가 다른 경우이 기능이 작동합니까?
zx8754

코드는 모든 이름의 길이가 4 자라는 사실을 이용합니다. 약간의 변화만으로도 다른 길이로 작동합니다.
Eelvex

이것은 또한 짝수의 사람들이 있다는 것을 이용합니다. X가 Y를 주면 Y도 항상 X도주게됩니다.
Adám

3

c99-252 자

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

순열의 순환 특성을 활용하여 약간의 개선. 이 버전은 항상 루프와 같은 구매 전략을 구축하므로 이전 (271 자) 버전보다 덜 무작위 적이지만 여전히 사양을 충족한다고 생각합니다.

작동하는 플랫폼이 필요합니다 /dev/random. 나는 \0큰 문자열에서 s를 생략하여 약 8을 깰 수 있어야 하지만 내 libc는 %4s매뉴얼 페이지가 말하는 방식 으로 인쇄 지정자를 다루지 않는 것 같습니다 .

셔플은 나쁘지만, 그렇게하면 "Foo buys for Foo" 조건 을 확인하지 않아도됩니다 .

읽을 수있는 :

#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

윈도우 PowerShell, 83

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

역사:

  • 2011-02-11 22:01 (136) – 첫 번째 시도.
  • 2011-02-11 22:05 (130) – 몇 가지 인라인. 색인이 아닌 이름을 섞습니다.
  • 2011-02-13 16:13 (128)$i매번 다시 생성 할 모듈러스가 필요하지 않습니다 .
  • 2011-02-13 16:20    (87)Anon 의 아이디어를 차용했습니다 . '에스 C # 1 용액 . 임의의 오프셋을 생성 한 다음 서클로 선물하십시오.
  • 2011-02-13 16:26    (83) – 난수 생성 및 색인이 변경되었습니다. $_문자열을 잡아 당겨 저장합니다 +.

3

하스켈, 241 189 자

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

완전 임의 출력 (사양을 여전히 만족함).

이것은 이름 목록의 모든 순열을 생성하고 무작위로 하나를 선택합니다 ( 이것은 Haskell에서 목록을 셔플하는 가장 짧은 방법 이라고 생각 합니다-사람이 더 작은 것이 있으면 감사하겠습니다). 목록에서 다음 사람에게 선물합니다.


나는이 임시 시도, 그것이 작동 여부는 확실
FUZxxl

@Anon : permutations$words"Andy Barb Carl Didi Earl Fran"개선 된 버전에서 시도한 몇 가지 다른 트릭. permutations98에 포함되지 않은 것을 잊었 List으므로 긴 이름을 사용해야합니다. 한번보세요
FUZxxl

그리고 당신의 특별한 목적을 위해 : r=tail.cycle. 인라인보다.
FUZxxl

그것을 꿇고 202 개 문자. 살펴보기 : paste.ubuntuusers.de/399799
FUZxxl

1
그리고 189main=randomRIO(0,719)>>=mapM_ putStrLn.f
자인 경우

3

골프 스크립트 : 72 64 57 자

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

테스트

$ 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
  • 감사합니다 gnibbler "AndyBarbCarlDidiEarlFran"4/ , 업데이트 및 7 자 이하
  • 57 문자 솔루션은 기본적으로 Nabb : D에 의해 이루어졌으며 또한 ;9rand내 것보다 더 무작위 임을 알았 습니다.6rand*

1
"AndyBarbCarlDidiEarlFran"4/
gnibbler

아 하, 감사합니다 @gnibbler, 멋진, 그것을 업데이트하려고합니다.
YOU

아니 당신이 사용하고있는 이유 6rand*- 0=rand또는 어쩌면 ;9rand바람직하다. 루프의 경우 {.n+\' buys for '}%(더 짧습니다.
Nabb

허; 내가 사용, D를 당신에게 @Nabb 감사합니다 : 같은 문자는 이제 J로 계산되었다 6rand*(이후, 내가 잘못 생각 나는 그것은 동일하게 6 개 항목의 배열을 무작위 것입니다 생각했기 때문에 ;9rand나보다 정말 무작위 모양)
당신

3

Japt -R, 41 바이트

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

@Oliver 덕분에 -2 바이트!

시도 해봐!

이것은 내가 높은 수준에서 취한 접근법입니다.

  • 참가자 이름이 포함 된 문자열을 압축 해제
  • 문자열을 배열로 나누기
  • 셔플
  • 다음으로 가장 높은 색인을 가진 사람에게 각 사람을 할당
  • 배열의 마지막 사람이 첫 번째 사람에게 할당됩니다.

몇 년 전 직장에서 "비밀 산타"프로그램을 만들면서이 문제에 대한 역사가 조금 있습니다. 우리는 몇 명의 구직 신청자에게도 그것을 요청했습니다. :)


@Oliver-팁 주셔서 감사합니다! ã첫 번째 요소와 마지막 요소를 연결하는 쌍을 반환하지 않는 것 같습니다 . 이 작업을 수행하는 방법을 찾고 있지만 알려 드릴 것입니다. 그래도 다시 감사합니다! ethproductions.github.io/japt/…
dana

43 ?
dana

1
아 맞아. 나는 이것이 42
Oliver


을 무엇을 기다리 "q".ö("q")할 일
ASCII 전용

2

파이썬-118 자

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]

파이썬-120 자

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]


1

파이썬-154 자

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

사과, 내 파이썬은 심각하게 부족합니다 ... while 루프는 기본적으로 "X buys for X"를 피하는 솔루션을 찾을 때까지 반복됩니까?
Steve

@Steve : 그것이하는 일과 거의 같습니다. L과 M의 대응하는 값의 각 쌍을 map호출 str.__eq__하고 루프가 참이 될 때까지 계속 진행합니다.
아논.

@ 스티브. 레코드를 1에서 5로 임의의 양으로 jsut하는 것이 더 짧을 지 모르지만, 나는 그것이 문제의 정신에 있지 않다고 생각합니다.
gnibbler

내가 직장에서 처음 질문을했을 때, 당신은 옳습니다. 내 동료들은 내 정의에 의해 배제되지 않았다는 것을 신속하게 지적했습니다 ... 그래서 여기에 게시 할 때 그대로 두었습니다.
Steve

1

D : 233 자

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

더 읽기 :

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

파이썬 (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

계획, 173

두 가지 솔루션 중 하나를 제공합니다.

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

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

상용구의 힙 :(

이 솔루션은 완전히 임의적이지는 않습니다. 예를 들어 A-> C-> E-> A와 같은 사람들의 "루프"는 항상 하나 이상 있으며 오프셋은 항상 루프에서 동일합니다. 그러나 특정 출력의 일부가 없으면 특정 실행의 출력을 예측할 수 없습니다.


그것이 내가 의도 한 해석입니다 (그리고 기본적으로 우리가 착륙 한 솔루션).
Steve

210이어야합니다. 파일 끝에서 줄 바꿈을 계산합니까?
gnibbler

@gnibbler : 아마 그랬을 것입니다. 방금 파일을 화장실에 넣었습니다. 실제로 손으로 계산하지는 않습니다.
아논.

1
무엇에 대해 var n="Andy Barb Carl Didi Earl Fran".Split()? 16 바이트를 저장합니다. 에 대한 인수를 생략하면 Main()9 바이트가 더 절약됩니다. 그리고 : c와 선언을 결합하여 다른 두 가지를 절약 할 수 있습니다 . iint c,i=...;for(c=0;...
Joey

@Joey : 제안에 따라 조정했습니다. 감사합니다.
아논.

0

루비-89 자

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

산출:

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
map대신 사용할 수 있습니다 each.
Dogbert

1
이 솔루션의 문제점은 홀수의 사람들이 있다면 중개인이 스스로 선물 할 것입니다. Mark Fran을위한 Earl 구매 Andy and를위한 Barb 구매 Didi를위한 Carl 구매 Didi는 Barb를위한 구매 Andy는 Fran을위한 Fran Mark 구매
StudleyJr

0

MathGolf , 41 바이트

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

온라인으로 사용해보십시오!

설명

이것은 각각의 경우에 동일한 확률로 생성되는 것을 보장하지는 않지만, 매 실행마다 다른 결과를 생성합니다. 셔플 연산자가 있으면 1 바이트를 제거 할 수 있지만 다른 날입니다.

"δ%è╘+µ√♂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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.