Escreva uma função f
,, que obtenha um número inteiro positivo e retorne uma função.
A nova função retornada deve ser idêntica a f
. No entanto, quando a "chamada de encerramento" ocorrer, f
deve retornar a soma de todos os números inteiros passados.
Por exemplo, g=f(4)
(se f
é a primeira função) deve ser definida g
para outra função. h=g(3)
fará o mesmo. No entanto, quando você chama h
sem argumentos (veja os detalhes abaixo), ele deve gerar 7, pois é a soma dos argumentos da função anterior. Dito de outra maneira f(3)(4)() == 7
.
Observe que isso não é o mesmo que f(3,4)()
.
"Chamada de encerramento" é uma das seguintes opções (sua escolha):
- chamar sem argumentos
- nulo como argumento
- qualquer valor não positivo
A quantidade arbitrária de chamadas de função deve ser suportada, não há limite predefinido.
É garantido que a soma total não será maior que 1'000.
Podemos assumir que existe pelo menos uma chamada antes da "chamada de encerramento".
Seu código não deve usar variáveis estáticas por programa, portanto, deve ser possível executar o experimento várias vezes no mesmo tempo de execução e observar exatamente o mesmo comportamento.
Exemplos:
f(1)() == 1
f(4)(2)(7)() == 13
f(4)(2)(7)(5)(2)() == 20
fonte
f(4)
retorna uma nova função. Se essa nova função for chamada sem argumentos, ela retornará4
, mas se for chamada com outro argumento, ela retornará novamente uma nova função com a mesma semântica, mas com o novo argumento adicionado ao4
e assim por diante.q = f(2)(3); b = f(1)(2)(3); q(); b()
?Respostas:
JavaScript (ES6), 18 bytes
Passe um valor falso para recuperar a soma. Zeros podem ser permitidos por um custo de 2 bytes.
Experimente online
Ungolfed:
fonte
Haskell (GHC), 118 bytes
São 98 bytes para o código e 20 bytes para o sinalizador do compilador GHC
-XFlexibleInstances
, o que permite uma extensão do sistema de tipos.Isso define uma "função"
f
, que pode ser chamada com um número arbitrário de números inteiros seguido pela unidade()
, após o qual retorna um número inteiro. As anotações de tipo são obrigatórias. Experimente online!Explicação
Forçar o sistema de tipo estrito de Haskell a permitir isso requer alguma mágica, a saber, habilitar a extensão GHC para instâncias flexíveis de classe de tipo. Como isso funciona é que
f
é uma função parametricamente polimórfica restrita por uma restrição de classe de tipo: seu tipo éF a => Int -> a
. Isso significa quef
recebe um número inteiro e retorna um valor do tipoa
, para qualquer tipoa
que pertença à classe de tipoF
.F
é apenas o nome da classe de tipo que fornece a funçãof
; é declarado na primeira linha.As próximas duas linhas são duas instâncias de
F
tipos diferentesa
. A segunda linha indica que o tipo de funções de()
para inteiros pertenceF
(onde()
é o tipo de unidade cujo único membro é o valor()
) e a implementação éf n () = n
; a função retorna seu primeiro argumento. A última linha afirma que, sea
pertencerF
, o mesmo ocorre com o tipo de funções de números inteiros paraa
: de uma funçãof :: Int -> a
, podemos gerar outra funçãof :: Int -> Int -> a
. A implementação éf m n = f (m+n)
(o código usa combinadores para torná-lo mais curto), onde of
da esquerda é o novo e of
da direita é o antigo. Isso essencialmente dáf
um novo argumento inteiro, que é adicionado ao próximo. Vários argumentos são somados como este:O
f
em cada linha tem um tipo diferente.As funções Haskell são alteradas automaticamente, portanto, se você fornecer
f
apenas números inteiros, obterá uma função.fonte
f
, não uma única função que faz o trabalho. No entanto, isso é o mais próximo que você pode chegar em Haskell. Eu não acho que é possível resolver a tarefa com uma única função por causa do sistema estrito de tipos.f
, mas infinitamente muitas funções chamadasf
. (Uma para cada número possível de argumentos.) Essas funções (dessa família infinita) têm dois tipos de definições, uma quando o número de argumentos é zero e a outra quando não.f n()=n
ef=(f.).(+)
, então, eu chamaria de definição de duas funções.g 0 = 1
eg n = g (n-1) * n
, onde existem duas definições, mas apenas uma função. Aqui temos duas definições, mas infinitamente muitas funções. (Cada de um tipo diferente.)ghci
carregamento acima e tente:t f
- diráf :: F a => Int -> a
(o que significa que sea
é uma instância da classef
, entãof
é uma funçãoInt -> a
). Portanto, poderíamos considerar isso como uma função ou infinitamente muitas, mas, embora tenha dois tipos de definições (assim como a função fatorial), não vejo nenhuma boa base para considerar duas funções.Python 2,
424136 bytesEssa solução nunca terá um estouro, pois o Python suporta números inteiros de precisão arbitrária. Zero é o "valor especial".
Experimente online
Ungolfed:
fonte
C,
6258 bytes, borderline competindoGuardado 4 bytes graças a Kevin! (Ainda não removemos o typedef porque é algo necessário para ser chamado.)
A função a chamar é
f
; você para de chamá-lo e obtém o resultado chamando-o com um número não positivo como0
. Experimente um equipamento de teste online!Portanto, até onde eu sei, a única maneira de "curry" funções que possuem vários tipos de retorno é fazer um dos seguintes:
union
/struct
que tenha umint
subtipo e function / auto-referencial.Eu tentei fazer (2), mas parecia um pouco contra o espírito da pergunta e, francamente, quase desfazível. Assim, de acordo com o espírito do desafio, optei pela opção (1). Isso requer converter cada função retornada em uma função, para que possa ser usada.
Essa sintaxe "currying" parece um pouco estranha, mas é bastante semelhante. Para imitar
f(21)(1)
, seria preciso escrever((B)((B)f(21))(1))(0)
. Eu defini oB
tipo como uma função que usa um número inteiro e retorna um ponteiro para uma função que usa um número inteiro. Expandido, parece com:fonte
q;f(x){return x?(q+=x,f):q;}
.q
depois de cada corrida, então a função não seria mais utilizávelMathematica, 25 bytes
Experimente online! (Usando matemática.)
É possível fazer três bytes a menos, portando a resposta JavaScript, mas eu queria apresentar uma solução Mathematica mais idiomática. O
@
açúcar é apenas um pouco sintático, o que torna a solução equivalente a:Então, sim, a ideia é que, no Mathematica, você não pode apenas definir uma função,
f[x_]
mas pode anexar diretamente um valor a uma expressão mais complicada que contenhaf
, por exemplo,f[x_]
receber outro argumento. Configurando duas definições para isso, podemos obter o comportamento desejado:f[x][y]
chamadaf[x+y]
, consumindo uma "chamada" e adicionando os argumentos internos. Esta regra se aplica até que fiquemosf[sum][]
.sum
.fonte
C ++, 72 bytes
Isso define um tipo
F
que atua como a função solicitada e uma variávelf
desse tipo a ser invocada. É válido a partir do C ++ 11 e funciona com versões online do GCC, clang, icc e VC ++.Uso:
Explicação:
Após o pré-processamento e reformatação, ele se parece com:
Isso normalmente seria escrito:
return a;
ereturn {+a};
faça o mesmo, como unário+
não altera o valor, e chaves redundantes em torno do valor de retorno são permitidas.int m
eint(m)
faça o mesmo, pois parênteses redundantes em torno de um nome de variável são permitidos, incluindo parâmetros de função.return {m+a};
ereturn {int(m)+a};
faça a mesma coisa, pois o lançamento dem
fromint
paraint
não altera seu valor. Essas alterações aproximam as duasoperator()
sobrecargas na sintaxe, permitindo que uma única definição de macro seja chamada duas vezes. Escolher a ordem correta para os três membros permite que a primeira palavra da próxima linha (int
) seja incluída também na definição da macro.fonte
operator()
para fazer esse trabalho foi especialmente legal.Ruby, 23 bytes
Uso:
fonte
C,
10496 bytesUsa o método no link que @JulianWolf compartilhou. O último argumento deve ser 0.
Experimente online!
fonte
Math.JS, 38 bytes
Ligue com
f(number_a)(number_b)(...)(negative_number)
Se for permitido especificar a chamada inicial, 12 bytes (
f(x)=i(x,0)\n
) podem ser eliminados e podem ser chamados comi(number_one,0)(number_two)(...)(negative_number)
Tente!
Explicação
Como mostrado no LaTex acima,
f(x)
simplesmente chamai(x,0)
, então,i(x,y)
retorna o valor dey
sex
for menor que 0, ou a funçãoj(z)=i(z,x+y)
, que aceita um argumento, que executa um loop. Adicionando ao valor dey
.fonte
C,
232206 bytesProvavelmente, isso pode ser muito importante, mas deve servir como prova de conceito de que C pode ser usado, sem nenhuma extensão de idioma *, para resolver esse problema chamando sem argumentos e não com um valor mágico.
* O @hvd observou que, embora isso funcione imediatamente usando o gcc, parte do comportamento não está definido no padrão C, o que significa que isso pode não ser portátil. Use por sua conta e risco!
Ungolfed:
Compilando e executando com
gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-currying
saídas (após alguns avisos)fonte
g
eh
continuar uma cadeia de invocações de macros funcione, pois não é especificado se o próximog
aparece no contexto da expansão do primeirog
. O C11 adiciona um exemplo ao 6.10.3.4 para indicar que não é especificado. (IIRC, o pré-processador do TenDRA é um que não o expande da maneira que você deseja.) Além disso, nenhuma versão da linguagem suporta argumentos de macro vazios e int implícito, portanto, um programa C válido não pode usar os dois. :) Ainda assim, boa resposta. Você está olhando para o golfe ainda mais?*s
vez destrlen(s)
. As strings C são de comprimento implícito, terminadas por achar
com valor0
. Hack de macro agradável para permitir chamadas com / sem um argumento!Código de máquina 8086, 27 bytes
Este código de máquina deve estar no endereço 0x100 e assume o pequeno modelo de código (cs = ds = es = ss). A localização da função pode ser alterada sem custar bytes extras. Colocá-lo em deslocamento
0
salvaria um byte (emxor si,si
vez demov si, 0x100
)Convenção de chamada necessária
Isso pressupõe que o chamador tenha pré-alocado pelo menos 27 bytes na pilha. Ele recebe um número
ax
e retorna um ponteiro de funçãobx
. Chamar esse ponteiro comax=0
termina a cadeia e retorna a soma embx
.Então, na primeira chamada:
Em seguida, para cada chamada subsequente:
Terminar:
Ungolfed (desmontagem comentada do código da máquina):
Depois de chamar isso com um AX diferente de zero,
bx = sp
o buffer é preenchido com uma cópia modificada do código de máquina defunction
. O imediato de 16 bits na primeira instrução contém o total. (Foi escrito pela última instrução antes daret
.)push di
/pop bx
poderia ser substituído pormov bx, di
(antesrep movsb
), simplificando, mas sem economia.Exigir que o chamador passe um ponteiro para o buffer dst
di
economizaria 4 bytes vs. o cálculo relativo asp
.Tornar o endereço de início da função igual ao tamanho da função salvaria um byte (
mov cx, si
).fonte
objdump -b binary
vez dehexdump -C
di
(4 bytes). Torne a função endereço inicial = tamanho: emmov cx, si
vez demov cx, 0x1b
.C #, 62 bytes
Para finalizar a chamada, passe em um número negativo, por exemplo
fonte
null
ou nenhum parâmetro para finalizar. No entanto, todas as maneiras que eu tentei foram muito mais tempo!m
vez dem<0
e passarnull
ou0
como o último parâmetro?Boolean
pode ser usado como umBoolean
... eu tentei com,null
mas ficou mais tempo. Eu queria usar o??
que significa que se o LHS for nulo, faça o RHS, mas como eu preciso se o LHS não for nulo, faça isso do RHS que eu não poderia.Scala, 58 caracteres
Experimente online
Ungolfed:
Explicação:
Este código define um
case class
chamado f com um construtor assumindo um int. Defina uma classe de caso que gere os métodos equals, hashcode, toString e copy e um objeto complementar com o mesmo nome para ativar a criação de objetos sem anew
palavra - chave.Esta classe possui um método de aplicação sobrecarregado: Um leva outro número inteiro para adicionar e cria um novo objeto com a soma atualizada e um sem argumentos para obter a soma.
No Scala, qualquer objeto com um método apply pode ser chamado como um método, ou seja,
o.apply(x)
pode ser escrito comoo(x)
. Isso é usado na biblioteca padrão para matrizes, listas, mapas eFunction1
características implementadas por funções anônimasfonte
Pitão, 19 bytes
Experimente online!
Estou impressionado que o Javascript vence o Pyth, mas, novamente, o Pyth não foi projetado para passar funções.
fonte
Perl 5, 36 bytes
fonte
-M5.016
? Parece que você deve ser capaz de soltar-M5.016
e também soltarmy
e salvar alguns bytes. Se for apenassay
, você pode usar a bandeira-E
, que não é ativadause strict
, então você ainda pode soltar amy
.__SUB__
), mas eu mudei isso antes de enviar e não removi o bit sobre o 5.16. Eu removo isso. Eu não acho que cairmy
seria correto embora.say
como parte do código, é apenas para fins ilustrativos)my
semuse strict
,$n
é implicitamente uma variável global. É ruim em scripts perl adequados, mas é bastante comum em one-liners, e parece funcionar aqui.Flak cerebral , 6 bytes
Na verdade, acabei de perceber que, como o ToS é um formato de retorno válido, o 0 não é realmente necessário, o que economiza 2 bytes:
Experimente online!
Submissão (s) original (s), 8 bytes
Usa
0
como valor especial:Experimente online!
Explicação
Dados os argumentos a 1 , a 2 ,…, a n , 0 , a pilha inicialmente se parece com isso:
a n
⋮
a 2
a 1
0 0
O código, em seguida, continua, aparece cada um i , acumula-los, aparece a 0 adiciona-los e empurra o resultado:
Soluções alternativas, 8 bytes
Em vez de adicionar o 0 e adicioná-lo à soma, também podemos trocar pilhas, pois a correta está inicialmente vazia:
Experimente online!
Usando a
-r
bandeira, o 0 está no topo da pilha, para podermos exibi-lo primeiro:Experimente online!
Experimente online!
fonte
C (GCC), 83 bytes
Meu primeiro golfe C! Existem algumas outras soluções C, mas essa é um pouco diferente. O uso do pré-processador é puramente cosmético. Essa abordagem foi discutida pela primeira vez na resposta de Conor O'Brien aqui .
O valor do terminal é zero. O valor de retorno é uma união, portanto, para chamar o resultado, usar o campo
f
e acessar o valor final, use o campov
, por exemploExperimente Online
Limitações
Uma variável global mantém o total em execução. Embora isso seja explicitamente proibido, o envio suporta chamadas repetidas (o total é redefinido na chamada de terminal), o que parece ser o motivo da proibição do estado global.
Um ponteiro para
f
é armazenado na união retornada por meio doint
membro, portanto isso claramente não é portátil. Não tenho certeza se isso funciona no GCC em todas as plataformas ou apenas no Linux ou apenas no x86 ou apenas com o ELF ou ... Se alguém souber algum detalhe sobre isso, comente ou envie uma mensagem!fonte
APL (Dyalog Classic) ,
48474644 32 bytesExperimente online!
Termina passando em zero. Sintaxe da chamada:
((0 f 1) 2) 0
-15 bytes graças a @ngn
Requer
⎕IO←0
Quaisquer dicas de golfe são bem-vindas!
fonte
:If x<0
para:If×x
e trocar o "se" e cláusulas "else"r←⍎condition⊃'else' 'then'
Perl 6 , 31 bytes
fonte
Dyvil , 34 bytes
Uso :
O final
()
pode ser omitido.Explicação :
Define um operador de justaposição que leva duas polegadas e as adiciona. O parâmetro
j
tem o valor padrão0
para suportar a chamada sem argumentos. O0
nos exemplos acima não é o nome, mas um literal.fonte
Julia v0.5 +, 52 bytes
Ligar como
F
. Provavelmente isso poderia ser muito mais curto adotando um método menos OO, mas eu sempre gosto de ter a chance de usar esse idioma.Se for possível supor que "pelo menos uma chamada será feita antes da chamada de término", a segunda linha poderá ser removida para salvar 6 bytes.
fonte
Julia 0,5 , 18 bytes
Experimente online!
fonte
R, 40 bytes
0 atua como o valor de parada aqui. Por mais dois bytes, podemos omiti-lo.
O problema é que R não possui um lambda embutido e conciso. Mas se adicionarmos um , podemos obter o código para 26 bytes :
(Sim, isso é R. válido. Ele só precisa de uma importação.)
fonte
PHP, 44 bytes
Uma ideia de @ user63956
Chamada de encerramento
0
Versão Online
Chamada de encerramento com
NULL
necessidade[$i]
de[+$i]
PHP, 47 bytes
Versão Online
PHP, 52 bytes
Chamada de encerramento
NULL
ou qualquer outro valor falso no PHPse o programa precisar terminar após a saída, substitua
print$s
pordie("$s")
+ 2 bytesVersão Online
fonte
$s
. assim que você poderia fazer algo assimreturn$i?f:$s
no finalfunction f($i){return[$_GET[0]+=$i][$i]?:f;}
.PowerShell, 86 bytes
Experimente online!
Código do teste:
Saída: 20
fonte
$n="$args"
invés de$n=$args[0]
.$args[0]
Porém, não funcionará no outro , porque você obterá concatenação de strings em vez de adição.Python 3 , 63 bytes
Experimente online!
Termina com 0
fonte
Python, 69 bytes
fonte
Oitava, 39 bytes
* O argumento da chamada de encerramento é 0.
Experimente online!
*
endfunction
necessário para adicionar outros códigos.fonte
R,
5452 bytesEconomizou 2 bytes graças ao MickyT!
Semelhante a uma das respostas do python. Ungolfed:
Funciona como
fonte
f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
return
.return
em R não é o mesmo que em outros idiomas, ele realiza um aborto prematuro. Não usarreturn
é idiomático. Por outro lado, sua versão não-golfada ainda tem o golfeif
.if
era preguiça, masreturn
é apenas para facilitar a leitura - dá o mesmo resultado com ou semreturn
.return
diminui a legibilidade porque sinaliza a coisa errada (saída prematura) e é um exemplo da programação do culto à carga .C ++ (gcc) ,
9591 bytesExperimente online!
fonte