Você está remando em uma canoa em um rio de águas claras razoavelmente rápido. De repente, seus remos explodem e você se encontra em uma situação perigosa que desce rapidamente um rio sem remos. Felizmente, você ainda tem suas habilidades de programação, por isso decide criar um programa na lateral da sua canoa para ajudá-lo a sobreviver às corredeiras. No entanto, como não há muita área de superfície na lateral da canoa para escrever seu programa, você deve torná-lo o mais curto possível.
O rio pode ser representado como uma grade de 8 por 16. Iremos rotular as colunas com os números 0
para 7
e as linhas com os números 0
para 15
.
y
--------15
--------14
--------13
--------12
--------11
--------10
--------9
--------8
--------7
--------6
--------5
--------4
--------3
--------2
--------1
--------0
01234567
x
Acima: Um rio completamente calmo e comum, sem obstruções. Naturalmente, este não é o rio em que você está.
Você começa na coordenada (4, 0) e daí sobe incontrolavelmente no rio (ou seja, o vetor (0,1)
) até atingir uma rocha (representada por um o
nesses exemplos). Quando você bate em uma pedra, você tem 55% de chance de passar da pedra para a esquerda (ou seja, o vetor (-1,1)
) e 45% de chance de passar da pedra para a direita (ou seja, o vetor (1,1)
). Se a canoa estiver nas colunas da extrema esquerda ou direita, ela sempre se moverá em direção ao centro. Se não houver pedras, ela se moverá para cima.
y
----x---15
----xo--14
-o--x---13
----x---12
---ox---11
---x----10
---xo---9
---ox---8
----xo--7
-----x--6
----ox--5
-o--x---4
----x---3
----xo--2
----x---1
----x---0
01234567
Acima: Uma possível rota que a canoa pode seguir, representada usando o personagem x
Dado o mapa do rio, escreva um programa que mostre a probabilidade de a canoa terminar em uma determinada coluna.
Aceite a entrada no método que for mais conveniente para o seu programa (por exemplo, STDIN, argumento de linha de comando raw_input()
, leitura de um arquivo, etc.). A primeira parte da entrada é um único inteiro de 0 a 7, representando a coluna para a qual o programa encontrará a probabilidade. A seguir, é apresentada uma lista de tuplas na forma que x,y
representa a posição das pedras.
Um exemplo:
Entrada:
4 4,1 5,5 3,5
Isso indicaria um rio com rochas nas posições (4,1), (5,5) e (3,5), e pedia a probabilidade da canoa terminar na 4ª coluna.
Saída:
0.495
Observe que neste exemplo, as posições das rochas eram simétricas, permitindo que o problema fosse resolvido com uma distribuição binomial. Nem sempre será esse o caso!
Além disso, o rio será sempre atravessável. Ou seja, nunca haverá duas rochas posicionadas adjacentes uma à outra horizontalmente. Veja o comentário de Glenn para um exemplo de caso impossível.
Este é o código de golfe, portanto, o menor número de caracteres vence. Sinta-se à vontade para fazer perguntas nos comentários, se a especificação não estiver clara.
fonte
Respostas:
GolfScript, 105 caracteres
Uma versão do GolfScript que ficou muito mais longa do que o pretendido - mas cada tentativa com uma abordagem diferente foi ainda mais longa. A entrada deve ser fornecida no STDIN.
Exemplo:
Código anotado:
fonte
Ruby,
204191172 caracteresSimula recursivamente todos os resultados possíveis, mantendo o controle da probabilidade de cada resultado individual e, em seguida, adiciona essa probabilidade a um contador cumulativo quando
y == 15
.Truques extravagantes:
c,*r=gets.split
- o operador "splat" (*
) pega todos os elementos restantesgets.split
e os cola nor
arraynext {something} if {condition}
: essencialmente equivalente a"Descoberto" evoluindo deif condition; something; return; end
parareturn something if condition
parabreak something if condition
, e então imaginei que tentaria um "operador de loop" mais curto para ver se funcionaria (o que funcionou, é claro).Agradeço a @ MartinBüttner por sugerir o uso de operadores ternários encadeados (que acabaram se tornando a enorme terceira linha no código golfado acima) e eliminando o ponto acima (que salvou 19 (!) Caracteres).
Entretanto, usei um truque chique: percebi que
s[foo],s[bar]
não funciona no Ruby para duas chamadas de método em uma instrução. Então, no começo eu mudei para(_=s[foo],s[bar])
(uma variável dummy), mas então eu percebi que eu poderia apenas adicionar e jogue fora os valores de retorno:s[foo]+s[bar]
. Isso só funciona porque as chamadas paras
apenas "retornam" outras chamadas paras
ou para um número (o[x]+=p
), portanto, não preciso me preocupar em procurarnil
.Outras várias otimizações: em
p
vez deputs
imprimir números, em<1
vez de==0
(já que a canoa nunca sai do rio) e comparações semelhantes em outros lugares,[0]*8
para probabilidades iniciais, pois os números de Ruby são sempre "passados por valor"Ungolfed:
fonte
next X if Y
em operadores ternários aninhados? Boa descoberta, no entanto, você pode querer adicioná-lo às dicas de Ruby!C #
418364bytesPrograma C # completo esperando entrada do STDIN. Funciona lendo as rochas em uma matriz de todos os locais do rio, criando efetivamente um mapa e, em seguida, realiza apenas 16 iterações de probabilidades de movimentação em torno de uma matriz decimal de 8 larguras antes de gerar o resultado.
Código formatado:
fonte
for(;j-->0;)
). Você pode se livrar de alguns caracteres substituindo o últimoC.WriteLine
porC.Write
. Além disso, se você usar emfloat
vez de,decimal
poderá salvar mais alguns bytes.decimal
porquefloat
não será preciso, mas o decimal deve ser útil para esses problemas, mas provavelmente poderia sair como ele diz. Vou colocar naC.Write
se eu conseguir golfe mais esta questão como é provavelmente mais perto da especificação do queC.WriteLine
como eu não acho que 4 bytes garante uma edição para este programa tamanho;)Haskell, 256 bytes
Aqui está uma versão muito não-gasta, juntamente com alguns truques que foram usados:
O último truque que usei foi observar que você pode agir como se as rochas em uma única linha fossem realmente separadas por uma quantidade infinitesimal. Em outras palavras, você pode aplicar o transformador de distribuição de probabilidade para cada rocha na mesma linha seqüencialmente e na ordem que desejar, em vez de aplicá-las todas simultaneamente. Isso só funciona porque o problema não permite duas rochas horizontalmente adjacentes.
Portanto, o programa transforma a localização de cada rocha em um transformador de distribuição de probabilidade, ordenado pela coordenada y da rocha. Os transformadores são então encadeados em ordem e aplicados à distribuição de probabilidade inicial. E é isso!
fonte
Perl 169 bytes
Lê de STDIN.
Bem direto, usa implicitamente as colunas -1 e 8 para suavizar casos de borda. As probabilidades podem ser propagadas com segurança para cada próximo nível, porque não existem pedras adjacentes, portanto, uma única corrida é suficiente.
fonte
PHP, 358
Usar a inteligência para determinar os caminhos possíveis e suas probabilidades é difícil e provavelmente exigiria mais código do que simplesmente simular 1.000.000 de acidentes com canoas. Oh, a humanidade!
Exemplo:
Golfe:
Esta versão não produz uma impressão bonita e gera a probabilidade de flutuação do desembarque da canoa na posição especificada.
fonte
PHP, 274
Não consigo ler / escrever o GolfScript para salvar minha vida, mas olhar para a submissão de @ Howard me indicou uma direção melhor do que simplesmente simular 1 milhão de acidentes de canoa.
Começando com uma variedade de probabilidades para posições iniciais, podemos simplesmente dividir esses números cada vez que uma pedra é encontrada.
Saída de exemplo:
Golfe:
Exemplo de execução:
fonte
Haskell, 237
Só espero que a canoa venha com o ghc instalado ...
O truque da lista infinita é roubado de Matt Noonan, parabéns a ele!
Espero ter acertado a lógica, mas o exemplo de Matt
"5 4,4 1,5 5,3 3,6 2,9 4,12 3,13"
cede0.5613750000000001
e o exemplo de OP"4 4,1 5,5 3,5"
cede0.49500000000000005
, o que parece estar correto, exceto por alguns erros de ponto flutuante.Aqui está em ação:
fonte