Eu percebo que isso é um pouco matemático, mas - aqui vai.
Em matemática, a sequência de hiperoperação é uma sequência infinita de operações aritméticas (chamadas hiperoperações) que começa com a operação unária do sucessor e continua com as operações binárias de adição, multiplicação e exponenciação, após as quais a sequência prossegue com outras operações binárias que se estendem além exponenciação, usando a associatividade correta.
Seu objetivo é escrever um programa que use três números inteiros x, y e n como entrada e produza o resultado da enésima hiperoperação em x e y.
Por exemplo
1 1 1
saídas 2
2 4 4
saídas 65536
3 3 4
saídas 7625597484987
- O programa deve ser escrito no menor pedaço de código.
- Você pode receber informações de
STDIN
ou de um arquivo. - Funções de biblioteca não permitidas.
- Restrições de entrada: n será ≥ 1.
http://en.wikipedia.org/wiki/Tetration tem uma boa explicação, caso você não consiga entender isso.
code-golf
arithmetic
Soham Chowdhury
fonte
fonte
n=1
? Se éx+y
oux+1
,1 1 1
deve retornar2
Respostas:
Ruby, lento,
86 8483 caracteresRuby, rápido,
96 9493 caracteresA primeira versão é maneira muito lento com o último caso de teste, então eu adicionei uma versão que usa multiplicação como o caso base, em vez de adição. A primeira versão leva idades para ser calculada
3 3 4
; o segundo é instantâneo (no console nativo do IRB; a versão da Web é um pouco mais lenta).Várias belezas de Ruby aparecem aqui:
Quase toda declaração é uma expressão em rubi. Assim, você pode colocar ponto e vírgula dentro do operador ternário, desde que haja parênteses suficientes. Coffeescript pediu emprestado esse. Também emprestou a sintaxe de chamada "sem parênteses necessária" de Ruby.
Retornos implícitos: esse é um recurso interessante e segue o anterior. De fato, iniciar a última linha de uma função com
return
é considerado manco, mesmo quando não estiver jogando golfe.Números são objetos em rubi (par
null
é um objeto). Em ruby, números inteiros têm o métodotimes
, que executa o bloco passado a ele várias vezes. Este é apenas um dos muitos métodos de iterador do Ruby. Aqui, oupto
método permite salvar mais dois caracteres sobre o quetimes
nos permite.unário
*
é o operador splat aqui. Transforma uma matriz em uma lista de argumentos. Assim como o JavascriptFunction#apply
, mas é mais curto e melhor.unário
&
transforma um procedimento em um bloco. Embora:to_i
seja um símbolo, ele se converte em um procedimento muito bem. Ou seja, ele se transforma em um procedimento que invocato_i
seu argumento e retorna o resultado. Mais informações sobre estouro de pilha.Seria possível obtê-lo ainda mais rápido usando
n=3
como caso base, mas receio que não seja necessário. Porém, custaria apenas 11 caracteres, graças a outra beleza do rubi: o operador de exponenciação**
. O Python possui esse operador, mas não é o primeiro (como o @ aka.nice observou - obrigado -, o Fortran já tinha esse operador).intérprete de rubi on-line disponível aqui: http://repl.it/Ikj/1
fonte
3 3 4
:) é muito lento.APL, 62
{...}⎕
: Recebe a entrada avaliada (os números separados por espaço são avaliados em uma matriz numérica) e aplica a função a ela.1=3⌷⍵:
: Se n for igual a 1 ...2⌷+\⍵
: retornar a soma dos 2 primeiros elementos (x + y) ...⋄0=2⌷⍵:
: senão se y for igual a 0 ...(⍵[3]⌊3)⌷⍵[1],0,1
: criar matriz numérica [x, 0,1] e retornar índicemin(n,3)
...⋄∇⍵[1],(∇⍵-0 1 0),3⌷⍵-1
: Outro retorno ∇ (x, ∇ (x, y-1, n), n-1). (∇ é auto-referência)Eu tenho um operador "hyper-raiser", que assume uma função e retorna a próxima hiperoperação
Por exemplo,
+{⍺⍺/⊃⍴/⌽⍵}
seria a função de multiplicação e+{⍺⍺/⊃⍴/⌽⍵}5 3
gera 15.Mas não é possível fazê-lo recuar. Talvez alguém possa fazer isso.
fonte
Python, 83
(Com base na resposta do flornquake )
Muito lento para grandes resultados.
Para
2, 4, 4
a saída é65536
.fonte
Python,
9692Entrada:
3, 3, 4
Saída:
7625597484987
Encurtado usando algumas idéias de @ WolframH .
fonte
Golfscript, lento, 39 caracteres
(link ao vivo)
Este é o algoritmo recursivo padrão com um caso base de n = 1 (adição) (isto é, lento). O mesmo que usei na minha solução Ruby
Aqui está uma versão com minhas anotações (principalmente manutenção de pilha). Não inclui uma otimização que adicionei mais tarde:
~
é o operador eval. No caso de strings, ele trata a string como um programa GolfScript. Felizmente, uma lista de números inteiros separados por espaço é um programa GolfScript válido que coloca esses números inteiros na pilha. Comparado a isso, minha versão anterior da rotina de entrada (" "/{~}/
dividida por espaço e avaliada cada) é bastante ruim. No caso de funções, chama a função. Quando precedido por.
(clone), ele chama a função consigo como o primeiro argumento.O Golfscript não parece ser exatamente adequado para criar algoritmos recursivos. Se você deseja um algoritmo recursivo que não seja otimizável por chamada de cauda, precisará criar e destruir quadros de pilha para preservar suas variáveis. Na maioria dos idiomas, isso é feito automaticamente. No golfscript, você precisa realmente clonar as variáveis (na verdade, entradas da pilha) e destruir as entradas da pilha que não são mais necessárias. Golfscript não tem conceito de quadros de pilha. Eu disse que o GolfScript é uma linguagem baseada em pilha?
O primeiro requisito é compreensível. Você precisa especificar os argumentos de alguma forma. Só é bom se eles mantiverem suas posições originais também. O segundo requisito é lamentável, especialmente porque o valor de retorno está no topo da pilha e o golfscript não tem a capacidade de excluir apenas qualquer elemento da pilha. Você pode girar a pilha e descartar o novo elemento superior, mas isso se acumula rapidamente.
\;
está bem.\;\;\;\;\;
não é. Você pode fazer isso\;
em um loop ({\;}9*
; custo: 6 caracteres para descartar até 9 elementos ou 7 caracteres para descartar até 99 elementos), mas podemos fazer melhor:O Golfscript possui matrizes de primeira classe. Ele também possui a sintaxe literal da matriz
[1 2 3 4]
. O que é inesperado é isso[
e,]
na verdade, não faz parte da sintaxe. São apenas dois operadores:[
marca a posição atual na pilha e]
coleta todos os elementos até encontrar a marca de início da matriz ou ficar sem pilha e descartá-la. Você pode até separar esses dois e ver o que acontece. Bem, uma coisa interessante:Eu disse golfscript não tem conceito de frames de pilha? Eu menti. Este é um quadro de pilha:
[
. Você pode descartar tudo de uma vez:];
. Mas e se quisermos manter o valor de retorno? Você pode fechar o quadro da pilha na entrada da função (então temos uma versão ligeiramente confusa do passo a matriz - não é um conceito interessante), ou podemos fechar o quadro da pilha e pegar seu último elemento em vez de descartá-lo completamente:]-1=
ou nós pode uncons o último elemento em vez disso, e em seguida, descartar o quadro:])\;
. Eles têm o mesmo comprimento, mas o último é um pouco mais frio, então eu estou usando.Então, em vez de 6 ou 7 caracteres para fazer uma limpeza, podemos fazer o 5. Ainda sinto que isso poderia ser mais praticado, mas ei, salvamos um personagem.
fonte
Squeak Smalltalk 4.x sabor muitos bytes!
Eu poderia implementar uma das formas recursivas em Inteiro em 71 caracteres
A leitura de um arquivo ou do FileStream stdin vai me custar um braço ... O Squeak obviamente não foi projetado como uma linguagem de script. Portanto, gastarei muitos bytes para criar meus próprios utilitários de uso geral não relacionados ao problema:
Implemente esse método de 21 caracteres no Stream (para pular os seaparators)
Implemente esse método de 20 caracteres no comportamento (para ler uma instância de um fluxo)
Em seguida, 28 caracteres na String (para criar um identificador de arquivo)
Em seguida, 59 caracteres no FileDirectory (para criar um readStream)
Em seguida, 33 caracteres no BlockClosure (para avaliar n vezes)
Em seguida, 63 caracteres na matriz (avalie o argumento com o receptor e os argumentos extraídos da matriz)
em seguida, resolva o problema avaliando esse snippet de 31 caracteres em qualquer lugar para ler do arquivo chamado x
Mesmo sem contar os utilitários, já são 71 + 31 = 102 caracteres ...
Agora, como tenho certeza de perder o codeGolf, tenho uma implementação mais divertida no Integer:
Este método definirá (compilar) uma mensagem binária feita de n + se ela não existir (não é entendida pelo destinatário da mensagem m) e reiniciará a execução no início do contexto do remetente. Inseri um retorno de carro adicional e espaços para facilitar a leitura.
Observe que
(m selector size-2min:1)hex last
é uma forma abreviada de(m selector size>2)asBit printString
.Se não fosse para demonstrar superpoderes do Smalltalk, a última declaração poderia ser substituída por mais curta e simples
Agora implemente o utilitário 28 chars em Character (para repeti-lo n vezes em uma String)
Em seguida, avalie esta expressão de 43 caracteres:
Podemos acelerar com mais 10 caracteres implementando em Inteiro:
e, neste caso, também temos um código mais curto, porque podemos substituir
^',(m selector size-2min:1)hex last
por^1'
Por um preço tão alto, o código funciona com o segundo número inteiro = 0 :)
fonte
Groovy - 77
Nota: requer quantidades obscenas de pilha (e tempo) para argumentos não minúsculos.
fonte
Sistema de álgebra computacional do AXIOM, bytes 69
teste:
Isso eliminaria alguma recursão ... É possível trocar x e y em algum retorno ... existem outros valores de teste?
fonte
APL (NARS), caracteres 61, bytes 122
teste:
fonte