¿Puedes Golf Golf?

53

Debe generar un campo de golf aleatorio de 18 hoyos.

Salida de ejemplo:

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

Reglas:

  • Su programa debe generar una lista de longitudes de agujeros para exactamente 18 agujeros
  • Cada hoyo debe tener una longitud de 3, 4 o 5
  • La longitud del hoyo debe sumar 72 para todo el recorrido.
  • Su programa debe ser capaz de producir todas las configuraciones de agujeros posibles con alguna probabilidad distinta de cero (las probabilidades de cada configuración no necesitan ser iguales, pero siéntase libre de reclamar felicitaciones adicionales si este es el caso)
mikera
fuente
3
Por favor confirme, 44152809 soluciones?
baby-rabbit
1
También tengo curiosidad sobre el número exacto de soluciones, sin embargo, creo que debería ser más de 44 millones ... (Sin embargo, no soy matemático: | 1 (5) / 1 (3) = 306 posibilidades (17 * 18) | 2 (5) / 2 (3) = 69360 poss (17 * 17 * 16 * 15) | 3 (5) / 3 (3) = 11182080 poss (16 * 16 * 16 * 15 * 14 * 13) | does ¿
Qué
11
@ baby-rabbit: puedo confirmar 44.152.809 soluciones por enumeración de fuerza bruta. Además, se puede calcular directamente de esta manera: ya que el promedio es exactamente 4, y las únicas posibilidades son 3, 4o 5, la posible solución clases son { 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}. Esto se puede calcular por 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. Esto significa que aproximadamente 11.4%todas las combinaciones posibles son soluciones válidas (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)da44152809L
Sanjeev Murty

Respuestas:

29

k ( 18 17 16 caracteres)

Volviendo al enfoque original, crédito a CS por la mejora.

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

Otro enfoque (17 caracteres), el mismo método que la solución J, H / T a CS

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

Versión antigua:

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

No es susceptible al desbordamiento de la pila y se ejecuta en una cantidad fija de espacio.

skeevey
fuente
¿Qué es H / T para CS?
Gareth
Este programa me ayudó a descubrir un error en mi intérprete de K, ¡gracias! No me había dado cuenta previamente de que nilads podría aplicarse a un solo argumento (que ignoran).
JohnE
17

K, 28

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

J, 20 18 17 caracteres

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

Esto funciona de la misma manera que la respuesta anterior, excepto que los 9 dígitos aleatorios son 0 o 1 y se niegan antes de agregarlos. Esto significa que hay tantos -1s como 1s. Agregar 4 me da una lista de 3s, 4sy 5s que suman 72 cada vez.

Respuesta anterior:

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

Genera los primeros 9 hoyos al azar ?9#3, luego los copia y los invierte (,2-])(convierte un 3 en un 5 y un 5 en un 3) para generar el 9. final. Esto garantiza que el total será 72 (ya que cada 3 tendrá un 5 coincidente) el total promedio por hoyo será 4 y 4x18 = 72). Luego baraja aleatoriamente el resultado ({~?~@#)para garantizar que todas las combinaciones sean posibles.

Gareth
fuente
en realidad no generarás {3,5,4,4,4 ...} es mejor mezclar todo el resultado
monstruo de trinquete
@rachetfreak Buen punto. Lo editaré ahora.
Gareth
13

Código de máquina x86 de 16 bits en MS-DOS - 45 bytes

Hexdump:

0E5F576A12595188ECE44088C3E44130D8240374F400C4AAE2EF595E80FC2475DFAC0432CD29B020CD29E2F5C3

Binario codificado Base64:

Dl9XahJZUYjs5ECIw+RBMNgkA3T0AMSq4u9ZXoD8JHXfrAQyzSmwIM0p4vXD

Código fuente real con algunos comentarios:

 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.

Compile nasm 18h.asm -o 18h.comy ejecute bajo MS-DOS (o Dosbox), o NTVDM desde una versión de Windows de 32 bits.

Salida de muestra:

4 5 4 5 4 5 3 4 3 4 3 4 4 5 4 3 5 3
Jonas Gulle
fuente
3
ensamblador de amor ...
woliveirajr
13

Mathematica 71 68 66 60

Con 6 caracteres guardados por la sugerencia de 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}

Todos los resultados posibles son posibles, pero no son igualmente probables.


Análisis

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

produce las 10 particiones posibles (combinaciones, no permutaciones) de 72 en 18 elementos que consisten en 3, 4 y 5.

particiones


RandomChoice selecciona uno de esos.

RandomSample devuelve una permutación de esa elección.

DavidC
fuente
Jeje, estaba a punto de publicar casi la misma respuesta, solo usando RandomChoice en lugar de RandomInteger. Creo que puedes afeitarte con 4 personajes más al hacerlo.
Tally
Tally, gracias. Tu sugerencia fue útil.
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

El algoritmo es similar al de @ sgrieve.

flodel
fuente
El mismo problema que @sgrieve anterior: nada impide que pase por 18 hoyos.
gt6989b
3
Eso no es un problema, el comando de ejemplo en este caso siempre genera 18 valores.
sgrieve
8

GolfScript (26 caracteres)

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

Hay algunas similitudes obvias con la solución de Ilmari, pero también algunas diferencias obvias. En particular, estoy explotando el hecho de que el par promedio es 4.

Peter Taylor
fuente
Maldición, pero eso seguro es un truco inteligente con la condición del bucle allí. Se me ocurrió {;0{3.rand+.@+}18*])72-}do, pero no pude encontrar la forma de acortarlo desde allí. +1.
Ilmari Karonen
7

Python 77

Código

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

Salida

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

La importación realmente mata esta solución. Utiliza numpy para generar 18 números entre 3 y 5 y sigue generando listas hasta que la suma de la lista sea igual a 72.

sgrieve
fuente
¿Qué impide que el programa alcance 72 pozos antes de generar 18 agujeros? ¿Qué evita que se salte 72?
DavidC
3
El código siempre generará 18 hoyos, luego verifique si la suma es igual a 72. Por ejemplo, si la suma después de 16 hoyos fue 72, aún generaría otros 2 hoyos, empujando la suma por encima de 72 y reprobando la prueba.
sgrieve
7

GolfScript, 27 caracteres

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

Utiliza el mismo método de muestreo de rechazo que la solución Python de sgrieve. Por lo tanto, cada salida válida en realidad es igualmente probable.

Ilmari Karonen
fuente
7

Q (25 caracteres)

Original (27)

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

Salida de muestra

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

Ligeramente más corto (25)

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

JavaScript, 66 64 61 caracteres

Muy inspirado por TwoScoopsofPig (PHP) y 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
Gravedad
fuente
2
s!=72puede ser s-72para guardar un personaje. Y el último punto y coma ;atampoco es necesario para otro personaje.
Joe Tuskan
Nunca vi for(i=x;i;i--)antes, salva 2 caracteres de for(i=0;i<x;i++), gracias hombre!
Math chiller
7

Python 2, 70 bytes

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

Aquí hay otro, similar a la solución de sgrieve:

Python 2, 73 bytes + igual probabilidad

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

JavaScript, 116 99 65 bytes

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
fuente
1
Cuando ejecuto esto en Chrome 21, me sale i is not defined.
mellamokb
5

Python, 128 120 116 caracteres

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

import las declaraciones siguen matando la longitud (23 caracteres solo para importar 2 funciones en el espacio de nombres)

Espero que no necesite el resultado en un futuro cercano, ya que este código primero evalúa todas las soluciones posibles antes de elegir una al azar. quizás la solución más lenta a este problema.

reclamo felicitaciones adicionales por la misma probabilidad de cada configuración ...

Adrien Plisson
fuente
44
import random,itertools
Grawity
tienes razón, eso acorta un poco las cosas.
Adrien Plisson
Otros consejos: import random as r,itertools as iluego use ry en ilugar de randomy itertools. Usar en 18*[0]lugar de range(18), y en [3,4,5,6]lugar de range(3,6):)
Alex L
Estoy usando Python 3: una comprensión de la lista es un generador y no tiene longitud, lo que prohíbe su uso con la choice()función. eso también es lo que hace que este código sea tan lento ...
Adrien Plisson
1
ooops, lo siento, estropeé la comprensión de la lista y la expresión del generador (generalmente evito la comprensión de la lista a favor de la expresión del generador debido al mejor rendimiento del iterador). de hecho, incluso en python3 todavía puedo eliminar algunos caracteres ... @Alex lo hizo bien.
Adrien Plisson
4

PHP - 77 caracteres

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

Al igual que la solución de sgrieve, esto crea una lista de 18 hoyos, verifica el par total, lo imprime o lo rechaza e intenta nuevamente. Por extraño que parezca, nuestras dos soluciones tienen la misma longitud.

Bastante molesto, PHP no ofrece funciones de matriz con ninguna brevedad de nombre. Array_sum y print_r me están matando. Sugerencias bienvenidas.

TwoScoopsofPig
fuente
1
Aquí no se necesitan llaves, y la suma puede serlo +=. <?while($s!=72)for($s=$i=0;18>$i;$s+=$a[++$i]=rand(3,5));print_r($a);
Grawity
Eso es útil: nunca pensé poner la lógica en la llamada de bucle for (y me siento un poco tonto por no incrementar un contador para la suma).
TwoScoopsofPig
Gracias, pero eso no es lo que quise decir con "no se necesitan llaves"; podrías haberlos eliminado también en el código original:while(array_sum($a)!=72)for($i=0;18>$i;)$a[++$i]=rand(3,5);
Grawity
Bueno, excepto que corro contra un php.ini más estricto que eso porque estoy jugando al golf en el trabajo; no se queja de que faltan llaves o no coinciden. Normalmente lo hubiera hecho.
TwoScoopsofPig
Eso es extraño; 5.4.7 con E_ALL | E_STRICT nunca se queja de faltas {}(ya que la sintaxis de PHP lo permite explícitamente).
Grawity
4

Ruby 1.9 (62 caracteres)

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

Rieles (55 caracteres)

En $ rails cREPL (en cualquier carpeta Rails):

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

Nota: Funciona con Ruby 1.8 si lo usa en shuffle[0]lugar de sample.

js-codificador
fuente
2
¿Necesita espacios en blanco alrededor hasta?
Kaz
@Kaz Tienes razón, no es necesario. :) 62 caracteres ahora.
js-coder
1
Puede usar (1..18).map{rand(3)+3}para obtener la matriz aleatoria;)
epidemian
4

Lisp ( 78 69 caracteres)

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

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

Es bastante similar a la solución Python de sgrieve.

Comience con c como NIL, verifique la suma de 72, la do"función de incremento" para c genera una lista de 18 números entre 3 y 5, verifique nuevamente 72, haga espuma, enjuague, repita.

Es refrescante ver doy loopjugar golf juntos.

invierno
fuente
3

C (123 caracteres) - esfuerzo en eficiencia

Conduzca a través de wc y generará todas las soluciones 44152809 en 10 segundos ...

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, bueno, no leí la pregunta correctamente, pero dado que estamos generando todas las soluciones, elegir una aleatoria con la misma probabilidad es un ejercicio de secuencias de comandos: P

conejo bebé
fuente
3

Clojure - 55

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

Un truco bastante divertido ... explota la estructura matemática del problema de que debe haber exactamente 3 agujeros par por 5 agujeros par.

mikera
fuente
3

Python 83

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

Como la solución de sgrieve, pero sin numpy

Golf La solución de Adrien Plisson: 120-> 108 caracteres

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

Salida :

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

Alex L
fuente
Buen enfoque, pero puede guardar 4 bytes escribiendo en randi([3,5],1,18)lugar de3+floor(rand(1,18)*3)
brainkz
3

Java (61 caracteres)

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

Salida de muestra:

5 4 3 4 5 3 4 4 3 5 4 4 4 4 3 4 4 5
Quásar
fuente
No soy un experto en Java, pero ¿no debería haber una declaración de sy i, y algún tipo de llamada al Sistema # println (..)?
hiergiltdiestfu
Esto es solo un fragmento de código, no un programa. Y en realidad se parece mucho a la versión C de @JoeIbanez.
Franz D.
2

C (94 caracteres)

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

Es s=0posible que no se requiera la línea 1, porque ¿cuáles son las posibilidades de que un int sin inicializar sea igual a 72? Simplemente no me gusta leer valores no inicializados en C. Además, esto probablemente requiera sembrar la rand()función.

salida

3 3 3 4 5 5 3 3 4 5 5 4 3 4 5 5 5 3 
Joe Ibáñez
fuente
Entonces, ¿básicamente vas a recorrer cadenas aleatorias de 18 números que van del 3 al 5 hasta que uno sea igual a 72? Lo bueno es que la eficiencia no es un requisito.
KeithS
55
@KeithS Para ser justos, eso es lo que están haciendo la mayoría de las respuestas a esta pregunta.
Gareth
2

Bash shell script (65 caracteres)

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

( Shuf proviene del paquete GNU coreutils. Además, gracias Gareth).

Por favor levantese
fuente
2

C # (143 no espacios en blanco):

()=>{
  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
fuente
new Guid()crea un GUID vacío. Para generar realmente un GUID único, debe llamar a un método estático Guid.NewGuid.
Rotsor
Y tiene dos errores uno por uno (por así decirlo): las comparaciones deben ser i <ny i> = 18-n, no al revés. Y podría reducir el tamaño utilizando una constante 3 en lugar de x-1 y 5 en lugar de x + 1. Y luego podría reemplazar Enumerable.Repeat por Enumerable.Range.
Mormegil
Editado; Todavía 143 caracteres
KeithS
No hay Math.Random, es System.Random.
CodesInChaos
Otro enfoque de C # (143 caracteres):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

Haskell, 104 102 98 caracteres.

import System.Random
q l|sum l==72=print l|1>0=main
main=mapM(\_->randomRIO(3::Int,5))[1..18]>>=q
Rotsor
fuente
[1..n]>>[r]es un poco más corto que replicate n$r.
dejó de girar en sentido contrario a las agujas del reloj el
También cambiado sequencea mapM.
Rotsor
2

Perl, 74

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

Solución 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}]"
o_o
fuente
2

TXR (99 caracteres)

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

Esta expresión genera una lista infinita de números aleatorios del 3 al 5:

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

El resto de la lógica es un bucle simple que verifica si los primeros 18 elementos de esta lista suman 72. Si no, saca un elemento y lo intenta nuevamente. El forbucle contiene un bloque implícito llamado nily, por (return ...)lo tanto, puede usarse para terminar el bucle y devolver el valor.

Tenga en cuenta que la longitud de 99 caracteres incluye una nueva línea de terminación, que es necesaria.

Kaz
fuente
Puse un commit que permite que (t) sea reemplazado por (). :)
Kaz
2

APL 12

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

Tenga en cuenta que tengo el origen del índice establecido en 0, lo que significa que las matrices comienzan en 0. Puede configurar esto con ⎕IO←0.

Zaq
fuente
La pregunta hace un programa que puede producir todas las configuraciones posibles. Los tuyos pueden producir simétricos. No se puede producir, por ejemplo, 555455555333333343, al menos eso me parece.
Moris Zucca
2

R, 42 bytes

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

sample, por defecto, dibuja de manera uniforme entre los posibles valores (aquí 3 4 5). r=Trepresenta replace=TRUEy permite la muestra con reemplazo.

plannapus
fuente
2

CJam, 17 14 bytes

CJam es más nuevo que este desafío, pero esta no es la respuesta más corta de todos modos, por lo que eso realmente no importa.

Z5]Amr*I4e]mrp

Pruébalo aquí.

Para mantener el total de 72, cada uno 3debe estar emparejado 5. Pues así es como funciona:

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
fuente