İsteğe bağlı boyda kurutma


53

Bir fonksiyonu, yaz fpozitif tamsayı alır ve bir işlev döndürür.

Döndürülen yeni işlev aynı olmalıdır f. Ancak, "sonlandırma çağrısı" gerçekleştiğinde, fbunun yerine geçen tüm tam sayıların toplamını döndürmelidir.

Örneğin, g=f(4)( filk işlev ise) gbaşka bir işleve ayarlanmalıdır . h=g(3)aynısını yapacağım. Bununla birlikte, hhiçbir argüman olmadan aradığınızda (ayrıntılar için aşağıya bakınız), önceki 7 fonksiyon argümanının toplamı olduğu gibi 7 değerini çıkarmalıdır. Başka bir yolla f(3)(4)() == 7.

Bunun aynı olmadığını unutmayın f(3,4)().

"Sonlandırma çağrısı" aşağıdaki seçeneklerden biridir (seçiminiz):

  • w / o argümanını çağır
  • argüman olarak null
  • pozitif olmayan herhangi bir değer

İsteğe bağlı işlev çağrısı miktarı desteklenmelidir, önceden tanımlanmış bir sınır yoktur.

Toplam tutarın 1'000'den büyük olmayacağı garanti edilmektedir.

"Fesih çağrısı" öncesinde en az bir çağrı yapıldığını varsayabiliriz.

Kodunuz statik, program başına değişken kullanmamalı, bu nedenle deneyi aynı çalışma zamanında birden çok kez çalıştırmak ve tamamen aynı davranışı gözlemlemek mümkün olmalıdır.

Örnekler:

f(1)() == 1
f(4)(2)(7)() == 13
f(4)(2)(7)(5)(2)() == 20

4
@LuisMendo Genellikle f(4)yeni bir işlev döndürür. Eğer bu yeni fonksiyon argümanlar olmadan çağrılırsa, döndürür 4, fakat eğer başka bir argüman ile çağrılırsa , aynı semantikte fakat yeni argümanlara eklenmiş vb. İle tekrar yeni bir fonksiyon döndürür 4.
Martin Ender

6
@LuisMendo Bu gerçekten Eugene'ye bağlı, ancak tekrarlanan çağrılara izin vermenin zorluğun üstesinden geleceğini düşünüyorum, çünkü ilginç kısım durumsal bir işlev yapmak değil, daha üst düzey bir işlev yapmaktır.
Martin Ender

6
@MartinEnder Bu çok mantıklı. Eugene, niyet buysa, lütfen meydan okumanın ifadesini değiştir. Sonsuz olarak çağrılabilen bir fonksiyon yazmak, fonksiyonun bir fonksiyon döndürmesi olduğunu hiç göstermez
Luis Mendo

4
Bir seferde çağrı zincirinin sadece bir örneği olacağını varsayabilir miyiz? Örneğin hayır q = f(2)(3); b = f(1)(2)(3); q(); b()?
Conor O'Brien,

3
Yakın zamanda Haskell'i aldığımda, bunun Haskell'de mümkün olup olmadığıyla ilgileniyorum. Güçlü tip sistem, olmayabileceğini düşündürüyor.
CAD97

Yanıtlar:


49

JavaScript (ES6), 18 bayt

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

Toplamı almak için sahte bir değer iletin. Sıfırlara 2 baytlık bir ücret karşılığında izin verilebilir.

Çevrimiçi deneyin

Ungolfed:

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

Mükemmel sunum!
Eugene D. Gubenkov

21

Haskell (GHC), 118 bayt

Bu, kod için 98 bayt ve GHC derleyici bayrağına göre 20 bayttır -XFlexibleInstances, bu da bir tür sistem uzantısı sağlar.

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

Bu f, birim tarafından takip edilen ve ()ardından bir tamsayı döndüren, isteğe bağlı sayıda tam sayı ile çağrılabilen bir "işlev" tanımlar . Tip açıklamaları gereklidir. Çevrimiçi deneyin!

açıklama

Haskell'in katı tip sistemini buna izin vermeye zorlamak, biraz da sihir gerektirir; yani, esnek tip sınıfı örnekler için GHC uzantısını mümkün kılar. Bunun nasıl çalıştığı, fbir tip sınıfı kısıtlamasıyla sınırlanan parametrik olarak polimorfik bir fonksiyondur: türü F a => Int -> a. Bu f, bir tamsayı alır ve yazım sınıfına ait aherhangi bir ayazım için bir tür değeri döndürür F. Fişlev sağlayan sadece sınıfın adıdır f; ilk satırda ilan edildi.

Sonraki iki satır Ffarklı türler için iki örnektir a. İkinci satır, fonksiyonların ()tamsayılara kadar olan fonksiyon tipinin ( tek üyesi değer olan birim tipinin Fnerede ()olduğunu ()) ve uygulamanın f n () = n; fonksiyon ilk argümanını döndürür. Son satır, eğer aaitse F, tamsayıdan fonksiyonlara, yani abir fonksiyondan f :: Int -> abaşka bir fonksiyon üretebileceğimizi belirtir f :: Int -> Int -> a. Uygulama f m n = f (m+n)(kod kısaltmak için birleştiricileri kullanır), fsolda yenisi ve fsağda eskisidir. Bu aslında verirfBir sonrakine eklenen yeni bir tamsayı argümanı. Birden fazla argüman bu şekilde toplanır:

  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

fHer bir hat üzerinde farklı bir türü vardır.

Haskell işlevleri otomatik olarak körlenir, bu nedenle fyalnızca tam sayı verirseniz , bir işlev görürsünüz.


1
Belki nitpicking, ama sorun istediği tam olarak değil. Her ikisi de denen iki (!) İşlevi tanımlıyorsunuz f, işi yapan tek bir işlev değil. Ancak, bu Haskell'de bulabileceğiniz kadar yakın. Sıkı tip sistem nedeniyle görevi tek bir işlevle çözmenin mümkün olduğunu sanmıyorum.
nimi

3
@ nimi Bu, çağrılan iki işlevi değil f, çağrılan sonsuz sayıda işlevi tanımlar f. (Her olası argüman sayısı için bir tane.) Bu işlevler (bu sonsuz aileden), bir argüman sayısı sıfır olduğunda diğeri argüman olmadığında, iki tür tanım vardır.
ShreevatsaR

@ ShreevatsaR: İki tanım görüyorum f n()=nve f=(f.).(+)bu yüzden iki fonksiyonu tanımlamak derim.
nimi

7
@ nimi İki tanım var, fakat iki fonksiyon yok. Tanımların sayısının fonksiyonların sayısı olması gerekmez. Örneğin, iki tanımlarla faktöryel fonksiyonunu tanımlayabilir g 0 = 1ve g n = g (n-1) * niki tanım ama sadece bir fonksiyon vardır. Burada iki tanımımız var ama sonsuz sayıda fonksiyon. (Farklı türden her biri.)
ShreevatsaR

1
@nimi btw ghciyukardaki yük ve deneyin :t f- söyleyecektir f :: F a => Int -> a(yani a, bir sınıf örneği ise f, o fzaman bir işlevdir Int -> a). Böylece, bunu bir işlev olarak ya da sonsuz sayıda olarak değerlendirebiliriz, ancak iki tür tanımı olmasına rağmen (tıpkı işlevsellik işlevi gibi) iki işlev olduğunu düşünmek için iyi bir temel göremiyorum.
ShreevatsaR

15

Python 2, 42 41 36 bayt

Python isteğe bağlı hassas tam sayıları desteklediğinden, bu çözüm hiçbir zaman taşma olmayacaktır. Sıfır "özel değer" dir.

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

Çevrimiçi deneyin

Ungolfed:

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

14

C, 62 58 bayt, sınırda rekabet ediyor

Kevin sayesinde 4 byte kurtarıldı! (Hala typedef'i kaldırmamak, çünkü çağrılmak için gereken bir şeydir.)

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

Çağrılacak işlev f; aramayı bırakıp sonucu, pozitif olmayan bir numara ile arayarak sonucu elde edersiniz 0. Çevrimiçi bir test cihazı deneyin!

Bu yüzden, söyleyebileceğim kadarıyla, çoklu dönüş türlerine sahip "köri" işlevlerinin tek yolu aşağıdakilerden birini yapmaktır:

  1. Sonucu, derleyiciye sonucu tekrar aramak istediğinizi söyleyen bir işleve verin;
  2. veya bir ve / ve işlevi / kendine başvuru alt türlerine sahip bir union/ structtürü oluşturun int.

Yapmayı denedim (2), ancak sorunun ruhuna karşı biraz görünüyordu ve açıkçası, hemen hemen geri alınamaz. Bu yüzden, mücadelenin ruhuna uygun olarak, seçenek (1) 'i seçtim. Bu, döndürülen her işlevin kullanılabileceği bir işleve dökülmesini gerektirir.

Bu "currying" sözdizimi biraz tuhaf görünüyor, ancak oldukça benzer. Taklit etmek için f(21)(1)bir tane yazmak zorunda kalacak ((B)((B)f(21))(1))(0). BBir tamsayı alan ve bir işaretçiyi tamsayı alan bir işleve döndüren bir işlev olarak tanımladım . Genişletilmiş, bu gibi görünüyor:

   ( (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

Yalnızca 0'da sona erdiğini söylerseniz, döküm yapmayı isteyeceksiniz (C'de yaptığınız için (C, kendisini döndüren bir işlevi doğru şekilde tanımlayamaz) ve arayana giden genel koşuyu temizleyerek bırakacaksınız. Bence çok mantıklı, her şeyi basitleştirebilirsiniz q;f(x){return x?(q+=x,f):q;}.
Kevin,


1
@Kevin henüz, site kurallarına göre, bir fonksiyonun tekrar kullanılabilir olması gerekir. qHer çalıştırmadan sonra sıfır olmasaydım, işlev artık kullanılamayacaktı
Conor O'Brien,

Belki işaretçiler? Her zaman referanstan
vazgeçmek zorunda kalacaksınız,

1
@ ConorO'Brien Sendika yaklaşımınızı yeni uyguladım . Bundan daha uzun, ama uzak değil.
Jakob

13

Mathematica, 25 bayt

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

Çevrimiçi deneyin! (Matematik kullanarak.)

JavaScript cevabını taşıyarak üç bayttan daha az işlem yapmak mümkündür, ancak daha deyimsel bir Mathematica çözümü sunmak istedim. @ sadece bir miktar sözdizimsel şekerdir, bu da çözeltiyi şuna eşdeğer yapar:

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

Öyleyse evet, Mathematica'da sadece bir fonksiyon tanımlayamazsınız, f[x_]fakat içeren daha karmaşık bir ifadeye doğrudan bir değer ekleyebilirsiniz.f örneğin f[x_]başka argüman geçirilen. Bunun için iki tanım oluşturarak, istenen davranışı elde edebiliriz:

  • İlk tanım bir çöktü f[x][y] çağrıyıf[x+y] , böylece bir "çağrıyı" tüketir ve içindeki argümanları toplar. Bu kural, biz ayrılana kadar geçerlidir f[sum][].
  • İkinci tanım, değerlendirilecek olan her şeyi tanımlayarak bu son durumu ortaya çıkarır sum.

1
<3 sembolik programlama
Julian Wolf

8

C ++, 72 bayt

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

Bu F, istenen işlev olarak işlev gören bir ftürü ve çağırmak için bu türün bir değişkenini tanımlar . C ++ 11 tarihinden itibaren geçerlidir ve çevrimiçi GCC, clang, icc ve VC ++ sürümleriyle çalışır.

Kullanımı:

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

Açıklama:

Ön işleme ve yeniden biçimlendirmeden sonra şöyle görünür:

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

Bu normalde yazılır:

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

return a;ve return {+a};aynı şeyi yapın, çünkü unary +değeri değiştirmez ve dönüş değerinin etrafındaki fazlalık parantezlere izin verilir. int mve int(m)aynı şeyi yapın, çünkü işlev parametreleri de dahil olmak üzere değişken bir adın etrafındaki fazla parantezlere izin verilir. return {m+a};ve return {int(m)+a};bir döküm olarak, aynı şeyi yapmak mden intüzere intdeğerini değiştirmez. Bu değişiklikler, iki operator()aşırı yüklenmeyi sözdizimde yakınlaştırır ve tek bir makro tanımının iki kez çağrılmasını sağlar. Üç üye için doğru sırayı seçmek, bir sonraki satırın ( int) ilk kelimesinin makro tanımına dahil edilmesini sağlar.


1
Güzel. Ve sadece golf oyunu değil ... operator()bu işi yapmak için aşırı yükleme yapmak özellikle güzeldi.
Ray Toal

6

Ruby, 23 bayt

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

Kullanımı:

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

6

C, 104 96 bayt

#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;}

@JulianWolf tarafından paylaşılan bağlantıdaki yöntemi kullanır. Son tartışma 0 olmalı.

Çevrimiçi deneyin!


Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
Dennis,

4

Math.JS, 38 Bayt

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

İle ara f(number_a)(number_b)(...)(negative_number)

İlk çağrıyı belirtmemize izin verilirse, 12 bayt ( f(x)=i(x,0)\n) bırakılabilir ve ile çağrılabilir.i(number_one,0)(number_two)(...)(negative_number)

Dene!

explination

Lateks!

Yukarıdaki LaTex'te gösterildiği gibi, f(x)basitçe çağırır i(x,0), daha sonra eğer 0'dan küçük ise veya döngüleri i(x,y)döndüren bir argüman alan fonksiyonun değerini döndürür . Değerine eklenir .yxj(z)=i(z,x+y)y


4

C, 232 206 bayt

#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;}

Bu muhtemelen ciddi bir şekilde golf oynayabilir, ancak herhangi bir dil uzantısı olmadan * C'nin kullanılabileceği kavramının bir kanıtı olarak hizmet etmelidir, sihirli bir değerden ziyade argümanlar olmadan çağırarak bu sorunu çözmek için.

* @hvd, gcc kullanarak kutudan çıkarken, davranışların bir kısmının C standardında tanımlanmadığını, yani bunun taşınabilir olamayacağını belirtmiştir. Kendi sorumluluğunuzdadır kullanın!

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;
}

gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-curryingÇıktılarla derleme ve çalıştırma (bazı uyarılardan sonra)

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

"herhangi bir dil uzatması olmadan" - Bir makro çağırma zinciri arasında geçiş yapmanın gve hdevam etmenin hilesi, bir diğerinin gilkinin genişletilmesi bağlamında görünüp görünmeyeceği belirtilmediğinden, çalışma garantisi yoktur g. C11, belirtilmemiş olduğunu açıklamak için 6.10.3.4'e bir örnek ekler. (IIRC, TenDRA'nın ön işlemcisi, istediğiniz şekilde genişletmeyecek olanıdır.) Bunun dışında, dilin hiçbir sürümü hem boş makro bağımsız değişkenlerini hem de örtük int'yi desteklemez, bu nedenle geçerli bir C programı her ikisini de kullanamaz. :) Yine de güzel cevaplar. Daha fazla golf oynamak için mi arıyorsunuz?
HVD

@hvd: evet, muhtemelen birkaç gün içinde ona geri dönecek ve golf oynayabilir miyim bir bakalım. Bunun belirtilmemiş bir davranış olduğu konusunda kesinlikle haklısınız, ancak bence buradaki standart muamele, diller kendi uygulamaları tarafından tanımlanıyor, gcc ile çalıştığı sürece mutluyum.
Julian Wolf

Sadece cevabınıza eklediğiniz yorumu herhangi bir dil uzantısına dayanmadığını söylüyordum. Evet, dil uzantılarında bile, burası bir cevap olarak kesinlikle geçerli, aksi belirtmek istemedi.
HVD

Ah, bu kesinlikle adil. Ekstra bayraklar gerekmese de, bunun taşınabilir olamayacağını şart koşmam gerektiğini söylüyorsun.
Julian Wolf

Boş dize *syerine test edebilirsiniz strlen(s). C dizeleri, bir chardeğerle sonlandırılan örtük uzunluktur 0. Güzel makro kesmek / bağımsız bir aramaya izin vermek için kesmek!
Peter Cordes

4

8086 makine kodu, 27 bayt

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

Bu makine kodu 0x100 adresinde olmalı ve küçük kod modelini varsaymalıdır (cs = ds = es = ss). Yine de, fonksiyon yeri ekstra baytlara gerek olmadan değiştirilebilir. Ofset'e koymak 0bir bayttan tasarruf eder ( xor si,siyerinemov si, 0x100 )

Gerekli arama sözleşmesi

Bu, arayanın yığında en az 27 bayt önceden tahsis ettiğini varsayar. Bir sayı alır axve bir işlev göstergesini içeri döndürür bx. Bu işaretçiyi ile çağırmak ax=0zinciri sonlandırır ve toplamı döndürür bx.
Yani ilk arama için:

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

Ardından, her bir sonraki arama için:

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

Sonlandırmak için:

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

Ungolfed (makine kodunun sökülmesi hakkında yorum yapıldı):

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

Bunu sıfır olmayan AX ile çağırdıktan sonra bx = spve tampon, makine kodunun değiştirilmiş bir kopyası ile doldurulur function. İlk komuttaki 16 bit aniden toplamı tutar. (Öncesindeki son talimat tarafından yazılmıştır ret.)

push di/ (daha önce ) pop bxile değiştirilebilir , daha basit hale getirir ancak tasarruf yapmaz.mov bx, direp movsb

Arayanın bir göstericiyi dst arabelleğine geçirmesi di buna göre hesaplamak yerine 4 byte tasarruf sağlayacaktır sp.

İşlevin başlangıç ​​adresini işlev büyüklüğü ile aynı yapmak bir bayt ( mov cx, si) kazandıracaktır.


Makine kodu baytlarının sökülmesini dahil ettiyseniz, bu daha iyi bir cevap olacaktır. Makine kodu cevapları kesinlikle eski sürümlere ihtiyaç duyar. örneğin, objdump -b binarybunun yerine kullanmahexdump -C
Peter Cordes,

Yorumlanan sökme işlemiyle güncellendi. Olası tasarruf: Arayanın ilk işaretçiyi di(4 bayt) geçmesini gerektirir . Fonksiyonu start address = size: mov cx, siyerine yapın mov cx, 0x1b.
Peter Cordes

2

C #, 62 bayt

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

Aramayı bitirmek için negatif bir numara

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

nullSona erecek parametrelere girerek veya hiç geçmeden çalışmasını istiyorum . Ancak, denediğim tüm yollar çok daha uzundu
TheLethalCoder

Son parametre olarak kullanmak !myerine m<0geçmek nullveya geçmek 0mi?
17'de

@ betseg Hayır C # sadece bir a Booleanolarak kullanılabilir Boolean... denedim nullama daha uzun sürdü . Ben kullanmak istedi ??LHS ÜSÖ do null ise, yani ancak LHS boş değilse ihtiyacım olarak bu başka yapamadım ÜSÖ do.
TheLethalCoder

2

Scala, 58 karakter

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

Çevrimiçi deneyin

Ungolfed:

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

Açıklama:

Bu kod case classint denilen bir kurucu ile denilen f'yi tanımlar . Nesne newanahtar kelimesi olmadan nesne oluşturmayı etkinleştirmek için eşittir, hashcode, toString ve copy yöntemlerini ve aynı ada sahip bir eşlik eden nesneyi oluşturacak bir case sınıfı tanımlayın .

Bu sınıfın aşırı yüklenmiş bir uygulama yöntemi var: Biri, güncellenmiş toplam ile yeni bir nesne eklemek ve oluşturmak için başka bir tamsayı alır ve biri toplamı alacak argümanlar olmadan.

Scala'da, uygulama yöntemi olan herhangi bir nesne, bir yöntem gibi çağrılabilir, yani o.apply(x)olarak yazılabilir o(x). Bu standart kütüphanede diziler, listeler, haritalar ve Function1adsız işlevlerin uyguladığı özellik için kullanılır.


2

Pyth, 19 bayt

DhdDebR?bh+dbdR$end

Çevrimiçi deneyin!

Javascript’in Pyth’i yendiğinden etkilendim ama yine de Pyth işlevlerin geçmesi için tasarlanmadı.


2

Perl 5, 36 bayt

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

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

Bu ne gerektirir -M5.016? Düşüyor -M5.016ve sonra mybir kaç baytı bırakıp kurtarabilmeniz gerekiyor gibi görünüyor . Sadece ise say, -Ebunun yerine bayrak kullanabilirsiniz , bu da etkinleştirilmez use strict, bu yüzden hala bırakabilirsiniz my.
Chris

@Chris haklısın, 5.16'ya ihtiyacım yok, ilk revizyonum (kullanıyor __SUB__) yaptı ama göndermeden önce bunu değiştirdim ve 5.16 ile ilgili biti kaldırmadım. Onu kaldıracağım. Düşüş myolsa da doğru olacağını sanmıyorum .
Ocaklar

(ve hayır, saykodun bir parçası olarak saymıyorum , sadece açıklama amaçlıdır)
Ocaklar

1
Eğer kaldırırsanız myolmadan use strict, $nörtülü küresel değişkendir. Uygun perl betiklerinde kötü bir formdur, ancak tek gömleklerde oldukça yaygındır ve burada işe yarıyor.
Chris

2

Beyin Flak , 6 bayt

Aslında ben sadece beri fark ToS geçerli bir dönüş biçimidir haşhaş 0 gerçekten 2 bayt kaydeder hangi gerekli değildir:

({{}})

Çevrimiçi deneyin!

Orijinal gönderim, 8 bayt

0Özel değer olarak kullanır :

({{}}{})

Çevrimiçi deneyin!

açıklama

Argüman belirtilmemişse bir 1'e , bir 2 , ..., bir n , 0 yığını başlangıçta şöyle görünür:

                                                       bir n

                                                       

                                                       bir 2

                                                       bir 1

                                                       0

Her açılan kod sonra gider bir i , onları biriktirir, çıkar 0 ekler ve sonucu iter:

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

Alternatif çözümler, 8 bayt

0'ı açmak ve toplamı eklemek yerine , doğru olanı başlangıçta boş olduğu için yığınları da değiştirebiliriz:

({{}}<>)

Çevrimiçi deneyin!

-rBayrak kullanarak 0 yığının tepesindedir, bu yüzden önce onu açabiliriz:

({}{{}})

Çevrimiçi deneyin!

{}({{}})

Çevrimiçi deneyin!


Aman Tanrım ... Harika olan!
Eugene D. Gubenkov

2

C (GCC), 83 bayt

İlk C Golf'üm! Birkaç C çözümü daha var, ama bu biraz farklı. Önişlemci kullanımı tamamen kozmetiktir. Bu yaklaşım ilk Conor O'Brien'ın yanıtında tartışıldı burada .

#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;}

Terminal değeri sıfır. Dönen değer bir birleşimdir, bu nedenle sonucu çağırmak, alan kullanmak fve son değere erişmek için alan kullanın v;

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

Çevrimiçi Deneyin

Sınırlamalar

Genel değişken değişken toplamı tutar. Bu açıkça reddedilmiş olsa da, gönderim tekrarlanan çağrıları (terminal çağrısında toplam sıfırlandı) destekliyor, bu da küresel durum yasağının sebebi gibi görünüyor.

Bir işaretçi üye tarafından fgeri gönderilen birliğe depolanır int, bu nedenle bu açıkça taşınabilir değildir. Bunun GCC'de tüm platformlarda mı yoksa sadece Linux'ta mı yoksa sadece x86'da mı yoksa sadece ELF'de mi çalıştığından emin değilim. Eğer birileri bunun hakkında bir şey biliyorsa, lütfen yorum yazın veya bir mesaj gönderin!


2

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

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

0f

Çevrimiçi deneyin!

Sıfır geçerek sonlandırır. Çağrı sözdizimi:((0 f 1) 2) 0

@Ngn sayesinde -15 bayt

gerektirir ⎕IO←0

Herhangi bir golf ipucu bekliyoruz!


Eğer sonlandırıcı değeri olarak 0 kullanıp kullanamayacağı, değiştirmek :If x<0için :If×xve "eğer" ve "Diğer" maddelerini takas
ngn

Derp. "Olumlu değil"
dediğini görmedim

Bu numarayı biliyor musun? r←⍎condition⊃'else' 'then'
ngn


Düşündüm ki 22 ...> _ <
Zacharý


1

Dyvil , 34 bayt

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

Kullanım :

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

Sonda ()atlanabilir.

Açıklama :

İki giriş alan bir bitişik işleç tanımlar ve bunları ekler. Parametre j, 0aramayı bağımsız değişkenler olmadan desteklemek için varsayılan değere sahiptir . 0Örneklerde yukarıda adı ancak bir hazır değil.


1

Julia v0.5 +, 52 bayt

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

Ara F . Bu muhtemelen daha az bir OO yöntemi benimseyerek daha da kısaltılabilir, ancak her zaman bu deyimi kullanma şansı elde etmekten hoşlanırım.

"Sonlandırma çağrısından önce en az bir arama yapılacağı" varsayılabilirse, ikinci satır 6 bayt tasarruf etmek için kaldırılabilir.



1

R, 40 bayt

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

0 burada durma değeri olarak işlev görür. İki bayt için atlayabiliriz.

Sorun, R'nin özlü bir yerleşik lambdadan yoksun olmasıdır. Ancak bir tane eklersek , kodu 26 bayta bulabiliriz :

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

(Evet, bu geçerli R. Sadece bir içe aktarmaya ihtiyacı var.)


1

PHP, 44 Bayt

@ User63956'dan Bir Fikir

Fesih çağrısı 0

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

Çevrimiçi sürüm

İle Fesih çağrı NULLAlçıya ihtiyaç [$i]için[+$i]

PHP, 47 Bayt

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

Çevrimiçi sürüm

PHP, 52 Bayt

Sonlandırma çağrısı NULLveya PHP’de yanlış olan herhangi bir değer

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

Çıkışın + 2 Bayt print$sile değiştirilmesinden sonra programın sonlandırılması gerekiyorsadie("$s")

Çevrimiçi sürüm


1
Bence fonksiyon dönmeli (basılmamalı) $s. return$i?f:$ssonunda sonunda bir şeyler yapabilirsin
Conor O'Brien,

@ ConorO'Brien Emin değilim ama eğer Düşünceniz doğru olursa, 5 Byte
Tasarruf Etmenizi Sağlayabilir

1
Birkaç bayt süper küresel değişkenlerle kaydedilebilir: function f($i){return[$_GET[0]+=$i][$i]?:f;}.
kullanıcı63956

@ user63956 çok güzel bir fikir
Jörg Hülsermann

1

PowerShell, 86 bayt

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

Çevrimiçi deneyin!

Test kodu:

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

Çıktı: 20


Çok hoş. PPCG'ye Hoşgeldiniz! Bunun $n="$args"yerine yaparak bir bayt kaydedebilirsiniz $n=$args[0]. Diğerinde işe yaramayacak $args[0], çünkü o zaman toplamadan ziyade string birleştirme elde edersiniz.
AdmBorkBork


1

Python, 69 bayt

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

1
Sanırım bu python mu? Cevabınızda kullanılan dili söylemelisiniz.
corvus_192

Cevabını daha fazla golf oynayabilir misin? Durduğu gibi, pek iyi golf oynamıyor.
Rɪᴋᴇʀ

1

Octave, 39 bayt

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

* Sonlandırma çağrısının argümanı 0'dır.

Çevrimiçi deneyin!

* endfunctiondiğer bazı kodları eklemek için gerekli.


1

R, 54 52 bayt

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

MickyT sayesinde 2 bayt kaydedildi!

Python cevaplarından birine benzer. Ungolfed:

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

Olarak çalışır

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

1
İyi iş. İf yan tümcesinin etrafındaki iç parantezlerden kurtulabilirsiniz. f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
MickyT

“Ungolfed” versiyonunun neden bu kadar şaşkın olduğunu düşünüyorum return. returnR 'de diğer dillerde olduğu gibi aynı değildir, erken iptal eder. Kullanmamak returndeyimseldir. Öte yandan, ungolfed versiyonunuz hala golf oynamıştır if.
Konrad Rudolph

@KonradRudolph Golf oynadı iftembellik, ancak returnsadece okunabilirlik için - aynı veya olmayan aynı sonucu verir return.
BLT

@ BLT Hm. R'deki gratuitous'un okunabilirliği return azalttığını kuvvetle hissediyorum çünkü yanlış bir şeyi (erken çıkış) işaret ediyor ve bir kargo kültü programlamanın bir örneği .
Konrad Rudolph

Güzel, yine yeni bir şey öğrendim. Bu geri gelmemin bir nedeni. Teşekkürler @KonradRudolph, bu Yığın Taşması sorusu da ilginç: stackoverflow.com/questions/11738823/…
BLT

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.