Pertukaran Hadiah Liburan

11

Masalah lain dari golf internal kita ... yang ini sekitar liburan tahun lalu.

MASALAH

Andy, Barb, Carl, Didi, Earl, dan Fran saling membeli hadiah. Gambarlah nama untuk pertukaran hadiah.

  1. Setiap orang membeli satu hadiah dan menerima satu hadiah.
  2. Tidak ada yang membeli hadiah mereka sendiri.
  3. Menjalankan solusi beberapa kali akan menghasilkan hasil yang berbeda (pasangan pemberi-penerima tidak dapat diprediksi atau identik dari lari ke lari).

MEMASUKKAN

Tidak ada

KELUARAN

Diformat seperti dalam contoh ini:

Andy membeli untuk Barb
Barb membeli untuk Carl
Carl membeli untuk Didi
Didi membeli untuk Earl
Earl membeli untuk Fran
Fran membeli untuk Andy

Steve
sumber
Haruskah output diurutkan berdasarkan nama?
Eelvex
@Eelvex Tidak, tidak perlu.
Steve
1
Ini digandakan oleh pertanyaan hari ini dan kata kunci yang saya cari tidak muncul, jadi untuk pencarian selanjutnya: kekacauan.
Peter Taylor

Jawaban:

4

J, 57

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

misalnya

   (,.' 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
Eelvex
sumber
Saya tidak tahu [J], tetapi apakah ini akan berhasil jika nama-nama memiliki panjang yang berbeda?
zx8754
Tidak. Kode mengeksploitasi fakta bahwa semua nama panjangnya 4 karakter. Ini akan bekerja untuk panjang yang berbeda dengan sedikit perubahan.
Eelvex
Ini juga mengeksploitasi bahwa ada jumlah orang yang genap. Perhatikan bahwa jika X memberi kepada Y, Y akan selalu memberi kepada X juga.
Adám
3

c99 - 252 karakter

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

Perbaikan sedikit dengan mengambil keuntungan dari sifat melingkar permutasi. Versi ini selalu membangun strategi pembelian seperti loop, jadi ini kurang acak daripada versi (271 karakter) sebelumnya, tapi saya percaya masih memenuhi spesifikasi.

Membutuhkan platform yang berfungsi /dev/random. Saya seharusnya bisa mengetuk sekitar 8 dengan menghilangkan huruf \0s dalam string besar, tetapi libc saya tampaknya tidak berurusan dengan %4spenspesifikasi cetak seperti yang dikatakan halaman manual.

Acak itu buruk, tetapi melakukannya dengan cara mencegah saya dari harus memeriksa kondisi "Foo membeli untuk Foo" .

Dapat dibaca:

#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]);
}
dmckee --- mantan kucing moderator
sumber
3

Windows PowerShell, 83

$i=random 5
($n=-split'Andy Barb Carl Didi Earl Fran')|%{"$_ buys for "+$n[++$i%6]}

Sejarah:

  • 2011-02-11 22:01 (136) - Upaya pertama.
  • 2011-02-11 22:05 (130) - Menguraikan beberapa hal. Mengacak nama sekarang, bukan indeks.
  • 2011-02-13 16:13 (128) - Saya tidak perlu modulus karena $iakan dibuat ulang setiap saat.
  • 2011-02-13 16:20    (87) - Meminjam gagasan dari Anon. 's C # solusi . Hanya menghasilkan offset acak dan kemudian biarkan mereka hadiah dalam lingkaran.
  • 2011-02-13 16:26    (83) - Mengubah pembuatan dan pengindeksan angka acak. Ditarik $_ke dalam string untuk menyimpan +.
Joey
sumber
3

Haskell, 241 189 karakter

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

Output sepenuhnya acak (yang masih memenuhi spesifikasi).

Ini menghasilkan semua permutasi daftar nama, mengambil satu secara acak (saya pikir ini adalah cara terpendek di Haskell untuk mengacak daftar - jika ada yang memiliki sesuatu yang lebih kecil, saya akan menghargai itu), dan kemudian setiap orang kemudian membeli sebuah hadir untuk orang berikutnya dalam daftar.

Segera.
sumber
Saya mencoba ad-hoc ini, saya tidak tahu apakah itu berfungsi: paste.ubuntuusers.de/399798
FUZxxl
@ Anon: permutations$words"Andy Barb Carl Didi Earl Fran"dan beberapa trik lain yang saya coba dalam versi saya yang ditingkatkan. Saya lupa, itu permutationstidak termasuk dalam 98 List, jadi Anda harus menggunakan nama panjang juga. Lihat itu.
FUZxxl
Dan untuk tujuan khusus Anda: r=tail.cycle. dan dari inline itu.
FUZxxl
Turun ke 202 karakter. Lihat: paste.ubuntuusers.de/399799
FUZxxl
1
Dan untuk 189 karakter, ganti baris ketiga dalam contoh saya dengan:main=randomRIO(0,719)>>=mapM_ putStrLn.f
FUZxxl
3

Golfscript: 72 64 57 karakter

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

Tes

$ 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
  • Terima kasih gnibbler untuk "AndyBarbCarlDidiEarlFran"4/, diperbarui dan mendapat 7 karakter lebih sedikit
  • Solusi 57 chars pada dasarnya adalah oleh Nabb: D, dan juga memperhatikan bahwa ;9randini lebih acak daripada saya6rand*
KAMU
sumber
1
"AndyBarbCarlDidiEarlFran"4/
gnibbler
ah ha, terima kasih @gnibbler, keren, akan memperbaruinya.
KAMU
Tidak yakin mengapa Anda menggunakan 6rand*- 0=randatau mungkin ;9randlebih disukai. Untuk loop, {.n+\' buys for '}%(lebih pendek ..
Nabb
heh; menjadi karakter chars yang sama dengan J sekarang: D dan terima kasih @Nabb, saya menggunakan 6rand*karena saya pikir itu akan secara acak mengacak 6 item array (saya pikir saya salah, karena ;9randterlihat sangat acak daripada milik saya)
ANDA
3

Japt -R, 41 byte

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

-2 byte terima kasih kepada @Oliver!

Cobalah!

Ini adalah pendekatan yang saya ambil di level tinggi:

  • membuka kompresi string yang berisi nama peserta
  • pisahkan string menjadi sebuah array
  • kocok
  • menetapkan setiap orang kepada orang tersebut dengan indeks tertinggi berikutnya
  • orang terakhir dalam array ditugaskan ke yang pertama

Saya memiliki sedikit sejarah dengan masalah ini karena saya membuat program "santa rahasia" untuk pekerjaan saya bertahun-tahun yang lalu. Kami akhirnya meminta beberapa pelamar pekerjaan untuk menyelesaikannya juga :)

dana
sumber
@Liver - terima kasih atas tipsnya! Sepertinya ãtidak mengembalikan pasangan yang menautkan elemen pertama ke elemen terakhir. Saya sedang mencari cara agar ini berfungsi, tetapi saya pikir saya akan memberi tahu Anda. Terima kasih sekali lagi! ethproductions.github.io/japt/…
dana
43 ?
dana
1
Ah kamu benar Saya pikir ini akan berhasil untuk 42
Oliver
1
41 byte
Oliver
Tunggu apa yang "q"di .ö("q")lakukan
hanya ASCII
2

Python - 118 karakter

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 karakter

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]
gnibbler
sumber
2

R - 85 karakter

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

Python - 154 karakter

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
gnibbler
sumber
Permintaan maaf, Python saya sangat kurang ... adalah loop sementara di sana pada dasarnya perulangan sampai menemukan solusi yang menghindari "X membeli untuk X"?
Steve
@ Steve: Cukup banyak. mapmemanggil str.__eq__setiap pasangan nilai yang sesuai di L dan M, dan loop terus berjalan sampai tidak ada yang benar.
Anon.
@Steve, ya. walaupun mungkin lebih pendek untuk hanya menggeser catatan dengan jumlah acak dari 1 menjadi 5, saya pikir itu tidak sesuai semangat pertanyaan
gnibbler
Ketika saya pertama kali mengajukan pertanyaan di tempat kerja, Anda benar sekali. Rekan kerja saya dengan cepat menunjukkan bahwa itu tidak dikesampingkan oleh definisi saya ... jadi saya membiarkannya seperti ketika memposting di sini.
Steve
1

D: 233 Karakter

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

Lebih Jelas:

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]);
}
Jonathan M Davis
sumber
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)
John
sumber
1

Skema, 173

Memberikan salah satu dari dua solusi.

(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)))

sumber
1

C #, 210 183 karakter

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

Tumpukan boilerplate :(

Solusi ini tidak sepenuhnya acak - selalu ada satu atau lebih "loop" orang misalnya A-> C-> E-> A, dan offset selalu sama di loop. Namun, tidak mungkin untuk memprediksi output dari proses tertentu kecuali Anda memiliki bagian dari output itu.

Segera.
sumber
Itulah interpretasi yang saya maksudkan (dan pada dasarnya solusi yang kita gunakan juga).
Steve
Harus 210. apakah Anda menghitung baris baru di akhir file?
gnibbler
@gnibbler: Saya mungkin. Saya baru saja memasukkan file ke wc, saya tidak akan menghitungnya dengan tangan.
Anon.
1
Bagaimana dengan var n="Andy Barb Carl Didi Earl Fran".Split()? Menghemat 16 byte. Anda dapat mengabaikan argumen Main(), yang menyimpan 9 byte lagi. Dan Anda dapat menggabungkan deklarasi cdan i: int c,i=...;for(c=0;...yang menyimpan dua lagi.
Joey
@ Joey: Tweaked sesuai saran Anda, terima kasih.
Anon.
0

Ruby - 89 karakter

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

Keluaran:

Andy buys for Didi
Barb buys for Earl
Fran buys for Carl
Carl buys for Fran
Earl buys for Barb
Didi buys for Andy
steenslag
sumber
1
Anda bisa menggunakan mapbukan each.
Dogbert
1
masalah dengan solusi ini adalah bahwa jika Anda memiliki jumlah orang yang ganjil, orang tengah akan memberi hadiah bagi dirinya sendiri Earl membeli untuk Mark Fran membeli untuk Andy Barb membeli untuk Carl Didi membeli untuk Didi Carl membeli untuk Barb Andy membeli untuk Fran Mark membeli untuk Earl
StudleyJr
0

MathGolf , 41 byte

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

Cobalah online!

Penjelasan

Ini tidak dijamin untuk menghasilkan setiap kasus dengan probabilitas yang sama, tetapi menghasilkan hasil yang berbeda setiap kali. Satu byte bisa dihapus jika saya memiliki operator acak, tapi itu untuk hari lain.

"δ%è╘+µ√♂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
maks
sumber