แลกเปลี่ยนของขวัญวันหยุด


11

ปัญหาอีกประการหนึ่งจากการเล่นกอล์ฟภายในของเรา ... ช่วงนี้เป็นวันหยุดปีที่แล้ว

ปัญหา

Andy, Barb, Carl, Didi, Earl และ Fran กำลังซื้อของขวัญให้กันและกัน วาดชื่อสำหรับแลกเปลี่ยนของขวัญ

  1. แต่ละคนซื้อของขวัญหนึ่งชิ้นและรับของขวัญหนึ่งชิ้น
  2. ไม่มีใครซื้อของขวัญของตัวเอง
  3. การรันโซลูชันหลายครั้งควรให้ผลลัพธ์ที่แตกต่างกัน (คู่ของตัวให้และตัวรับไม่ควรคาดเดาหรือเหมือนกันจากการรันเพื่อรัน)

INPUT

ไม่มี.

เอาท์พุท

จัดรูปแบบตามตัวอย่างนี้:

Andy ซื้อ Barb
Barb ซื้อ Carl
Carl ซื้อ Didi
Didi ซื้อ Earl
Earl ซื้อ Fran
Fran ซื้อ Andy


ควรเรียงลำดับผลลัพธ์ตามชื่อหรือไม่?
Eelvex

@Eevenx Nope ไม่จำเป็น
Steve

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 ตัวอักษร มันจะทำงานได้กับความยาวที่แตกต่างกันโดยมีการเปลี่ยนแปลงเพียงเล็กน้อย
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ได้ ฉันควรจะสามารถเคาะออกประมาณ 8 โดยการละเว้น\0ในสตริงใหญ่ แต่ libc ของฉันดูเหมือนจะไม่ได้เกี่ยวข้องกับ%4sspecifiers พิมพ์วิธีที่หน้าคนพูด

สับไม่ดี แต่ทำมันที่ป้องกันไม่ให้ฉันทางจากที่มีการตรวจสอบ"ซื้อ 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) - ยืมความคิดจากอานนท์ 's วิธีการแก้ปัญหา C # เพียงแค่สร้างการชดเชยแบบสุ่มแล้วปล่อยให้พวกเขาเป็นของขวัญในแวดวง
  • 2011-02-13 16:26    (83) - การสร้างหมายเลขสุ่มและการสร้างดัชนีแบบสุ่ม ดึงเป็นสตริงเพื่อบันทึก$_+

3

Haskell, 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 เพื่อสลับรายการ - ถ้าใครมีอะไรที่เล็กกว่าฉันจะขอบคุณมัน) จากนั้นแต่ละคนก็ซื้อ นำเสนอสำหรับบุคคลต่อไปในรายการ


ฉันลอง ad-hoc นี้แล้วฉันไม่คิดว่าจะทำงานได้หรือไม่: paste.ubuntuusers.de/399798
FUZxxl

@Anon: permutations$words"Andy Barb Carl Didi Earl Fran"และเทคนิคอื่น ๆ ที่ฉันลองในรุ่นปรับปรุงของฉัน ฉันลืมนั่นpermutationsไม่รวมอยู่ใน 98 Listดังนั้นคุณต้องใช้ชื่อยาวเช่นกัน ดูที่มัน
FUZxxl

และเพื่อจุดประสงค์พิเศษของคุณ: r=tail.cycle. และกว่าแบบอินไลน์
FUZxxl

รับลงไปที่202ตัวอักษร ลองดู: paste.ubuntuusers.de/399799
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
  • ขอบคุณ gnibbler สำหรับ"AndyBarbCarlDidiEarlFran"4/อัปเดตและลดลง 7 ตัวอักษร
  • วิธีแก้ปัญหา 57 ตัวโดย Nabb: D และยังสังเกตว่า;9randมันสุ่มกว่าของฉัน6rand*

1
"AndyBarbCarlDidiEarlFran"4/
gnibbler

อ้าฮ่า ๆ ขอบคุณ @gnibbler เจ๋งไปอัปเดต
คุณ

ไม่แน่ใจว่าทำไมคุณถึงใช้6rand*- 0=randหรืออาจ;9randจะดีกว่า สำหรับวงที่{.n+\' buys for '}%(สั้น ..
Nabb

หึ; กลายเป็นตัวอักษรเดียวกันนับกับ J ตอนนี้: D และขอขอบคุณ @Nabb ผมใช้6rand*เพราะผมคิดว่ามันจะสุ่มอย่างเท่าเทียมกัน 6 รายการอาร์เรย์ (ผมคิดว่าผมผิดตั้งแต่;9randรูปลักษณ์สุ่มจริงๆกว่าฉัน)
คุณ

3

Japt -R, 41 ไบต์

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

-2 ไบต์ขอบคุณ @Oliver!

ลองมัน!

นี่เป็นวิธีที่ฉันใช้ในระดับสูง:

  • คลายการบีบอัดสตริงที่มีชื่อผู้เข้าร่วม
  • แยกสตริงเป็นอาร์เรย์
  • สับเปลี่ยน
  • กำหนดแต่ละบุคคลให้กับบุคคลด้วยดัชนีสูงสุดถัดไป
  • บุคคลสุดท้ายในอาร์เรย์ได้รับมอบหมายให้เป็นคนแรก

ฉันมีประวัติเล็กน้อยเกี่ยวกับปัญหานี้ในขณะที่ฉันสร้างโปรแกรม "Secret santa" สำหรับงานของฉันเมื่อหลายปีก่อน เราได้ขอให้ผู้สมัครงานสองสามคนทำงานด้วยเช่นกัน :)


@Oliver - ขอบคุณสำหรับเคล็ดลับ! ดูเหมือนว่าãจะไม่ส่งคืนคู่ที่เชื่อมโยงองค์ประกอบแรกกับองค์ประกอบสุดท้าย ฉันกำลังพยายามหาทางทำงานให้ได้ แต่คิดว่าฉันจะบอกให้คุณรู้ ขอขอบคุณอีกครั้ง! ethproductions.github.io/japt/…
dana

43 ?
dana

1
อ่าคุณพูดถูก ฉันคิดว่าสิ่งนี้จะใช้ได้กับ 42
Oliver


รอสิ่ง"q"ที่.ö("q")ต้องทำ
ASCII-only

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

ขออภัย Python ของฉันขาดหายไปอย่างรุนแรง ... ขณะที่วนรอบนั้นวนซ้ำจนกว่าจะพบโซลูชันที่หลีกเลี่ยง "X ซื้อเพื่อ X" หรือไม่
Steve

@ Steve: นั่นมันทำอะไรได้สวย mapเรียกstr.__eq__ค่าที่สอดคล้องกันแต่ละคู่ใน L และ M และวนซ้ำไปเรื่อย ๆ จนกระทั่งไม่มีค่าใดเป็นจริง
อานนท์

@ Steve ใช่ แม้ว่ามันอาจจะสั้นกว่าที่จะ jsut เปลี่ยนระเบียนด้วยจำนวนสุ่มจาก 1 ถึง 5 แต่ฉันคิดว่านั่นไม่ใช่จิตวิญญาณของคำถาม
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

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

โครงการ, 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: ฉันอาจจะเป็น ฉันเพิ่ง catted ไฟล์เป็น wc ฉันจะไม่นับด้วยมือจริง ๆ
อานนท์

1
เกี่ยวกับvar n="Andy Barb Carl Didi Earl Fran".Split()อะไร บันทึก 16 ไบต์ คุณสามารถปล่อยอาร์กิวเมนต์ให้Main()ซึ่งจะบันทึกอีก 9 ไบต์ และคุณสามารถรวมการประกาศcและi: int c,i=...;for(c=0;...ซึ่งช่วยอีกสองอย่าง
Joey

@ Joey: tweaked มันตามคำแนะนำของคุณขอบคุณ
อานนท์

0

Ruby - 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
ปัญหาด้วยวิธีนี้คือว่าถ้าคุณมีเลขคี่ของคนขายของที่ระลึกคนจะอยู่ตรงกลางตัวเองซื้อเอิร์ลสำหรับซื้อมาร์คฟรานสำหรับซื้อแอนดี้เข็มสำหรับซื้อคาร์ล Didi สำหรับซื้อ Didi คาร์ลลวดหนามแอนดี้ซื้อสำหรับฟรานมาร์คซื้อสำหรับเอิร์ล
StudleyJr

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.