Bisakah Anda Golf Golf?

53

Anda harus membuat lapangan golf 18-lubang secara acak.

Contoh output:

[3 4 3 5 5 4 4 4 5 3 3 4 4 3 4 5 5 4]

Aturan:

  • Program Anda harus menampilkan daftar panjang lubang dengan tepat 18 lubang
  • Setiap lubang harus memiliki panjang 3, 4 atau 5
  • Panjang lubang harus ditambah hingga 72 untuk seluruh kursus
  • Program Anda harus dapat menghasilkan setiap kemungkinan konfigurasi lubang dengan beberapa probabilitas non-nol (probabilitas masing-masing konfigurasi tidak harus sama, tetapi jangan ragu untuk mengklaim pujian tambahan jika ini masalahnya)
mikera
sumber
3
Silakan konfirmasi, solusi 44152809?
baby-kelinci
1
Saya juga penasaran dengan jumlah solusi yang tepat, namun saya pikir seharusnya lebih dari 44 juta ... (Saya bukan ahli matematika, namun: | 1 (5) / 1 (3) = 306 kemungkinan (17 * 18) 2 (5) / 2 (3) = 69360 poss (17 * 17 * 16 * 15) | 3 (5) / 3 (3) = 11182080 poss (16 * 16 * 16 * 15 * 15 * 14 * 13) | itu terlihat benar?
NRGdallas
11
@ baby-kelinci: Saya dapat mengkonfirmasi 44.152.809 solusi dengan penghitungan brute force. Selain itu, dapat langsung dihitung dengan cara ini: karena rata-rata adalah persis 4, dan satu-satunya kemungkinan adalah 3, 4, atau 5, solusi yang mungkin kelas yang { no 3's or 5's, one 3 and one 5, two 3's and two 5's, ..., nine 3's and nine 5's}. Ini dapat dihitung dengan nCr(18,0)*nCr(18,0) + nCr(18,1)*nCr(17,1) + nCr(18,2)*nCr(16,2) + ... + nCr(18,9)*nCr(9,9) = 44,152,809. Ini berarti kira 11.4%- kira semua kemungkinan kombinasi adalah solusi yang valid (44,152,809 / 3^18).
mellamokb
2
sum(factorial(18)/factorial(x)/factorial(y)/factorial(z) for x in range(25) for y in range(25) for z in range(25) if 3*x+4*y+5*z == 72 and x+y+z == 18)memberikan44152809L
Sanjeev Murty

Jawaban:

29

k ( 18 17 16 karakter)

Kembali ke pendekatan awal, beri kredit ke CS untuk peningkatan.

(+/4-){3+18?3}/0

Pendekatan lain (17 karakter), metode yang sama dengan solusi J, H / T ke CS

4+a,-a:9?2 -18?18

Versi lama:

(72-+/){18?3+!3}/0

Tidak rentan terhadap stack-overflow dan beroperasi dalam jumlah ruang yang tetap.

skeevey
sumber
Apa H / T untuk CS?
Gareth
Program ini membantu saya menemukan bug pada penerjemah K saya - terima kasih! Saya sebelumnya tidak menyadari bahwa nilad dapat diterapkan pada satu argumen (yang mereka abaikan).
JohnE
17

K, 28

{$[72=+/s:18?3 4 5;s;.z.s`]}
tmartin
sumber
15

J, 20 18 17 karakter

(?~18){4+(,-)?9#2

Ini bekerja dengan cara yang sama seperti jawaban sebelumnya kecuali bahwa 9 angka acak adalah 0 atau 1 dan dinegasikan sebelum ditambahkan. Ini berarti ada -1s sebanyak ada 1s. Menambahkan 4 memberi saya daftar 3s, 4s dan 5s yang menambahkan hingga 72 setiap kali.

Jawaban sebelumnya:

({~?~@#)3+(,2-])?9#3

Hasilkan 9 lubang pertama secara acak ?9#3, kemudian salin dan balikkan (,2-])(mengubah 3 menjadi 5 dan 5 menjadi 3) untuk menghasilkan 9. final. Ini menjamin bahwa total akan menjadi 72 (karena setiap 3 akan memiliki pencocokan 5 yang total rata-rata per lubang adalah 4 dan 4x18 = 72). Itu kemudian secara acak mengocok hasilnya ({~?~@#)untuk memastikan bahwa setiap kombinasi adalah mungkin.

Gareth
sumber
sebenarnya Anda tidak akan menghasilkan {3,5,4,4,4 ...} Anda lebih baik mengocok seluruh hasil
ratchet freak
@rachetfreak Poin bagus. Saya akan mengedit sekarang.
Gareth
13

Kode mesin x86 16-bit di bawah MS-DOS - 45 byte

Hexdump:

0E5F576A12595188ECE44088C3E44130D8240374F400C4AAE2EF595E80FC2475DFAC0432CD29B020CD29E2F5C3

Biner kode Base64:

Dl9XahJZUYjs5ECIw+RBMNgkA3T0AMSq4u9ZXoD8JHXfrAQyzSmwIM0p4vXD

Kode sumber aktual dengan beberapa komentar:

 bits 16
 org 0x100

again:
 push cs               ; Save whatever CS we get.
 pop di                ; Use CS:DI as our course buffer..
 push di               ; Save for later use in the print loop
 push 18               ; We need 18 holes for our golf course.
 pop cx                ; ch = 0, cl = 18.
 push cx               ; Save for later use.
 mov ah, ch            ; Zero out ah.
generate_course:
 in al, 0x40           ; Port 0x40 is the 8253 PIT Counter 0.
 mov bl, al            ; Save the first "random" value in bl.
 in al, 0x41           ; Port 0x41 is the 8253 PIT Counter 1.
 xor al, bl            ; Add some more pseudo randomness.
 and al, 3             ; We only need the two lower bits.
 jz generate_course    ; If zero, re-generate a value, since we need only 3, 4, 5 holes.
 add ah, al            ; Sum in ah register.
 stosb                 ; Store in the course buffer.
 loop generate_course  ; Loop for 18 holes.
 pop cx                ; cx = 18.
 pop si                ; si = course buffer.
 cmp ah, 36            ; 72 holes?
 jne again             ; No, re-generate the whole course.

print:                 ; Yup, we have a nice course.
 lodsb                 ; Load the next hole.
 add al, '2'           ; Add ASCII '2' to get '3', '4' or '5'
 int 0x29              ; Undocumented MS-DOS print function.
 mov al, ' '           ; Print a space too for better readability.
 int 0x29              ; Print the character.
 loop print            ; Print the whole course.
 ret                   ; Return to the beginning of the PSP where a INT 0x20 happen to be.

Kompilasi dengan nasm 18h.asm -o 18h.comdan jalankan di bawah MS-DOS (atau Dosbox), atau NTVDM dari versi Windows 32-bit.

Output sampel:

4 5 4 5 4 5 3 4 3 4 3 4 4 5 4 3 5 3
Jonas Gulle
sumber
3
love assembler ...
woliveirajr
13

Mathematica 71 68 66 60

Dengan 6 karakter disimpan oleh saran Tally.

RandomSample@RandomChoice@IntegerPartitions[72, {18}, {3, 4, 5}]

{5, 4, 3, 3, 5, 3, 5, 5, 3, 3, 4, 5, 3, 5, 4, 4, 5, 3}

Semua hasil yang mungkin adalah mungkin, tetapi mereka tidak memiliki kemungkinan yang sama.


Analisis

IntegerPartitions[72, {18}, {3, 4, 5}]

menghasilkan semua 10 partisi yang mungkin (kombinasi, bukan permutasi) dari 72 menjadi 18 elemen yang terdiri dari 3, 4 dan 5.

partisi


RandomChoice memilih salah satu dari itu.

RandomSample mengembalikan permutasi dari pilihan itu.

DavidC
sumber
Hehe, saya baru saja memposting jawaban yang hampir sama persis, hanya menggunakan RandomChoice sebagai ganti RandomInteger. Saya pikir Anda dapat mencukur 4 karakter lagi dengan melakukannya.
Tally
Tally, terima kasih. Saran Anda sangat membantu.
DavidC
8

R - 41

x=0;while(sum(x)!=72)x=sample(3:5,18,T);x

# [1] 5 3 5 3 3 3 3 3 5 4 5 4 5 4 4 5 5 3

Algoritma ini mirip dengan @ sgrieve.

flodel
sumber
Masalah yang sama dengan @sgrieve di atas - tidak ada yang mencegahnya masuk dalam 18 lubang.
gt6989b
3
Itu bukan masalah, perintah sampel dalam hal ini selalu menghasilkan 18 nilai.
sgrieve
8

GolfScript (26 karakter)

{;0{3rand.3+@@+(}18*])}do`

Ada beberapa kesamaan yang jelas dengan solusi Ilmari, tetapi juga beberapa perbedaan yang jelas. Secara khusus, saya mengeksploitasi fakta bahwa par rata-rata adalah 4.

Peter Taylor
sumber
Sial, tapi itu pasti trik yang cerdas dengan kondisi loop di sana. Saya datang dengan {;0{3.rand+.@+}18*])72-}dodiri saya sendiri, tetapi tidak tahu bagaimana cara membuatnya lebih pendek dari sana. +1.
Ilmari Karonen
7

Python 77

Kode

from numpy.random import*;l=[]
while sum(l)!=72:l=randint(3,6,18)
print l

Keluaran

[3 4 4 5 3 3 3 5 4 4 5 4 5 3 4 4 5 4]

Impor benar-benar membunuh solusi ini. Menggunakan numpy untuk menghasilkan 18 angka antara 3 dan 5 dan terus menghasilkan daftar sampai jumlah daftar sama dengan 72.

sgrieve
sumber
Apa yang mencegah program mencapai 72 jauh sebelum menghasilkan 18 lubang? Apa yang mencegahnya melompati 72?
DavidC
3
Kode akan selalu menghasilkan 18 lubang, lalu periksa apakah jumlahnya sama dengan 72. Misalnya, jika jumlah setelah 16 lubang adalah 72, itu masih akan menghasilkan 2 lubang, therby mendorong jumlah di atas 72 dan gagal dalam tes.
sgrieve
7

GolfScript, 27 karakter

{;18{3.rand+}*].{+}*72-}do`

Menggunakan metode sampel penolakan yang sama dengan solusi Python sgrieve. Jadi, setiap output yang valid sebenarnya memiliki kemungkinan yang sama.

Ilmari Karonen
sumber
7

Q (25 karakter)

Asli (27)

while[72<>sum a:18?3 4 5];a

Output sampel

4 4 3 3 4 5 4 3 4 5 5 3 5 5 5 4 3 3

Sedikit lebih pendek (25)

{72<>sum x}{x:18?3 4 5}/0
sinedcm
sumber
7

JavaScript, 66 64 61 karakter

Sangat terinspirasi oleh TwoScoopsofPig (PHP) dan Joe Tuskan (JS).

for(a=[s=0];s!=72;)for(s=i=0;i<18;s+=a[i++]=Math.random()*3+3|0);a

for(a=[s=0];s-72;)for(s=i=0;i<18;s+=a[i++]=Math.random()*3+3|0)a

for(a=s=[];s;)for(i=18,s=72;i;s-=a[--i]=Math.random()*3+3|0)a
grawity
sumber
2
s!=72bisa s-72dengan menyimpan satu char. Dan semi-colon terakhir ;atidak diperlukan untuk char lain.
Joe Tuskan
Saya tidak pernah melihat for(i=x;i;i--)sebelumnya menyimpan 2 karakter dari for(i=0;i<x;i++), terima kasih man!
Math chiller
7

Python 2, 70 byte

from random import*
print sample(([3,5]*randint(0,9)+[4]*99)[:18],18)
sunting:

Inilah yang lain, mirip dengan solusi sgrieve:

Python 2, 73 byte + probabilitas yang sama

from random import*
a=[]
while sum(a)-72:a=sample([3,4,5]*18,18)
print a
daniero
sumber
5

JavaScript, 116 99 65 byte

for(i=0,h=[];i<18;)h[i++]=5;while(h.reduce(function(a,b){return a+b})!=72){i=Math.random()*18|0;h[i]=[3,4,4][i%3]}h;

h=[0];while(h.reduce(function(a,b){return a+b})-72)for(i=0;i<18;h[i++]=[3,4,5][Math.random()*3|0])h

while(i%18||(a=[i=s=0]),s+=a[i++]=Math.random()*3+3|0,s-72|i-18)a
Joe Tuskan
sumber
1
Ketika saya menjalankan ini di Chrome 21, saya mengerti i is not defined.
mellamokb
5

Python, 128 120 116 karakter

import random,itertools
random.choice([g for g in itertools.product(*(range(3,6)for l in range(18))) if sum(g)==72])

import pernyataan masih panjang pembunuh (hanya 23 karakter untuk mengimpor 2 fungsi di namespace)

saya harap Anda tidak memerlukan hasilnya dalam waktu dekat, karena kode ini pertama mengevaluasi semua solusi yang mungkin sebelum memilih satu secara acak. mungkin solusi paling lambat untuk masalah ini.

saya mengklaim pujian ekstra untuk probabilitas yang sama dari setiap konfigurasi ...

Adrien Plisson
sumber
4
import random,itertools
grawity
Anda benar, itu mempersingkat segalanya.
Adrien Plisson
Kiat lain: import random as r,itertools as ilalu gunakan rdan ibukannya randomdan itertools. Gunakan 18*[0]sebagai ganti range(18), dan [3,4,5,6]bukannya range(3,6):)
Alex L
Saya menggunakan python 3: daftar pemahaman adalah generator dan tidak memiliki panjang, yang melarang penggunaannya dengan choice()fungsi. itu juga yang membuat kode ini sangat lambat ...
Adrien Plisson
1
ooops, maaf, saya mengacaukan daftar pemahaman dan ekspresi generator (saya biasanya menghindari pemahaman daftar yang mendukung ekspresi generator karena kinerja iterator yang lebih baik). jadi memang, bahkan di python3 saya masih bisa menghapus beberapa karakter ... @Alex melakukannya dengan benar.
Adrien Plisson
4

PHP - 77 Karakter

<?while(array_sum($a)!=72){for($i=0;18>$i;){$a[++$i]=rand(3,5);}}print_r($a);

Sama seperti solusi sgrieve, ini membangun daftar 18 lubang, memeriksa par total, dan mencetaknya atau menolaknya dan mencoba lagi. Anehnya, kedua solusi kami memiliki panjang yang sama.

Agak menjengkelkan, PHP tidak menawarkan fungsi array dengan singkatnya nama. Array_sum dan print_r membunuhku. Saran diterima.

TwoScoopsofPig
sumber
1
Kurung kurawal tidak diperlukan di sini, dan jumlah bisa +=. <?while($s!=72)for($s=$i=0;18>$i;$s+=$a[++$i]=rand(3,5));print_r($a);
grawity
Itu berguna - saya tidak pernah berpikir untuk memasukkan logika dalam for loop call (dan saya merasa agak bodoh karena tidak menambah penghitung untuk penjumlahan).
TwoScoopsofPig
Terima kasih - tapi itu sebenarnya bukan yang saya maksudkan dengan "kurung kurawal tidak diperlukan"; Anda bisa menghapusnya dalam kode asli juga:while(array_sum($a)!=72)for($i=0;18>$i;)$a[++$i]=rand(3,5);
grawity
Ya, kecuali saya menghadapi php.ini yang lebih ketat dari itu karena saya bermain golf di tempat kerja; itu tidak ada habisnya mengeluh tentang kawat gigi yang hilang / tidak cocok. Biasanya saya akan melakukannya.
TwoScoopsofPig
Itu aneh; 5.4.7 dengan E_ALL | E_STRICT tidak pernah mengeluh tentang kehilangan {}(karena sintaks PHP secara eksplisit mengizinkannya).
grawity
4

Ruby 1.9 (62 karakter)

a=Array.new(18){[3,4,5].sample}until(a||[]).inject(:+)==72
p a

Rails (55 karakter)

Dalam $ rails cREPL (dalam folder Rails apa pun):

a=Array.new(18){[3,4,5].sample}until(a||[]).sum==72
p a

Catatan: Ia bekerja dengan Ruby 1.8 jika Anda menggunakan shuffle[0]bukan sample.

js-coder
sumber
2
Apakah Anda perlu ruang kosong sekitar sampai?
Kaz
@ Ka Anda benar, tidak perlu. :) 62 karakter sekarang.
js-coder
1
Anda dapat menggunakan (1..18).map{rand(3)+3}untuk mendapatkan array acak;)
epidemian
4

Lisp ( 78 69 karakter)

(do ((c () (mapcar (lambda (x) (+ 3 (random 3))) (daftar make 18))))) ((= (terapkan '+ c) 72) c))

(do((c()(loop repeat 18 collect(+ 3(random 3)))))((=(apply'+ c)72)c))

Ini agak mirip dengan solusi Python sgrieve.

Mulai dengan c sebagai NIL, periksa jumlah 72, the do "fungsi kenaikan" untuk c menghasilkan daftar 18 angka antara 3 dan 5, periksa 72 lagi, busa, bilas, ulangi.

Sangat menyegarkan untuk melihat dodan loopbermain golf bersama dengan baik.

musim dingin
sumber
3

C (123 chars) - upaya efisiensi

Pipa melalui wc dan itu akan menghasilkan semua solusi 44152809 dalam 10 detik ...

char s[19];g(d,t){int i;if(d--){for(i=51,t-=3;i<54;i++,t--)if(t>=3*d&&t<=5*d)s[d]=i,g(d,t);}else puts(s);}main(){g(18,72);}

Oh, well - tidak membaca pertanyaan dengan benar - tetapi mengingat kita menghasilkan semua solusi kemudian memilih yang acak dengan probabilitas yang sama adalah latihan scripting: P

bayi-kelinci
sumber
3

Clojure - 55

(shuffle(mapcat #([[4 4][3 5]%](rand-int 2))(range 9)))

Trik yang cukup menyenangkan .... mengeksploitasi struktur matematika dari masalah yang harus ada persis 3 lubang par 5 lubang par.

mikera
sumber
3

Python 83

import random as r;x=[]
while sum(x)!=72:x=[r.randint(3,5) for i in 18*[0]]
print x

Seperti solusi sgrieve, tetapi tanpa numpy

Solusi Golfing Adrien Plisson: 120-> 108 karakter

import random as r,itertools as i
r.choice([g for g in i.product(*([3,4,5,6]for l in 18*[0]))if sum(g)==72])

MATLAB 53

x=[];
while sum(x)~=72
x=3+floor(rand(1,18)*3);
end
x

Keluaran :

x = 4 3 4 4 4 4 5 4 4 3 4 4 3 5 3 5 4 5

Alex L
sumber
Pendekatan yang bagus, tetapi Anda dapat menyimpan 4 byte dengan mengetik randi([3,5],1,18)alih-alih3+floor(rand(1,18)*3)
brainkz
3

Jawa (61 karakter)

while(s!=72)for(i=0,s=0;i<18;i++)s+=3+(int)(Math.random()*3);

Output sampel:

5 4 3 4 5 3 4 4 3 5 4 4 4 4 3 4 4 5
Quasar
sumber
Saya bukan pakar Java, tetapi tidakkah seharusnya ada deklarasi s dan i, dan semacam panggilan ke System # println (..)?
hiergiltdiestfu
Ini hanya cuplikan kode, bukan program. Dan itu sebenarnya sangat mirip dengan versi @JoeIbanez 'C.
Franz D.
2

C (94 karakter)

int h[18],s=0,i;
while(s!=72)for(i=s=0;i<18;s+=h[i++]=rand()%3+3);
while(i)printf("%d ",h[--i]);

Itu s=0 on line 1 mungkin tidak diperlukan, karena apa yang kemungkinan int diinisiasi akan sama 72? Saya hanya tidak suka membaca nilai yang tidak diinisialisasi dalam lurus C. Juga, ini mungkin memerlukan seedingrand() fungsi.

keluaran

3 3 3 4 5 5 3 3 4 5 5 4 3 4 5 5 5 3 
Joe Ibanez
sumber
Jadi pada dasarnya Anda akan mengulang melalui string acak dari 18 angka berkisar 3 sampai 5 sampai satu sama dengan 72? Efisiensi hal yang baik bukanlah persyaratan.
KeithS
5
@KeithS Agar adil, itulah yang dilakukan sebagian besar jawaban untuk pertanyaan ini.
Gareth
2

Script Bash shell (65 karakter)

shuf -e `for x in {0..8}
do echo $((r=RANDOM%3+3)) $((8-r))
done`

( Shuf berasal dari paket GNU coreutils. Juga, terima kasih Gareth.)

Tolong berdiri
sumber
2

C # (143 non-spasi putih):

()=>{
  var n=new Math.Random().Next(10);
  Enumerable.Range(1,18)
    .Select((x,i)=>i<n?3:i>=18-n?5:4)
    .OrderBy(x=>Guid.NewGuid())
    .ForEach(Console.Write);
}
KeithS
sumber
new Guid()membuat GUID kosong. Untuk benar-benar menghasilkan GUID unik, Anda perlu memanggil metode statis Guid.NewGuid.
Rotsor
Dan Anda memiliki dua kesalahan satu-per-satu (bisa dikatakan): perbandingannya harus i <n dan i> = 18-n, bukan sebaliknya. Dan Anda bisa mengurangi ukuran dengan menggunakan konstanta 3 bukannya x-1 dan 5 bukannya x +1. Dan kemudian Anda bisa mengganti Enumerable.Repeat oleh Enumerable.Range.
Mormegil
Diedit; masih 143 karakter
KeithS
Tidak Math.Random, tidak System.Random.
CodesInChaos
Pendekatan C # lainnya (143 karakter):var r=new Random();for(;;){var e=Enumerable.Range(1,18).Select(i=>r.Next(3,6)).ToList();if(e.Sum()==72){e.ForEach(i=>Console.Write(i));break;}}
thirir000
2

Haskell, 104 102 98 karakter.

import System.Random
q l|sum l==72=print l|1>0=main
main=mapM(\_->randomRIO(3::Int,5))[1..18]>>=q
Rotsor
sumber
[1..n]>>[r]sedikit lebih pendek dari replicate n$r.
Berhenti menghidupkan counterclockwis
Juga diubah sequencemenjadi mapM.
Rotsor
2

Perl, 74

{@c=map{3+int rand 3}(0)x18;$s=0;$s+=$_ for@c;redo unless$s==72}print"@c"

Solusi alternatif:

@q=((3,5)x($a=int rand 9),(4,4)x(9-$a));%t=map{(rand,$_)}(0..17);print"@q[@t{sort keys%t}]"
o_o
sumber
2

TXR (99 karakter)

@(bind g@(for((x(gen t(+ 3(rand 3))))y)(t)((pop x))(set y[x 0..18])(if(= [apply + y]72)(return y))))

Ungkapan ini menghasilkan daftar malas acak dari angka acak dari 3 hingga 5:

(gen t (+ 3(rand 3)))  ;; t means true: while t is true, generate.

Sisa logikanya adalah loop sederhana yang memeriksa apakah 18 elemen pertama dari daftar ini berjumlah hingga 72. Jika tidak, ia akan memunculkan elemen dan mencoba lagi. The forLoop berisi sebuah blok implisit disebut nildan sebagainya(return ...) dapat digunakan untuk mengakhiri loop dan kembali nilai.

Perhatikan bahwa panjang 99 karakter termasuk baris baru yang berhenti, yang diperlukan.

Kaz
sumber
Saya memasukkan komit yang memungkinkan (t) diganti oleh (). :)
Kaz
2

APL 12

4+{⍵,-⍵}?9⍴2

Perhatikan bahwa saya memiliki indeks asal diatur ke 0, artinya array mulai dari 0. Anda dapat mengatur ini dengan ⎕IO←0.

Zaq
sumber
Pertanyaannya menanyakan program yang dapat menghasilkan setiap konfigurasi yang memungkinkan. Anda dapat menghasilkan yang simetris. Anda tidak dapat menghasilkan misalnya 555455555333333343, setidaknya sepertinya begitu bagi saya.
Moris Zucca
2

R, 42 byte

a=0;while(sum(a)-72)a=sample(3:5,18,r=T);a

sample, secara default, menarik secara merata di antara nilai yang mungkin (di sini 3 4 5). r=Tsingkatan replace=TRUEdan memungkinkan sampel dengan penggantian.

plannapus
sumber
2

CJam, 17 14 byte

CJam lebih baru dari tantangan ini, tetapi ini bukan jawaban terpendek, jadi itu tidak masalah.

Z5]Amr*I4e]mrp

Uji di sini.

Untuk mempertahankan total 72, masing 3- masing harus dipasangkan dengan 5. Jadi, inilah cara kerjanya:

Z5]            e# Push [3 5].
   Amr         e# Get a random number between 0 and 9.
      *        e# Repeat the [3 5] array that many times.
       I4e]    e# Pad the array to size 18 with 4s.
           mr  e# Shuffle the array.
             p e# Print it.
Martin Ender
sumber