Caril de comprimento arbitrário


53

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, fdeve retornar a soma de todos os números inteiros passados.

Por exemplo, g=f(4)(se fé a primeira função) deve ser definida gpara outra função. h=g(3)fará o mesmo. No entanto, quando você chama hsem 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

4
@LuisMendo Geralmente, isso significa que 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 ao 4e assim por diante.
Martin Ender

6
@LuisMendo Realmente depende de Eugene, mas acho que permitir chamadas repetidas afastaria significativamente o desafio, porque a parte interessante não é criar uma função com estado, mas criar uma função de ordem superior.
Martin Ender

6
@MartinEnder Isso faz muito sentido. Eugene, se essa for a intenção, altere a redação do desafio. Escrever uma função que pode ser infinitamente chamada não sugere em absoluto que a função deviam retornar uma função
Luis Mendo

4
Podemos assumir que haverá apenas uma instância da cadeia de chamadas por vez? Por exemplo, não q = f(2)(3); b = f(1)(2)(3); q(); b()?
Conor O'Brien

3
Tendo recentemente apanhado Haskell, estou interessado em saber se isso é possível em Haskell. O sistema de tipos fortes me faz pensar que pode não ser.
CAD97

Respostas:


49

JavaScript (ES6), 18 bytes

f=n=>m=>m?f(m+n):n

Passe um valor falso para recuperar a soma. Zeros podem ser permitidos por um custo de 2 bytes.

Experimente online

Ungolfed:

f = function(n) {
    return function(m) {
        if (m) {
            return f(m+n);
        } else {
            return n;
        }
    }
}

Submissão brilhante!
Eugene D. Gubenkov

21

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.

class F a where f::Int->a
instance F(()->Int)where f n()=n
instance F a=>F(Int->a)where f=(f.).(+)

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 que frecebe um número inteiro e retorna um valor do tipo a, para qualquer tipo aque pertença à classe de tipo F. Fé apenas o nome da classe de tipo que fornece a função f; é declarado na primeira linha.

As próximas duas linhas são duas instâncias de Ftipos diferentes a. A segunda linha indica que o tipo de funções de ()para inteiros pertence F(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, se apertencer F, o mesmo ocorre com o tipo de funções de números inteiros para a: de uma função f :: Int -> a, podemos gerar outra função f :: Int -> Int -> a. A implementação é f m n = f (m+n)(o código usa combinadores para torná-lo mais curto), onde o fda esquerda é o novo e o fda direita é o antigo. Isso essencialmente dáfum novo argumento inteiro, que é adicionado ao próximo. Vários argumentos são somados como este:

  f  a1   a2   a3   a4   a5  ()
= f (a1 + a2)  a3   a4   a5  ()
= f (a1 + a2 + a3)  a4   a5  ()
= f (a1 + a2 + a3 + a4)  a5  ()
= f (a1 + a2 + a3 + a4 + a5) ()
=    a1 + a2 + a3 + a4 + a5

O fem cada linha tem um tipo diferente.

As funções Haskell são alteradas automaticamente, portanto, se você fornecer fapenas números inteiros, obterá uma função.


11
Talvez eu esteja falando sério, mas não é exatamente o que o desafio pede. Você está definindo duas (!) Funções, ambas chamadas 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.
N2020 /

3
@nimi Isso define não duas funções chamadas f, mas infinitamente muitas funções chamadas f. (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.
precisa saber é o seguinte

@ ShreevatsaR: Eu vejo duas definições f n()=ne f=(f.).(+), então, eu chamaria de definição de duas funções.
Nimi

7
@nimi Existem duas definições, mas não duas funções. O número de definições não precisa ser o número de funções. Por exemplo, você pode definir a função fatorial com as duas definições g 0 = 1e g 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.)
ShreevatsaR

11
@nimi BTW no ghcicarregamento acima e tente :t f- dirá f :: F a => Int -> a(o que significa que se aé uma instância da classe f, então fé uma função Int -> 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.
precisa saber é o seguinte

15

Python 2, 42 41 36 bytes

Essa solução nunca terá um estouro, pois o Python suporta números inteiros de precisão arbitrária. Zero é o "valor especial".

f=lambda n:lambda m:m and f(m+n)or n

Experimente online

Ungolfed:

def f(n):
    def g(m=''):
        return f(m+n)if m<''else n
    return g

14

C, 62 58 bytes, borderline competindo

Guardado 4 bytes graças a Kevin! (Ainda não removemos o typedef porque é algo necessário para ser chamado.)

typedef(*(*B)(_))(_);q;f(x,o,_){x=x?(q+=x,f):(x=q,q=0,x);}

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 como 0. 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:

  1. Converta o resultado em uma função para informar ao compilador que deseja chamar o resultado novamente;
  2. ou crie um tipo union/ structque tenha um intsubtipo 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 o Btipo 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:

   ( (B)( (B) f(21) )(1) )(0)
//            f(21)            - call f with 21
//        (B)                  - cast to B, a function pointer
//      (           )(1)       - call with 1
//   (B)                       - cast to a function pointer
// (                     )(0)  - call with 0

Se você disser que termina em 0 apenas, precisará da conversão (o que você faz em C porque C não pode definir adequadamente uma função que se retorna) e sai da limpeza do global entre as execuções para o chamador (que Eu acho que é perfeitamente razoável), você pode simplificar a coisa toda para q;f(x){return x?(q+=x,f):q;}.
Kevin


11
@ Kevin ainda, de acordo com as regras do site, uma função deve ser reutilizável. Se eu não fiz de zero qdepois de cada corrida, então a função não seria mais utilizável
Conor O'Brien

Talvez ponteiros de função? Você teria que de referência de cada vez, mas pode valer a pena conferir
Downgoat

11
@ ConorO'Brien Acabei de implementar sua abordagem de união. É mais longo que este, mas não está longe.
Jakob

13

Mathematica, 25 bytes

f[x_]@y_=f[x+y]
f[x_][]=x

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:

f[x_][y_]=f[x+y]
f[x_][]=x

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 contenha f, por exemplo, f[x_]receber outro argumento. Configurando duas definições para isso, podemos obter o comportamento desejado:

  • A primeira definição recolhe uma f[x][y]chamada f[x+y], consumindo uma "chamada" e adicionando os argumentos internos. Esta regra se aplica até que fiquemos f[sum][].
  • A segunda definição descompacta este caso final, definindo a coisa toda para a qual avaliar sum.

11
<Programação simbólica #
Julian Wolf

8

C ++, 72 bytes

#define O(P)operator()(P){return{P+a};}int
struct F{F O(int(m))O()a;}f;

Isso define um tipo Fque atua como a função solicitada e uma variável fdesse tipo a ser invocada. É válido a partir do C ++ 11 e funciona com versões online do GCC, clang, icc e VC ++.

Uso:

int main() {
  return f(1)(2)(3)(); // returns 6
}

Explicação:

Após o pré-processamento e reformatação, ele se parece com:

struct F {
  F operator()(int(m)) { return{int(m)+a}; }
  int operator()() { return {+a}; }
  int a;
} f;

Isso normalmente seria escrito:

struct F {
  F operator()(int m) { return {m+a}; }
  int operator()() { return a; }
  int a;
} f;

return a;e return {+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 me int(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};e return {int(m)+a};faça a mesma coisa, pois o lançamento de mfrom intpara intnão altera seu valor. Essas alterações aproximam as duas operator()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.


11
Bela. E não apenas a solução de golfe ... sobrecarregar operator()para fazer esse trabalho foi especialmente legal.
quer

6

Ruby, 23 bytes

f=->n{->m{m ?f[n+m]:n}}

Uso:

f[1][2][3][nil]
=> 6

6

C, 104 96 bytes

#define a(i)s(i)|b
#define b(i)u(i)|c
#define c(i)u(i)|b
b,c,d;s(i){b=c=i;i=d;}u(i){c=b+=i;i=d;}

Usa o método no link que @JulianWolf compartilhou. O último argumento deve ser 0.

Experimente online!


Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Dennis

4

Math.JS, 38 bytes

f(x)=i(x,0)
i(x,y)=x<0?y:j(z)=i(z,y+x)

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

Látex!

Como mostrado no LaTex acima, f(x)simplesmente chama i(x,0), então, i(x,y)retorna o valor de yse xfor menor que 0, ou a função j(z)=i(z,x+y), que aceita um argumento, que executa um loop. Adicionando ao valor de y.


4

C, 232 206 bytes

#include<string.h>
#include<stdlib.h>
#define f(X)s(""#X)?0:g
#define g(X)u(""#X)?0:h
#define h(X)u(""#X)?0:g
g=0,h=0;s(char*s){g=h=atoi(s);return 0;}u(char*s){char*a=strlen(s)?s:"0";g=h+=atoi(a);return 0;}

Provavelmente, 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:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define f(X) start("" #X) ? 0 : f0
#define f0(X) update("" #X) ? 0 : f1
#define f1(X) update("" #X) ? 0 : f0

long f0 = 0;
long f1 = 0;

int start(const char *s) {
    f0 = f1 = strtol(s, NULL, 10);

    return 0;
}

int update(const char *s) {
    const char *a = strlen(s) ? s : "0";
    f0 = f1 += strtol(a, NULL, 10);

    return 0;
}

int main() {
    printf("f(1)()          -> %ld\n", f(1)());
    printf("f(1)(2)(0)(3)() -> %ld\n", f(1)(2)(0)(3)());
    printf("f(1)(-2)(3)()   -> %ld\n", f(1)(-2)(3)());
    printf("f()             -> %ld\n", f());

    return 0;
}

Compilando e executando com gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-curryingsaídas (após alguns avisos)

f(1)()          -> 1
f(1)(2)(3)(0)() -> 6
f(1)(-2)(3)()   -> 2
f()             -> 0

"sem extensões de idioma" - Não é garantido que o truque de alternar entre ge hcontinuar uma cadeia de invocações de macros funcione, pois não é especificado se o próximo gaparece no contexto da expansão do primeiro g. 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?
Hv

@ DVD: sim, provavelmente vou voltar em alguns dias e ver se consigo jogar golfe. Você definitivamente está certo de que esse é um comportamento não especificado, mas acho que o tratamento padrão aqui é que as linguagens são definidas por sua implementação, desde que funcione com o gcc, fico feliz.
Julian Lobo

Acabei de abordar o comentário que você incluiu na sua resposta de que ele não depende de nenhuma extensão de idioma. Sim, mesmo com extensões de idioma, é perfeitamente válido como resposta aqui, não significava sugerir o contrário.
Hv

Ah, isso é definitivamente justo. Você está certo que eu deveria estipular que, embora nenhuma sinalização extra seja necessária, isso pode não ser portátil.
Julian Lobo

Você pode testar a cadeia vazia com em *svez de strlen(s). As strings C são de comprimento implícito, terminadas por a charcom valor 0. Hack de macro agradável para permitir chamadas com / sem um argumento!
Peter Cordes

4

Código de máquina 8086, 27 bytes

00000000  bb 00 00 85 c0 74 13 01  d8 be 00 01 89 e7 47 47  |.....t........GG|
00000010  57 b9 1b 00 f3 a4 5b 89  47 01 c3                 |W.....[.G..|
0000001b

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 0salvaria um byte (em xor si,sivez de mov 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 axe retorna um ponteiro de função bx. Chamar esse ponteiro com ax=0termina a cadeia e retorna a soma em bx.
Então, na primeira chamada:

mov bp, sp
sub sp, 28
mov ax, number_to_add
call function
; new function pointer in bx

Em seguida, para cada chamada subsequente:

sub sp, 28
mov ax, number_to_add
call bx
; new function pointer in bx

Terminar:

mov ax, 0
call bx
; result in bx
mov sp, bp

Ungolfed (desmontagem comentada do código da máquina):

00000000  BB0000            mov bx,0x0      ; 0 is replaced after copying
00000003  85C0              test ax,ax
00000005  7413              jz 0x1a         ; if(ax==0) ret (with value in bx)
00000007  01D8              add ax,bx       ; arg += total
00000009  BE0001            mov si,0x100    ; address of the original: ds:0x100
0000000C  89E7              mov di,sp
0000000E  47                inc di
0000000F  47                inc di          ; dst = sp+2 = above return address
00000010  57                push di
00000011  B91B00            mov cx,0x1b
00000014  F3A4              rep movsb         ; copy the function code.
00000016  5B                pop bx            ; bx = start of copy destination
00000017  894701            mov [bx+0x1],ax   ; update total in the copied code
0000001A  C3                ret               ; with bx = function pointer

Depois de chamar isso com um AX diferente de zero, bx = spo buffer é preenchido com uma cópia modificada do código de máquina de function. O imediato de 16 bits na primeira instrução contém o total. (Foi escrito pela última instrução antes da ret.)

push di/ pop bxpoderia ser substituído por mov bx, di(antes rep movsb), simplificando, mas sem economia.

Exigir que o chamador passe um ponteiro para o buffer dst dieconomizaria 4 bytes vs. o cálculo relativo a sp.

Tornar o endereço de início da função igual ao tamanho da função salvaria um byte ( mov cx, si).


Essa seria uma resposta melhor se você incluísse a desmontagem dos bytes do código da máquina. As respostas de código de máquina definitivamente precisam de uma versão não-bloqueada. por exemplo, use em objdump -b binaryvez dehexdump -C
Peter Cordes

Atualizado com desmontagem comentada. Possíveis economias: exija que o chamador passe um ponteiro dst di(4 bytes). Torne a função endereço inicial = tamanho: em mov cx, sivez de mov cx, 0x1b.
Peter Cordes

2

C #, 62 bytes

dynamic f(int n)=>(System.Func<int,dynamic>)(m=>m<0?n:f(n+m));

Para finalizar a chamada, passe em um número negativo, por exemplo

f(1)(2)(3)(-1) == 6

Eu gostaria de fazê-lo funcionar, passando nullou nenhum parâmetro para finalizar. No entanto, todas as maneiras que eu tentei foram muito mais tempo
TheLethalCoder

Você pode usar em !mvez de m<0e passar nullou 0como o último parâmetro?
betseg

@ betseg Não em c # apenas um Booleanpode ser usado como um Boolean... eu tentei com, nullmas 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.
TheLethalCoder

2

Scala, 58 caracteres

case class f(n:Int){def apply(m:Int)=f(n+m)
def apply()=n}

Experimente online

Ungolfed:

case class f(n:Int){
  def apply(m:Int)=f(n+m)
  def apply()=n
}

Explicação:

Este código define um case classchamado 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 a newpalavra - 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 como o(x). Isso é usado na biblioteca padrão para matrizes, listas, mapas e Function1características implementadas por funções anônimas


2

Pitão, 19 bytes

DhdDebR?bh+dbdR$end

Experimente online!

Estou impressionado que o Javascript vence o Pyth, mas, novamente, o Pyth não foi projetado para passar funções.


2

Perl 5, 36 bytes

sub f{my$n=pop;sub{@_?f($n+pop):$n}}

say f(1)->(); # 1
say f(1)->(2)->(3)->(); # 6

O que isso requer -M5.016? Parece que você deve ser capaz de soltar -M5.016e também soltar mye salvar alguns bytes. Se for apenas say, você pode usar a bandeira -E, que não é ativada use strict, então você ainda pode soltar a my.
Chris

@ Chris, você está certo, ele não precisa do 5.16, minha revisão inicial foi (usando __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 cair myseria correto embora.
Hbbs

(e não, eu não estou contando saycomo parte do código, é apenas para fins ilustrativos)
Hobbs

11
Se você remover mysem use strict, $né implicitamente uma variável global. É ruim em scripts perl adequados, mas é bastante comum em one-liners, e parece funcionar aqui.
Chris

2

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 0como 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:

(      )  -- push the following value:
 {  }     --   while ToS ≠ 0 (sums the runs):
  {}      --     pop 1 element
     {}   --   pop the remaining 0 & add it

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 -rbandeira, o 0 está no topo da pilha, para podermos exibi-lo primeiro:

({}{{}})

Experimente online!

{}({{}})

Experimente online!


Oh meu Deus ... Ótimo!
Eugene D. Gubenkov

2

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 .

#define r union r
t=0;r{int v;r(*f)();};r e;r f(a){t+=a;e.v=a?f:t;t*=a>0;return e;}

O valor do terminal é zero. O valor de retorno é uma união, portanto, para chamar o resultado, usar o campo fe acessar o valor final, use o campo v, por exemplo

f(1).f(2).f(3).f(0).v

Experimente 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 do intmembro, 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!


2

APL (Dyalog Classic) , 48 47 46 44 32 bytes

r←(a f)x
r←⍎'(a+x)f'↓⍨-0=x

0f

Experimente 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!


se você pode usar 0 como valor terminator, a mudança :If x<0para :If×xe trocar o "se" e cláusulas "else"
NGN

Derp. Eu não vi que dizia "não positivo"
Zacharý 25/05

você conhece esse truque? r←⍎condition⊃'else' 'then'
NGN


Pensei que disse 22 ...> _ <
Zacharý 25/05


1

Dyvil , 34 bytes

infix int apply(i:int,j:int=0)=i+j

Uso :

0() // = 0
0(1)() // = 1
0(1)(2)() // = 3

O final ()pode ser omitido.

Explicação :

Define um operador de justaposição que leva duas polegadas e as adiciona. O parâmetro jtem o valor padrão 0para suportar a chamada sem argumentos. O 0nos exemplos acima não é o nome, mas um literal.


1

Julia v0.5 +, 52 bytes

type F n end
F()=0
(f::F)()=f.n
(f::F)(x)=(f.n+=x;f)

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.



1

R, 40 bytes

f=function(x)function(y)`if`(y,f(x+y),x)

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 :

f=x->(y->`if`(y,f(x+y),x))

(Sim, isso é R. válido. Ele só precisa de uma importação.)


1

PHP, 44 bytes

Uma ideia de @ user63956

Chamada de encerramento 0

function f($i){return[$_GET[0]+=$i][$i]?:f;}

Versão Online

Chamada de encerramento com NULLnecessidade [$i]de[+$i]

PHP, 47 bytes

function f($i){global$s;return$i?f.!$s+=$i:$s;}

Versão Online

PHP, 52 bytes

Chamada de encerramento NULLou qualquer outro valor falso no PHP

function f($i){global$s;$i?$s+=$i:print$s;return f;}

se o programa precisar terminar após a saída, substitua print$spor die("$s")+ 2 bytes

Versão Online


11
Eu acho que a função deve retornar (não imprimir) $s. assim que você poderia fazer algo assim return$i?f:$sno final
Conor O'Brien

@ ConorO'Brien eu não tenho certeza, mas se o seu pensamento é certo que poderia poupar 5 Bytes Obrigado
Jörg Hülsermann

11
Alguns bytes podem ser salvas com variáveis superglobais: function f($i){return[$_GET[0]+=$i][$i]?:f;}.
user63956

@ user63956 uma idéia muito agradável
Jörg Hülsermann

1

PowerShell, 86 bytes

$f={$n=$args[0];$f=(gv f).value;{if($args){&$f($args[0]+$n)}else{$n}}.getnewclosure()}

Experimente online!

Código do teste:

&(&(&(&(&(&$f 4)2)7)5)2)

Saída: 20


Muito agradável. Bem-vindo ao PPCG! Você pode salvar um byte ao $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.
AdmBorkBork


1

Python, 69 bytes

def f(a=0,s=[]):
    if a:
        return lambda b=0:f(b,s+[a])
    return sum(s)

11
Estou assumindo que isso é python? Você deve indicar o idioma usado na sua resposta.
precisa saber é o seguinte

Você pode tentar jogar sua resposta mais? Tal como está, não é muito bem jogado.
Rɪᴋᴇʀ

1

Oitava, 39 bytes

function r=f(n)r=@(m)merge(m,f(m+n),n);

* O argumento da chamada de encerramento é 0.

Experimente online!

* endfunctionnecessário para adicionar outros códigos.


1

R, 54 52 bytes

f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}

Economizou 2 bytes graças ao MickyT!

Semelhante a uma das respostas do python. Ungolfed:

f=function(x){
  g=function(y=''){
    if(y>''){
      f(y+x)
      }
      else{x}
  }
  g
}

Funciona como

> f(1)(2)(4)()
[1] 7

11
Bom trabalho. Você pode se livrar das chaves internas em torno da cláusula if. f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
MickyT

Estou um pouco confuso por que a sua versão "ungolfed" tem return. returnem R não é o mesmo que em outros idiomas, ele realiza um aborto prematuro. Não usar returné idiomático. Por outro lado, sua versão não-golfada ainda tem o golfe if.
Konrad Rudolph

@KonradRudolph O golfe ifera preguiça, mas returné apenas para facilitar a leitura - dá o mesmo resultado com ou sem return.
BLT

@BLT Hm. Sinto fortemente que a gratuidade em R return diminui a legibilidade porque sinaliza a coisa errada (saída prematura) e é um exemplo da programação do culto à carga .
Konrad Rudolph

Legal, eu aprendi algo novo novamente. Essa é uma razão pela qual eu continuo voltando. Obrigado @KonradRudolph, também esta questão do Stack Overflow é interessante: stackoverflow.com/questions/11738823/…
BLT

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.