Sai Golf Golf?


53

È necessario generare un campo da golf a 18 buche casuale.

Esempio di output:

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

Regole:

  • Il programma deve generare un elenco di lunghezze dei fori esattamente per 18 fori
  • Ogni foro deve avere una lunghezza di 3, 4 o 5
  • Le lunghezze dei fori devono aggiungere fino a 72 per l'intero percorso
  • Il tuo programma deve essere in grado di produrre ogni possibile configurazione di buche con qualche probabilità diversa da zero (le probabilità di ogni configurazione non devono essere uguali, ma sentiti libero di chiedere complimenti extra in questo caso)

3
Conferma 44152809 soluzioni?
baby-rabbit,

1
Anch'io sono curioso del numero esatto di soluzioni, tuttavia penso che dovrebbe essere più di 44 milioni ... (Non sono un matematico, tuttavia: | 1 (5) / 1 (3) = 306 possibilità (17 * 18) | 2 (5) / 2 (3) = 69360 poss (17 * 17 * 16 * 15) | 3 (5) / 3 (3) = 11182080 poss (16 * 16 * 16 * 15 * 14 * 13) | che aspetto giusto?
NRGdallas,

11
@ baby-rabbit: posso confermare 44.152.809 soluzioni mediante enumerazione della forza bruta. Inoltre, può essere calcolata direttamente in questo modo: dal momento che la media è esattamente 4, e le uniche possibilità sono 3, 4o 5, la soluzione possibile classi sono { 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}. Questo può essere calcolato da 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. Ciò significa che approssimativamente 11.4%di tutte le possibili combinazioni sono soluzioni valide (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)44152809L
Sanjeev Murty il

Risposte:


29

k ( 18 17 16 caratteri)

Ritorno all'approccio originale, credito a CS per il miglioramento.

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

Altro approccio (17 caratteri), stesso metodo della soluzione J, da H / T a CS

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

Vecchia versione:

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

Non suscettibile di overflow dello stack e viene eseguito in uno spazio fisso.


Che cos'è H / T in CS?
Gareth,


Questo programma mi ha aiutato a scoprire un bug nel mio interprete K, grazie! In precedenza non avevo realizzato che i nilad potevano essere applicati a un singolo argomento (che ignorano).
Giovanni,


15

J, 20 18 17 caratteri

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

Funziona allo stesso modo della risposta precedente, tranne per il fatto che le 9 cifre casuali sono 0 o 1 e vengono annullate prima di essere aggiunte. Ciò significa che ci sono tanti -1s quanti ne esistono 1. L'aggiunta di 4 mi dà un elenco di 3s, 4s e 5s che aggiungono fino a 72 ogni volta.

Risposta precedente:

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

Genera le prime 9 buche in modo casuale ?9#3, quindi le copia e le inverte (,2-])(trasforma un 3 in un 5 e un 5 in un 3) per generare il 9. finale. Ciò garantisce che il totale sarà 72 (poiché ogni 3 avrà una corrispondenza 5 il il totale medio per buca sarà 4 e 4x18 = 72). Quindi mescola casualmente il risultato ({~?~@#)per garantire che ogni combinazione sia possibile.


in realtà non si generano {3,5,4,4,4 ...} si sta meglio mischiare l'intero risultato
maniaco del cricchetto

@rachetfreak Un buon punto. Modificherò ora.
Gareth,

13

Codice macchina x86 a 16 bit in MS-DOS - 45 byte

hexdump:

0E5F576A12595188ECE44088C3E44130D8240374F400C4AAE2EF595E80FC2475DFAC0432CD29B020CD29E2F5C3

Base64 codificato binario:

Dl9XahJZUYjs5ECIw+RBMNgkA3T0AMSq4u9ZXoD8JHXfrAQyzSmwIM0p4vXD

Codice sorgente effettivo con alcuni commenti:

 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.

Compilare nasm 18h.asm -o 18h.comed eseguire in MS-DOS (o Dosbox) o NTVDM da una versione di Windows a 32 bit.

Uscita campione:

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

3
love assembler ...
woliveirajr,

13

Mathematica 71 68 66 60

Con 6 caratteri salvati dal suggerimento di 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}

Tutti i possibili risultati sono possibili, ma non sono ugualmente probabili.


Analisi

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

produce tutte e 10 le possibili partizioni (combinazioni, non permutazioni) di 72 in 18 elementi costituiti da 3, 4 e 5.

partizioni


RandomChoice seleziona uno di quelli.

RandomSample restituisce una permutazione di quella scelta.


Hehe, stavo per pubblicare quasi la stessa identica risposta, usando solo RandomChoice invece di RandomInteger. Penso che puoi radere altri 4 personaggi in questo modo.
Tally,

Tally, grazie. Il tuo suggerimento è stato utile.
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

L'algoritmo è simile a quello di @ sgrieve.


Stesso problema di @sgrieve sopra: nulla gli impedisce di superare 18 buche.
gt6989b,

3
Non è un problema, il comando di esempio in questo caso genera sempre 18 valori.
sgrieve

8

GolfScript (26 caratteri)

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

Ci sono alcune ovvie somiglianze con la soluzione di Ilmari, ma anche alcune ovvie differenze. In particolare, sto sfruttando il fatto che il par medio è di 4.


Dannazione, ma questo è sicuramente un trucco intelligente con la condizione del loop lì. Mi sono {;0{3.rand+.@+}18*])72-}doinventato, ma non sono riuscito a capire come accorciarlo da lì. +1.
Ilmari Karonen,

7

Python 77

Codice

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

Produzione

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

L'importazione uccide davvero questa soluzione. Usa numpy per generare un numero di 18 compreso tra 3 e 5 e continua a generare elenchi fino a quando la somma dell'elenco è pari a 72.


Cosa impedisce al programma di raggiungere ben 72 prima di generare 18 buche? Cosa gli impedisce di saltare 72?
DavidC,

3
Il codice genererà sempre 18 buche, quindi verificherà se la somma è 72. Ad esempio, se la somma dopo 16 buche fosse 72, genererebbe comunque altre 2 buche, spingendo quindi la somma sopra 72 e fallendo il test.
Sgrieve

7

GolfScript, 27 caratteri

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

Utilizza lo stesso metodo di campionamento del rifiuto della soluzione Python di sgrieve. Pertanto, ogni output valido è effettivamente altrettanto probabile.


7

Q (25 caratteri)

Originale (27)

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

Uscita campione

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

Leggermente più corto (25)

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

7

JavaScript, 66 64 61 caratteri

Fortemente ispirato a TwoScoopsofPig (PHP) e 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

2
s!=72può essere s-72quello di salvare un carattere. E l'ultimo punto e virgola ;anon è necessario nemmeno per un altro carattere.
Joe Tuskan,

non l'ho mai visto for(i=x;i;i--)prima salva 2 caratteri for(i=0;i<x;i++), grazie amico!
Chiller matematico,

7

Python 2, 70 byte

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

Eccone un altro, simile alla soluzione di sgrieve:

Python 2, 73 byte + uguale probabilità

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

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

1
Quando eseguo questo in Chrome 21, ottengo i is not defined.
mellamokb,

5

Python, 128 120 116 caratteri

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

import le istruzioni sono ancora killer di lunghezza (23 caratteri per importare solo 2 funzioni nello spazio dei nomi)

spero che non sia necessario il risultato in un prossimo futuro, poiché questo codice valuta innanzitutto tutte le possibili soluzioni prima di sceglierne una a caso. forse la soluzione più lenta a questo problema.

chiedo complimenti extra per la stessa probabilità di ogni configurazione ...


4
import random,itertools
Grawity,

hai ragione, ciò accorcia un po 'le cose.
Adrien Plisson,

Altri suggerimenti: import random as r,itertools as iquindi utilizzare re iinvece di randome itertools. Usa 18*[0]invece di range(18)e [3,4,5,6]invece di range(3,6):)
Alex L

sto usando Python 3: la comprensione di una lista è un generatore e non ha lunghezza, il che ne proibisce l'uso con la choice()funzione. questo è anche ciò che rende questo codice così lento ...
Adrien Plisson,

1
ooops, mi dispiace, ho incasinato la comprensione dell'elenco e l'espressione del generatore (in genere evito la comprensione dell'elenco a favore dell'espressione del generatore a causa delle migliori prestazioni dell'iteratore). quindi in effetti, anche in Python3 posso ancora rimuovere alcuni personaggi ... @Alex ha fatto bene.
Adrien Plisson,

4

PHP - 77 caratteri

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

Proprio come la soluzione di sgrieve, questo crea un elenco di 18 buche, controlla il par totale e lo stampa o lo rifiuta e riprova. Stranamente, le nostre due soluzioni hanno la stessa lunghezza.

Piuttosto fastidioso, PHP non offre funzioni di array con alcuna brevità di nome. Array_sum e print_r mi stanno uccidendo. Suggerimenti benvenuti.


1
Qui non sono necessarie parentesi graffe e la somma può esserlo +=. <?while($s!=72)for($s=$i=0;18>$i;$s+=$a[++$i]=rand(3,5));print_r($a);
Grawity,

È utile - non ho mai pensato di mettere la logica nella chiamata del ciclo for (e mi sento un po 'stupido per non incrementare un contatore per la somma).
TwoScoopsofPig

Grazie - ma non è quello che intendevo per "parentesi graffe non necessarie"; avresti potuto rimuoverli anche nel codice originale:while(array_sum($a)!=72)for($i=0;18>$i;)$a[++$i]=rand(3,5);
grawity,

Beh, tranne che corro contro un php.ini più severo di quello perché sto giocando a golf al lavoro; si lamenta senza fine della mancanza o della mancata corrispondenza delle parentesi graffe. Normalmente avrei.
TwoScoopsofPig

È strano; 5.4.7 con E_ALL | E_STRICT non si lamenta mai dei dispersi {}(poiché la sintassi di PHP lo consente esplicitamente).
Grawity,

4

Ruby 1.9 (62 caratteri)

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

Rotaie (55 caratteri)

Nella $ rails cREPL (in qualsiasi cartella Rails):

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

Nota: funziona con Ruby 1.8 se si utilizza shuffle[0]invece di sample.


2
Hai bisogno di spazi bianchi fino a quando?
Kaz,

@Kaz Hai ragione, non è necessario. :) 62 caratteri ora.
js-coder,

1
È possibile utilizzare (1..18).map{rand(3)+3}per ottenere l'array casuale;)
epidemia

4

Lisp ( 78 69 caratteri)

(do ((c () (mapcar (lambda (x) (+ 3 (random 3))) (make-list 18)))) ((= (applica '+ c) 72) c))

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

È piuttosto simile alla soluzione Python di sgrieve.

Inizia con c come NIL, controlla la somma di 72, la do"funzione di incremento" per c genera un elenco di 18 numeri tra 3 e 5, controlla di nuovo 72, schiuma, risciacqua, ripeti.

È rinfrescante vedere doe loopgiocare a golf insieme.


3

C (123 caratteri) - impegno per l'efficienza

Installa il wc e genererà tutte le soluzioni 44152809 entro 10 secondi ...

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, bene - non ho letto correttamente la domanda - ma dato che stiamo generando tutte le soluzioni, quindi sceglierne una casuale con uguale probabilità è un esercizio di scripting: P


3

Clojure - 55

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

Un trucco abbastanza divertente .... sfrutta la struttura matematica del problema in base al quale devono esserci esattamente 3 buche pari a 5 buche par.


3

Python 83

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

Come la soluzione di sgrieve, ma senza intorpidimento

La soluzione Golf di Adrien Plisson: 120-> 108 caratteri

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

Uscita :

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


Ottimo approccio, ma puoi salvare 4 byte digitando randi([3,5],1,18)invece di3+floor(rand(1,18)*3)
brainkz il

3

Java (61 caratteri)

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

Uscita campione:

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

Non sono un esperto di Java, ma non dovrebbe esserci una dichiarazione di S e I e una sorta di chiamata a System # println (..)?
hiergiltdiestfu,

Questo è solo uno snippet di codice, non un programma. E in realtà assomiglia molto alla versione C di @JoeIbanez.
Franz D.

2

C (94 caratteri)

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

La s=0linea 1 potrebbe non essere richiesta, perché quali sono le probabilità che un int non inizializzato sia uguale a 72? Semplicemente non mi piace leggere valori non inizializzati nella riga C. Inoltre, questo probabilmente richiede il seeding della rand()funzione.

produzione

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

Quindi, in sostanza, eseguirai il ciclo tra stringhe casuali di 18 numeri compresi tra 3 e 5 fino a quando uno sembra essere uguale a 72? Per fortuna l'efficienza non è un requisito.
KeithS,

5
@KeithS Ad essere sinceri, è quello che fanno la maggior parte delle risposte a questa domanda.
Gareth,

2

Bash shell script (65 caratteri)

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

( shuf proviene dal pacchetto GNU coreutils. Inoltre, grazie Gareth.)


2

C # (143 non bianchi):

()=>{
  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);
}

new Guid()crea un GUID vuoto. Per generare effettivamente un GUID univoco è necessario chiamare un metodo statico Guid.NewGuid.
Rotsor,

E hai due errori uno a uno (per così dire): i confronti dovrebbero essere i <n e i> = 18-n, non viceversa. E potresti ridurre le dimensioni usando una costante 3 invece di x-1 e 5 invece di x + 1. E quindi è possibile sostituire Enumerable.Repeat con Enumerable.Range.
Mormegil,

Modificato; ancora 143 caratteri
KeithS

Non c'è Math.Random, lo è System.Random.
CodesInChaos

Un altro approccio C # (143 caratteri):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;}}
thepirat000


2

Perl, 74

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

Soluzione alternativa:

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

2

TXR (99 caratteri)

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

Questa espressione genera un elenco pigro infinito di numeri casuali da 3 a 5:

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

Il resto della logica è un semplice ciclo che controlla se i primi 18 elementi di questo elenco si sommano a 72. In caso contrario, elimina un elemento e riprova. Il forciclo contiene un blocco implicito chiamato nile così(return ...) può essere utilizzato per terminare il loop e restituire il valore.

Si noti che la lunghezza di 99 caratteri include una nuova riga finale, che è richiesta.


Ho inserito un commit che consente a (t) di essere sostituito da (). :)
Kaz,

2

APL 12

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

Si noti che l'origine dell'indice è impostata su 0, il che significa che le matrici iniziano da 0. È possibile impostare questo con ⎕IO←0.


La domanda pone un programma in grado di produrre ogni possibile configurazione. I tuoi possono produrre quelli simmetrici. Non puoi produrre ad esempio 555455555333333343, almeno mi sembra.
Moris Zucca,

2

R, 42 byte

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

sample, per impostazione predefinita, disegna uniformemente tra i possibili valori (qui 3 4 5). r=Trappresenta replace=TRUEe consente il campione con sostituzione.


2

CJam, 17 14 byte

CJam è più recente di questa sfida, ma questa non è la risposta più breve, quindi non importa.

Z5]Amr*I4e]mrp

Provalo qui.

Per mantenere il totale di 72, ognuno 3deve essere associato 5. Quindi ecco come funziona:

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.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.