ホリデーギフト交換


11

私たちの社内ゴルフからのもう一つの問題...これは昨年の休暇中の問題です。

問題

アンディ、バーブ、カール、ディディ、アール、フランはお互いにプレゼントを買っています。ギフト交換の名前を描きます。

  1. 各人が1つのギフトを購入し、1つのギフトを受け取ります。
  2. 誰も自分の贈り物を買いません。
  3. ソリューションを複数回実行すると、異なる結果が得られます(実行者と受信者のペアが実行ごとに予測可能または同一であってはなりません)。

入力

なし。

出力

この例のようにフォーマット:

アンディはバーブのために買います
バーブはカールのために買います
カールは
ディディのために買いますディディは
アールのために買いますアールは
フランのために買いますフランはアンディのために買います


出力を名前でソートする必要がありますか?
— エルベックス

@Eelvexいいえ、必要ありません。
— スティーブ

1
これは今日の質問と重複しており、私が検索したキーワードは表示されなかったので、将来の検索では混乱です。
— ピーターテイラー

回答:


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文字の長さであるという事実を利用しています。わずかな変更でさまざまな長さで機能します。
— エルベックス

これはまた、偶数人の人々がいることを悪用します。XがYに与える場合、Yは常にXにも与えることに注意してください。
— アダム

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は%4smanページが言うように印刷指定子を扱っていないようです。

シャッフルは悪いですが、そのようにすると、「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

Windows 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) – アノンからアイデアを借りました。のC#ソリューション。ランダムオフセットを生成し、サークルにギフトを贈るだけです。
  • 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")!!)

完全にランダムな出力(まだ仕様を満たしている)。

これにより、名前のリストのすべての順列が生成され、ランダムに1つが選択されます(これはHaskellでリストをシャッフルする最短の方法だと思います。リスト内の次の人にプレゼント。


私はこれをアドホックに試しましたが、うまくいくかどうかはわかり
— FUZxxl

@Anon:permutations$words"Andy Barb Carl Didi Earl Fran"改良版で試したその他のトリック。忘れてしまいましたが、これpermutationsは98には含まれていないListので、長い名前を使用する必要があります。それを見てください。
— FUZxxl

そして、あなたの特別な目的のために:r=tail.cycle。インラインよりも。
— FUZxxl

それを降りて202の文字。ご覧
— FUZxxl

1
そして、のために189:文字、と私の例では第三行を置き換えるmain=randomRIO(0,719)>>=mapM_ putStrLn.f
— FUZxxl

3

Golfscript: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
  • に感謝し"AndyBarbCarlDidiEarlFran"4/、更新し、7文字少なくなりました
  • 57文字のソリューションは、基本的にNabb:Dによるものであり、これ;9randは私よりもランダムであることに気づきました6rand*

1
"AndyBarbCarlDidiEarlFran"4/
— ニブラー

ああ、@ gnibbler、ありがとう、更新してくれてありがとう。
— あなた

なぜ使用しているのかわからない6rand*- 0=randまたは多分;9rand望ましい。ループの場合{.n+\' buys for '}%(は短いです
— 。-ナブ

へー; Dとありがとう@Nabb、私が使用:同じ文字が今Jでカウントになった6rand*私は、それが均等に(私は以来、私が間違っていたと思う6つの項目の配列をランダム化しますと思ったので、;9rand私より本当にランダムなルックス)
— YOU

3

Japt -R、41バイト

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

@Oliverのおかげで-2バイト!

それを試してみてください!

これは私が高レベルで取ったアプローチです:

  • 参加者の名前を含む文字列を解凍します
  • 文字列を配列に分割します
  • シャッフル
  • 各人を次に高いインデックスを持つ人に割り当てる
  • 配列の最後の人が最初の人に割り当てられます

私は何年も前に仕事のために「秘密のサンタ」プログラムを作成したので、この問題について少し歴史があります。私たちはいくつかの求職者にそれを介して作業するように依頼することになりました:)


@Oliver-ヒントをありがとう!ã最初の要素と最後の要素をリンクするペアが返されていないようです。私はこれを機能させる方法に取り組んでいますが、あなたに知らせたいと思いました。どうもありがとう!ethproductions.github.io/japt/…–
— ダナ

43?
— ダナ

1
ああ、あなたは正しい。これは
— オリバー


何を待って"q"中に.ö("q")行う
— ASCIIのみ

2

Python-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]

Python-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

Python-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

おApび申し上げますが、私のPythonにはひどく欠けています...「XがXを買う」ことを回避する解決策が見つかるまで、基本的にループはループしますか?
— スティーブ

@Steve:それはほとんど何をするものです。LおよびMの対応する値の各ペアをmap呼び出しstr.__eq__ます。ループは、それらのいずれもtrueになるまで継続します。
— アノン。

@スティーブ、はい。おそらくjsutがレコードを1から5にランダムにシフトする方が短いかもしれませんが、それは問題の精神ではないと思います
— ニブラー

私が最初に職場で質問をしたとき、あなたはまったく正しい。私の同僚は、それが私の定義によって除外されていないことをすぐに指摘しました。
— スティーブ

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

2つの解決策のいずれかを提供します。

(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のように常に1つ以上の人の「ループ」があり、ループ内のオフセットは常に同じです。ただし、特定の実行の出力を予測することは、その出力の一部がない限り不可能です。


それが私が意図していた解釈です(そして基本的には私たちが着いた解決策でもあります)。
— スティーブ

210になるはずです。ファイルの最後で改行を数えていますか?
— ニブラー

@gnibbler:おそらくそうだった。ファイルをwcに入れただけで、実際には手動でカウントするつもりはありません。
— アノン。

1
どうvar n="Andy Barb Carl Didi Earl Fran".Split()?16バイトを節約します。の引数を省略してMain()、さらに9バイト節約できます。そして、あなたはの宣言組み合わせることができますcとi:int c,i=...;for(c=0;...別の2を節約できます。
— ジョーイ

@ジョーイ:あなたの提案に従ってそれを微調整しました、ありがとう。
— アノン。

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。
— ワイリーE.コヨーテ

1
このソリューションでの問題は、あなたが人々の奇数真ん中の人の意志の贈り物を持っている場合、自分自身伯爵のためのフランマークバイのためのバーブアンディ・バイのためのディディカール・バイのためのカール・ディディバイのためのアンディ・バーブ購入に適したマーク・フランの買いのためのアールバイ
— 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.