节日礼物交换


11

我们内部打高尔夫球的另一个问题...去年假期前后。

问题

安迪(Andy),巴布(Barb),卡尔(Carl),迪迪(Didi),伯爵(Earl)和弗兰(Fran)正在互相购买礼物。画出礼物交换的名字。

  1. 每个人买一份礼物并收到一份礼物。
  2. 没有人买自己的礼物。
  3. 多次运行解决方案应产生不同的结果(不同运行之间给与接收器对不可预测或相同)。

输入

没有。

输出值

格式如下例所示:

安迪买了倒钩
卡尔倒钩购买
了迪迪卡尔购买
厄尔-迪迪购买
弗兰伯爵购买
安迪弗兰购买


输出应该按名称排序吗?
Eelvex 2011年

@Eelvex不,不是必需的。
史蒂夫

1
今天,这个问题被一个问题重复了,我搜索的关键字没有显示出来,所以对于以后的搜索:混乱。
彼得·泰勒

Answers:


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 '16

否。该代码利用了所有名称均为4个字符长的事实。只需很少的更改,它即可适用于不同的长度。
Eelvex

这还利用了偶数的人。请注意,如果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似乎没有像%4s手册页所说的那样处理打印说明符。

洗牌是不好的,但是这样做避免了我不得不检查“ Foo为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) –借用了Anon的想法C#解决方案。只需生成一个随机偏移量,然后让他们圈出礼物即可。
  • 2011-02-13 16:26    (83) –更改了随机数的生成和索引。拉$_入字符串以保存+

3

Haskell,241189个字符

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整理列表的最短方法-如果有人较小,我将不胜感激),然后每个人都购买一个为列表中的下一个人呈现。


我尝试了这个临时方法,我不确定它是否有效:paste.ubuntuusers.de/399798
FUZxxl 2011年

@Anon:permutations$words"Andy Barb Carl Didi Earl Fran"以及我在改进版本中尝试过的其他技巧。我忘记了,那permutations不包括在98中List,所以您也必须使用长名。看看它。
FUZxxl 2011年

并且为了您的特殊目的:r=tail.cycle。而不是内联。
FUZxxl 2011年

降至202个字符。看看:paste.ubuntuusers.de/399799
FUZxxl 2011年

1
对于189个字符,将示例中的第三行替换为:main=randomRIO(0,719)>>=mapM_ putStrLn.f
FUZxxl 2011年

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
  • 感谢gnibbler的"AndyBarbCarlDidiEarlFran"4/更新,并减少了7个字符
  • 57个字符的解决方案基本上是由Nabb:D提出的,并且还注意到它;9rand比我的随机性更大6rand*

1
"AndyBarbCarlDidiEarlFran"4/
gnibbler 2011年

啊哈,谢谢@gnibbler,太酷了,准备更新它。

不知道为什么要使用6rand*- 0=rand也许;9rand是更好的选择。对于环,{.n+\' buys for '}%(是..短
Nabb

h 现在变成了与J相同的字符计数:D并感谢@Nabb,我用过,6rand*因为我认为它将同等地随机分配6个项目数组(我认为我错了,因为;9rand看起来确实比我的随机)
YOU

3

Japt -R,41个字节

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

-2个字节感谢@Oliver!

尝试一下!

这是我在较高层次上采取的方法:

  • 解压缩包含参与者名称的字符串
  • 将字符串拆分为数组
  • 洗牌
  • 将每个人分配给索引次高的人
  • 数组中的最后一个人被分配给第一个

几年前,我为自己的工作创建了一个“秘密圣诞老人”程序,因此我对这个问题有一点了解。我们最终要求一些求职者也要完成它:)


@Oliver-感谢您的提示!似乎ã并没有返回将第一个链接到最后一个元素的对。我正在研究一种使它起作用的方法,但是我想让您知道。再次感谢!ethproductions.github.io/japt/…–
dana

43
丹娜

1
啊,你是对的。我认为这将适用于42
Oliver


等待什么是"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]

2

R-85个字符

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

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

抱歉,我的Python严重缺乏...在那儿,while循环基本上一直在循环,直到找到避免“ X为X买进”的解决方案为止?
史蒂夫

@Steve:这差不多就是它的作用。map调用str.__eq__L和M中的每对对应值,然后循环一直进行到它们都不为真为止。
Anon。

@Steve,是的。尽管将记录随机从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

提供两种解决方案之一。

(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#,210183个字符

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,并且循环中的偏移量始终相同。但是,除非您有一部分输出,否则无法预测特定运行的输出。


那就是我想要的解释(基本上也是我们找到的解决方案)。
史蒂夫,

应该是210。您要在文件末尾计算换行符吗?
gnibbler 2011年

@gnibbler:我可能是。我只是将文件添加到了wc中,我并不是真的要手工计算。
Anon。

1
var n="Andy Barb Carl Didi Earl Fran".Split()呢 节省16个字节。您可以省略参数Main(),以节省另外9个字节。你可以结合的申报ciint c,i=...;for(c=0;...节省了另外两个。
Joey

@Joey:根据您的建议进行了调整,谢谢。
Anon。

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
该解决方案的问题是,如果您的人数过多,那么中间人会给自己送礼物,伯爵为马克·弗兰买,安迪·巴布为卡尔·迪迪买,狄迪·卡尔为巴蒂买,安迪·弗兰·马克为弗兰·马克买,为伯爵
StudleyJr 2012年

0

MathGolf,41字节

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

在线尝试!

说明

不能保证以相同的概率产生每种情况,但是每次运行确​​实会产生不同的结果。如果我使用洗牌运算符,则可以删除一个字节,但这是另一天的事情。

"δ%è╘+µ√♂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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.