我们内部打高尔夫球的另一个问题...去年假期前后。
问题
安迪(Andy),巴布(Barb),卡尔(Carl),迪迪(Didi),伯爵(Earl)和弗兰(Fran)正在互相购买礼物。画出礼物交换的名字。
- 每个人买一份礼物并收到一份礼物。
- 没有人买自己的礼物。
- 多次运行解决方案应产生不同的结果(不同运行之间给与接收器对不可预测或相同)。
输入
没有。
输出值
格式如下例所示:
安迪买了倒钩
卡尔倒钩购买
了迪迪卡尔购买
厄尔-迪迪购买
弗兰伯爵购买
安迪弗兰购买
我们内部打高尔夫球的另一个问题...去年假期前后。
安迪(Andy),巴布(Barb),卡尔(Carl),迪迪(Didi),伯爵(Earl)和弗兰(Fran)正在互相购买礼物。画出礼物交换的名字。
没有。
格式如下例所示:
安迪买了倒钩
卡尔倒钩购买
了迪迪卡尔购买
厄尔-迪迪购买
弗兰伯爵购买
安迪弗兰购买
Answers:
(,.' 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
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]);
}
$i=random 5
($n=-split'Andy Barb Carl Didi Earl Fran')|%{"$_ buys for "+$n[++$i%6]}
历史:
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整理列表的最短方法-如果有人较小,我将不胜感激),然后每个人都购买一个为列表中的下一个人呈现。
permutations$words"Andy Barb Carl Didi Earl Fran"
以及我在改进版本中尝试过的其他技巧。我忘记了,那permutations
不包括在98中List
,所以您也必须使用长名。看看它。
r=tail.cycle
。而不是内联。
main=randomRIO(0,719)>>=mapM_ putStrLn.f
"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个字符;9rand
比我的随机性更大6rand*
"AndyBarbCarlDidiEarlFran"4/
6rand*
- 0=rand
也许;9rand
是更好的选择。对于环,{.n+\' buys for '}%(
是..短
6rand*
因为我认为它将同等地随机分配6个项目数组(我认为我错了,因为;9rand
看起来确实比我的随机)
`AÌ)B¼C¤E¤FÎÂDi¹`qe ö¬ê1 ò mq` ¿ys f
-2个字节感谢@Oliver!
这是我在较高层次上采取的方法:
几年前,我为自己的工作创建了一个“秘密圣诞老人”程序,因此我对这个问题有一点了解。我们最终要求一些求职者也要完成它:)
ã
并没有返回将第一个链接到最后一个元素的对。我正在研究一种使它起作用的方法,但是我想让您知道。再次感谢!ethproductions.github.io/japt/…–
"q"
在.ö("q")
做
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
map
调用str.__eq__
L和M中的每对对应值,然后循环一直进行到它们都不为真为止。
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]);
}
提供两种解决方案之一。
(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)))
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,并且循环中的偏移量始终相同。但是,除非您有一部分输出,否则无法预测特定运行的输出。
var n="Andy Barb Carl Didi Earl Fran".Split()
呢 节省16个字节。您可以省略参数Main()
,以节省另外9个字节。你可以结合的申报c
和i
:int c,i=...;for(c=0;...
节省了另外两个。
(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
map
代替each
。
"δ%è╘+µ√♂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