Você pode golfe golfe?

53

Você é obrigado a gerar um campo de golfe aleatório de 18 buracos.

Exemplo de saída:

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

Regras:

  • Seu programa deve gerar uma lista de comprimentos de orifícios para exatamente 18 orifícios
  • Cada orifício deve ter um comprimento de 3, 4 ou 5
  • Os comprimentos dos furos devem somar 72 em todo o percurso
  • Seu programa deve ser capaz de produzir todas as configurações de furos possíveis com uma probabilidade diferente de zero (as probabilidades de cada configuração não precisam ser iguais, mas fique à vontade para pedir elogios extras, se for o caso)
Mikera
fonte
3
Por favor, confirme, 44152809 soluções?
baby-rabbit
11
Também estou curioso sobre o número exato de soluções, no entanto, acho que deveria ser mais de 44 milhões ... (no entanto, não sou matemático: | 1 (5) / 1 (3) = 306 possibilidades (17 * 18) | 2 (5) / 2 (3) = 69360 poss (17 * 17 * 16 * 15) | 3 (5) / 3 (3) = 11182080 poss (16 * 16 * 16 * 15 * 14 * 13) | faz que parece certo?
NRGdallas
11
@ baby-rabbit: posso confirmar 44.152.809 soluções por enumeração de força bruta. Além disso, ele pode ser calculado diretamente desta forma: uma vez que a média é exatamente 4, e as únicas possibilidades são 3, 4ou 5, a possível solução aulas são { 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}. Isso pode ser calculado 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. Isso significa que aproximadamente 11.4%todas as combinações possíveis são soluções válidas (44,152,809 / 3^18).
Mellamokb 26/09/12
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

Respostas:

29

k ( 18 17 16 caracteres)

De volta à abordagem original, credite à CS a melhoria.

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

Outra abordagem (17 caracteres), mesmo método da solução J, H / T para CS

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

Versão antiga:

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

Não é suscetível ao estouro de pilha e é executado em uma quantidade fixa de espaço.

skeevey
fonte
O que é H / T para CS?
Gareth
Este programa me ajudou a descobrir um bug no meu intérprete K- obrigado! Eu não percebi anteriormente que nilads poderiam ser aplicadas a um único argumento (que eles ignoram).
precisa saber é
17

K, 28

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

J, 20 18 17 caracteres

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

Isso funciona da mesma maneira que a resposta anterior, exceto que os 9 dígitos aleatórios são 0 ou 1 e são negados antes de serem anexados. Isso significa que existem tantos -1s quanto existem 1s. Adicionando 4 me dá uma lista de 3s, 4s e 5s que somam 72 cada vez.

Resposta anterior:

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

Gera os 9 primeiros buracos aleatoriamente ?9#3, depois os copia e os inverte (,2-])(transforma um 3 em um 5 e um 5 em um 3) para gerar o 9. final. Isso garante que o total será 72 (já que a cada 3 terá um 5 correspondente). o total médio por furo será 4 e 4x18 = 72). Em seguida, embaralha aleatoriamente o resultado ({~?~@#)para garantir que todas as combinações sejam possíveis.

Gareth
fonte
na verdade, você não vai gerar {3,5,4,4,4 ...} você é melhor para baralhar todo o resultado
aberração catraca
@rachetfreak Bom ponto. Eu vou editar agora.
Gareth
13

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

Hexdump:

0E5F576A12595188ECE44088C3E44130D8240374F400C4AAE2EF595E80FC2475DFAC0432CD29B020CD29E2F5C3

Binário codificado em Base64:

Dl9XahJZUYjs5ECIw+RBMNgkA3T0AMSq4u9ZXoD8JHXfrAQyzSmwIM0p4vXD

Código fonte real com alguns comentários:

 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.come execute no MS-DOS (ou Dosbox) ou NTVDM a partir de uma versão do Windows de 32 bits.

Saída de amostra:

4 5 4 5 4 5 3 4 3 4 3 4 4 5 4 3 5 3
Jonas Gulle
fonte
3
amor assembler ...
woliveirajr
13

Mathematica 71 68 66 60

Com 6 caracteres salvos por sugestão 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 os resultados possíveis são possíveis, mas não são igualmente prováveis.


Análise

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

produz todas as 10 partições possíveis (combinações, não permutações) de 72 em 18 elementos que consistem em 3, 4 e 5.

partições


RandomChoice seleciona um deles.

RandomSample retorna uma permutação dessa escolha.

DavidC
fonte
Hehe, eu estava prestes a postar quase exatamente a mesma resposta, usando apenas RandomChoice em vez de RandomInteger. Eu acho que você pode fazer a barba de mais 4 personagens fazendo isso.
Tally
Tally, obrigado. Sua sugestão foi útil.
28414
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

O algoritmo é semelhante ao @ sgrieve.

flodel
fonte
O mesmo problema do @sgrieve acima - nada impede que ele ultrapasse os 18 buracos.
Gt6989b
3
Isso não é um problema, o comando de amostra nesse caso sempre gera 18 valores.
sgrieve
8

GolfScript (26 caracteres)

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

Existem algumas semelhanças óbvias com a solução de Ilmari, mas também algumas diferenças óbvias. Em particular, estou explorando o fato de que o par médio é 4.

Peter Taylor
fonte
Porra, mas com certeza é um truque inteligente com a condição de loop lá. Eu vim {;0{3.rand+.@+}18*])72-}docomigo mesmo, mas não consegui descobrir como reduzi-lo a partir daí. +1.
Ilmari Karonen
7

Python 77

Código

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

Resultado

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

A importação realmente mata essa solução. Ele usa numpy para gerar 18 números entre 3 e 5 e continua gerando listas até que a soma da lista seja 72.

lamentar
fonte
O que impede que o programa chegue a 72 poços antes de gerar 18 buracos? O que o impede de pular 72?
DavidC
3
O código sempre gera 18 buracos e, em seguida, verifica se a soma é igual a 72. Por exemplo, se a soma após 16 buracos fosse 72, ainda geraria outros 2 buracos, pressionando a soma acima de 72 e falhando no teste.
sgrieve
7

GolfScript, 27 caracteres

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

Usa o mesmo método de amostragem de rejeição da solução Python do sgrieve. Portanto, toda saída válida é realmente igualmente provável.

Ilmari Karonen
fonte
7

Q (25 caracteres)

Original (27)

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

Saída de amostra

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

Um pouco mais curto (25)

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

JavaScript, 66 64 61 caracteres

Fortemente inspirado em 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
gravidade
fonte
2
s!=72pode ser s-72para salvar um caractere. E o último ponto e vírgula ;atambém não é necessário para outro caractere.
Joe Tuskan
eu nunca vi for(i=x;i;i--)antes, ele salva 2 caracteres for(i=0;i<x;i++), obrigado cara!
Math chiller
7

Python 2, 70 bytes

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

Aqui está outro, semelhante à solução do sgrieve:

Python 2, 73 bytes + probabilidade igual

from random import*
a=[]
while sum(a)-72:a=sample([3,4,5]*18,18)
print a
daniero
fonte
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
fonte
11
Quando executo isso no Chrome 21, recebo i is not defined.
Mellamokb 26/09/12
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 instruções ainda são extintas (23 caracteres apenas para importar 2 funções no espaço para nome)

espero que você não precise do resultado em um futuro próximo, pois esse código avalia primeiro todas as soluções possíveis antes de escolher uma aleatoriamente. talvez a solução mais lenta para esse problema.

Eu reivindico elogios extras pela mesma probabilidade de cada configuração ...

Adrien Plisson
fonte
4
import random,itertools
grawity
você está certo, isso encurta um pouco as coisas.
Adrien Plisson
Outras dicas: import random as r,itertools as iuse re em ivez de randome itertools. Use 18*[0]em vez de range(18), e [3,4,5,6]em vez de range(3,6):)
Alex L
Eu estou usando python 3: uma lista de compreensão é um gerador e não tem comprimento, o que proíbe seu uso com a choice()função Isso também é o que torna este código tão lento ...
Adrien Plisson
11
desculpe, eu estraguei a compreensão da lista e a expressão do gerador (geralmente evito a compreensão da lista em favor da expressão do gerador por causa do melhor desempenho do iterador). então, mesmo em python3, ainda posso remover alguns caracteres ... @Alex fez isso direito.
Adrien Plisson
4

PHP - 77 caracteres

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

Assim como a solução da sgrieve, ela cria uma lista de 18 buracos, verifica o valor total do par e imprime ou rejeita e tenta novamente. Curiosamente, nossas duas soluções têm o mesmo comprimento.

De maneira irritante, o PHP não oferece funções de matriz com nenhuma brevidade de nome. Array_sum e print_r estão me matando. Sugestões são bem-vindas.

TwoScoopsofPig
fonte
11
Aparelhos cacheados não são necessários aqui, e a soma pode ser +=. <?while($s!=72)for($s=$i=0;18>$i;$s+=$a[++$i]=rand(3,5));print_r($a);
grawity
Isso é útil - nunca pensei em colocar a lógica na chamada de loop for (e me sinto meio burro por não aumentar um contador para a soma).
TwoScoopsofPig
Obrigado - mas não é exatamente isso que eu quis dizer com "chaves não necessárias"; você também pode removê-los no código original:while(array_sum($a)!=72)for($i=0;18>$i;)$a[++$i]=rand(3,5);
grawity
Bem, exceto que eu corro contra um php.ini mais rigoroso do que isso porque estou jogando golfe no trabalho; ele não se queixa de falta ou incompatibilidade entre chaves. Normalmente eu teria.
TwoScoopsofPig
Isso é estranho; 5.4.7 com E_ALL | E_STRICT nunca reclama de falta{} (porque a sintaxe do PHP permite explicitamente isso).
grawity
4

Ruby 1.9 (62 caracteres)

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

Trilhos (55 caracteres)

No $ rails cREPL (em qualquer pasta Rails):

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

Nota: Funciona com o Ruby 1.8 se você usar em shuffle[0]vez de sample.

js-coder
fonte
2
Você precisa de espaço em branco até?
Kaz
@ Kaz Você está certo, não é necessário. :) 62 caracteres agora.
JS-codificador
11
Você pode usar (1..18).map{rand(3)+3}para obter a matriz aleatória;)
epidemian
4

Lisp ( 78 69 caracteres)

(do (c () (mapcar (lambda (x) (+ 3 (aleatório 3))) (lista de composição 18)))) ((= (aplicar '+ c) 72) c))

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

É bastante semelhante à solução Python do sgrieve.

Comece com c como NIL, verifique uma soma de 72, a do"função de incremento" para c gera uma lista de 18 números entre 3 e 5, verifique 72 novamente, ensaboar, enxaguar, repetir.

É refrescante ver doe loopjogar golfe juntos.

muda de inverno
fonte
3

C (123 caracteres) - esforço de eficiência

Conduza através do wc e gerará todas as soluções 44152809 em 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, bem - não li a pergunta corretamente - mas, como estamos gerando todas as soluções, escolher uma aleatória com igual probabilidade é um exercício de script: P

coelho bebê
fonte
3

Clojure - 55

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

Um truque bastante divertido .... explora a estrutura matemática do problema de que deve haver exatamente 3 buracos de par e 5 buracos de par.

Mikera
fonte
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 a solução de sgrieve, mas sem entorpecente

Solução de golfe 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

Saída :

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

Alex L
fonte
Boa abordagem, mas você pode salvar 4 bytes digitando em randi([3,5],1,18)vez 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);

Saída de amostra:

5 4 3 4 5 3 4 4 3 5 4 4 4 4 3 4 4 5
Quasar
fonte
Eu não sou especialista em Java, mas não deveria haver uma declaração de eu e algum tipo de chamada para o System # println (..)?
hiergiltdiestfu
Este é apenas um trecho de código, não um programa. E na verdade parece muito com a versão C do @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]);

o s=0 linha 1 pode não ser necessária, porque quais são as chances de um int não inicializado ser igual a 72? Eu simplesmente não gosto de ler valores não inicializados na reta C. Além disso, isso provavelmente requer a propagação dorand() função.

resultado

3 3 3 4 5 5 3 3 4 5 5 4 3 4 5 5 5 3 
Joe Ibanez
fonte
Então, basicamente, você percorrerá seqüências aleatórias de 18 números que variam de 3 a 5 até que um seja igual a 72? Ainda bem que a eficiência não é um requisito.
Keith
5
@KeithS Para ser justo, é isso que a maioria das respostas a esta pergunta está fazendo.
Gareth
2

Script shell Bash (65 caracteres)

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

( shuf vem do pacote GNU coreutils. Além disso, obrigado Gareth.)

PleaseStand
fonte
2

C # (143 sem espaço em branco):

()=>{
  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
fonte
new Guid()cria um GUID vazio. Para realmente gerar um GUID exclusivo, você precisa chamar um método estático Guid.NewGuid.
Rotsor 26/09/12
E você tem dois erros isolados (por assim dizer): as comparações devem ser i <n e i> = 18-n, e não o contrário. E você pode reduzir o tamanho usando uma constante 3 em vez de x-1 e 5 em vez de x + 1. E então você pode substituir Enumerable.Repeat por Enumerable.Range.
Mormegil 26/09/12
Editado; ainda 143 caracteres
KeithS 26/09/12
Não existe Math.Random, é System.Random.
CodesInChaos
Outra abordagem 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
fonte
[1..n]>>[r]é um pouco menor que replicate n$r.
deixou de girar no sentido anti-
Também foi alterado sequencepara mapM.
Rotsor 27/09/12
2

Perl, 74

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

Solução 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
fonte
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))))

Essa expressão gera uma lista lenta e infinita de números aleatórios de 3 a 5:

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

O restante da lógica é um loop simples que verifica se os 18 primeiros elementos desta lista somam 72. Caso contrário, ele exibe um elemento e tenta novamente. ofor loop contém um bloco implícito chamado nile, portanto,(return ...) pode ser usado para finalizar o loop e retornar o valor.

Observe que o comprimento de 99 caracteres inclui uma nova linha final, necessária.

Kaz
fonte
Coloquei um commit que permite que o (t) seja substituído por (). :)
Kaz
2

APL 12

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

Observe que eu tenho a origem do índice definida como 0, o que significa que as matrizes começam em 0. Você pode definir isso com ⎕IO←0.

Zaq
fonte
A pergunta faz um programa que pode produzir todas as configurações possíveis. Os seus podem produzir simétricos. Você não pode produzir, por exemplo, 555455555333333343, pelo menos me parece.
Moris Zucca
2

R, 42 bytes

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

sample, por padrão, desenha igualmente entre os valores possíveis (aqui 3 4 5). r=Trepresenta replace=TRUEe permite a amostra com substituição.

plannapus
fonte
2

CJam, 17 14 bytes

O CJam é mais novo que esse desafio, mas essa não é a resposta mais curta, então isso realmente não importa.

Z5]Amr*I4e]mrp

Teste aqui.

Para manter o total de 72, cada um 3deve estar emparelhado 5. Então, aqui está como isso 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
fonte