Trao đổi quà tặng ngày lễ


11

Một vấn đề khác từ việc chơi golf nội bộ của chúng tôi ... vấn đề này vào các ngày lễ năm ngoái.

VẤN ĐỀ

Andy, Barb, Carl, Didi, Earl và Fran đang mua quà cho nhau. Vẽ tên cho một trao đổi quà tặng.

  1. Mỗi người mua một món quà và nhận một món quà.
  2. Không ai mua quà tặng của riêng họ.
  3. Chạy giải pháp nhiều lần sẽ tạo ra các kết quả khác nhau (cặp người nhận-người nhận không nên dự đoán hoặc giống hệt nhau từ khi chạy sang chạy).

ĐẦU VÀO

Không ai.

ĐẦU RA

Được định dạng như trong ví dụ này:

Andy mua cho Barb
Barb mua cho Carl
Carl mua cho Didi
Didi mua cho Earl
Earl mua cho Fran
Fran mua cho Andy


Có nên sắp xếp đầu ra theo tên?
Eelvex

@Eelvex Không, không cần thiết.
Steve

1
Điều này đã được nhân đôi bởi một câu hỏi ngày hôm nay và từ khóa tôi đã tìm kiếm không bật nó lên, vì vậy cho các tìm kiếm trong tương lai: loạn trí.
Peter Taylor

Câu trả lời:


4

J, 57

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

ví dụ

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

Tôi không biết [J], nhưng điều này có hiệu quả không nếu các tên có độ dài khác nhau?
zx8754

Không. Mã khai thác thực tế là tất cả các tên dài 4 ký tự. Nó sẽ hoạt động với các độ dài khác nhau với rất ít thay đổi.
Eelvex

Điều này cũng khai thác rằng có một số lượng người chẵn. Lưu ý rằng nếu X đưa cho Y, Y cũng sẽ luôn cung cấp cho X.
Adám

3

c99 - 252 ký tự

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

Cải thiện nhẹ bằng cách tận dụng tính chất vòng tròn của hoán vị. Phiên bản này luôn xây dựng chiến lược mua giống như vòng lặp, vì vậy nó ít ngẫu nhiên hơn phiên bản trước (271 ký tự), nhưng tôi tin rằng nó vẫn đáp ứng được thông số kỹ thuật.

Yêu cầu một nền tảng có hoạt động /dev/random. Tôi đã có thể loại bỏ khoảng 8 bằng cách bỏ qua các \0s trong chuỗi lớn, nhưng libc của tôi dường như không xử lý các công %4scụ in ấn theo cách mà trang man nói.

Shuffle là xấu, nhưng làm theo cách đó ngăn tôi khỏi phải kiểm tra các điều kiện "Foo mua cho Foo" .

Có thể đọc được

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

Lịch sử:

  • 2011/02/11 22:01 (136) - Nỗ lực đầu tiên.
  • 2011/02/11 22:05 (130) - Đã nêu một vài điều. Xáo trộn các tên bây giờ, không phải các chỉ mục.
  • 2011/02/13 16:13 (128) - Tôi không cần mô-đun như $isẽ được tạo lại mỗi lần.
  • 2011/02/13 16:20    (87) - Mượn ý tưởng từ Anon. 's C # giải pháp . Chỉ cần tạo một phần bù ngẫu nhiên và sau đó chỉ để cho họ quà tặng trong vòng tròn.
  • 2011/02/13 16:26    (83) - Thay đổi việc tạo và lập chỉ mục số ngẫu nhiên. Kéo $_vào chuỗi để lưu +.

3

Haskell, 241 189 ký tự

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

Đầu ra hoàn toàn ngẫu nhiên (vẫn đáp ứng thông số kỹ thuật).

Điều này tạo ra tất cả các hoán vị của danh sách các tên, chọn một cách ngẫu nhiên (tôi nghĩ đây là cách ngắn nhất trong Haskell để xáo trộn danh sách - nếu bất cứ ai có bất cứ điều gì nhỏ hơn, tôi sẽ đánh giá cao nó), và sau đó mỗi người mua một trình bày cho người tiếp theo trong danh sách.


Tôi đã thử quảng cáo này, tôi không chắc nó có hoạt động hay không: paste.ubfoxusers.de/399798
FUZxxl

@Anon: permutations$words"Andy Barb Carl Didi Earl Fran"và một số thủ thuật khác tôi đã thử trong phiên bản cải tiến của mình. Tôi quên mất, điều đó permutationskhông có trong 98 List, vì vậy bạn cũng phải sử dụng tên dài. Có một cái nhìn vào nó.
FUZxxl

Và cho mục đích đặc biệt của bạn : r=tail.cycle. và hơn là nội tuyến nó.
FUZxxl

Có nó xuống tới 202 ký tự. Có một cái nhìn: paste.ubfoxusers.de/399799
FUZxxl

1
Và với 189 ký tự, thay thế dòng thứ ba trong ví dụ của tôi bằng:main=randomRIO(0,719)>>=mapM_ putStrLn.f
FUZxxl

3

Golfscript: 72 64 57 ký tự

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

Xét nghiệm

$ 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
  • Cảm ơn gnibbler đã "AndyBarbCarlDidiEarlFran"4/cập nhật và nhận được 7 ký tự ít hơn
  • Giải pháp chars 57 về cơ bản là bởi Nabb: D, và cũng nhận thấy rằng ;9randnó ngẫu nhiên hơn so với của tôi6rand*

1
"AndyBarbCarlDidiEarlFran"4/
gnibbler

ah ha, cảm ơn bạn @gnibbler, tuyệt, sẽ cập nhật nó.
BẠN

Không chắc chắn tại sao bạn đang sử dụng 6rand*- 0=randhoặc có thể ;9randlà tốt hơn. Đối với vòng lặp, {.n+\' buys for '}%(ngắn hơn ..
Nabb

heh; trở nên giống chars đếm với J bây giờ: D và cảm ơn bạn @Nabb, tôi sử dụng 6rand*bởi vì tôi nghĩ nó sẽ không kém phần ngẫu nhiên mảng 6 mục (Tôi nghĩ rằng tôi đã sai, vì ;9randngoại hình thực sự ngẫu nhiên hơn tôi)
BẠN

3

Japt -R, 41 byte

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

-2 byte nhờ @Oliver!

Thử nó!

Đây là cách tiếp cận tôi đã thực hiện ở mức cao:

  • giải nén một chuỗi chứa tên người tham gia
  • chia chuỗi thành một mảng
  • xáo trộn nó
  • chỉ định mỗi người cho người có chỉ số cao nhất tiếp theo
  • người cuối cùng trong mảng được gán cho người đầu tiên

Tôi có một chút lịch sử với vấn đề này khi tôi tạo ra một chương trình "santa bí mật" cho công việc của tôi nhiều năm trước. Cuối cùng chúng tôi cũng yêu cầu một vài người xin việc cũng làm việc đó :)


@Oliver - cảm ơn vì lời khuyên! Có vẻ như ãkhông trả lại một cặp liên kết đầu tiên đến yếu tố cuối cùng. Tôi đang làm việc để làm cho điều này hoạt động, nhưng nghĩ rằng tôi sẽ cho bạn biết. Cảm ơn một lần nữa! ethproductions.github.io/japt/ từ
dana

43 ?
dana

1
À, bạn nói đúng. Tôi nghĩ rằng điều này sẽ làm việc cho 42
Oliver


Chờ những gì hiện các "q"trong .ö("q")việc phải làm
ASCII chỉ

2

Python - 118 ký tự

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 ký tự

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 ký tự

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

1

Python - 154 ký tự

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

Xin lỗi, Python của tôi đang thiếu trầm trọng ... là vòng lặp while có vòng lặp cơ bản cho đến khi nó tìm ra giải pháp tránh "X mua cho X"?
Steve

@Steve: Đó là khá nhiều những gì nó làm. mapcác cuộc gọi str.__eq__trên mỗi cặp giá trị tương ứng trong L và M và vòng lặp sẽ tiếp tục cho đến khi không có giá trị nào đúng.
Anon.

@Steve, vâng. mặc dù có thể ngắn hơn để jsut thay đổi các bản ghi theo số lượng ngẫu nhiên từ 1 đến 5, nhưng tôi nghĩ đó không phải là tinh thần của câu hỏi
gnibbler

Khi tôi lần đầu tiên đặt câu hỏi tại nơi làm việc, bạn hoàn toàn chính xác. Các đồng nghiệp của tôi nhanh chóng chỉ ra rằng nó không bị loại trừ bởi các định nghĩa của tôi ... vì vậy tôi đã để nó như khi đăng ở đây.
Steve

1

D: 233 ký tự

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

Dễ đọc hơn:

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

Con trăn (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

Đề án, 173

Đưa ra một trong hai giải pháp.

(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 ký tự

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

Hàng đống nồi hơi :(

Giải pháp này không hoàn toàn ngẫu nhiên - luôn có một hoặc nhiều "vòng lặp" của mọi người, ví dụ A-> C-> E-> A và các độ lệch luôn giống nhau trong các vòng lặp. Tuy nhiên, không thể dự đoán đầu ra của một lần chạy cụ thể trừ khi bạn có một phần của đầu ra đó.


Đó là cách giải thích mà tôi dự định (và về cơ bản là giải pháp chúng tôi cũng tìm đến).
Steve

Nên là 210. bạn đang đếm dòng mới ở cuối tập tin phải không?
gnibbler

@gnibbler: Có lẽ là tôi. Tôi chỉ trích dẫn tập tin vào wc, tôi sẽ không thực sự đếm nó bằng tay.
Anon.

1
Thế còn var n="Andy Barb Carl Didi Earl Fran".Split()? Lưu 16 byte. Bạn có thể bỏ qua đối số để Main()lưu thêm 9 byte. Và bạn có thể kết hợp khai báo ci: int c,i=...;for(c=0;...giúp tiết kiệm hai cái khác.
Joey

@Joey: Tinh chỉnh nó theo đề xuất của bạn, cảm ơn.
Anon.

0

Ruby - 89 ký tự

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

Đầu ra:

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
Bạn có thể sử dụng mapthay vì each.
Wile E. Coyote

1
Vấn đề với giải pháp này là nếu bạn có một số người lẻ, người trung lưu sẽ tự tặng Earl mua cho Mark Fran mua cho Andy Barb mua cho Carl Didi mua cho Didi Carl mua cho Barb Andy mua cho Fran Mark mua cho Earl
StudleyJr

0

MathGolf , 41 byte

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

Hãy thử trực tuyến!

Giải trình

Điều này không được đảm bảo để tạo ra mỗi trường hợp với xác suất bằng nhau, nhưng nó tạo ra kết quả khác nhau cho mỗi lần chạy. Một byte có thể bị xóa nếu tôi có toán tử trộn, nhưng đó là cho một ngày khác.

"δ%è╘+µ√♂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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.