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


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

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

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 +.

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.


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*

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


@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


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]

2

R - 85 karakter

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

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

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

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

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

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.


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

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.