Kari yang panjangnya sewenang-wenang


53

Tulis fungsi,, fyang mengambil bilangan bulat positif dan mengembalikan fungsi.

Fungsi baru yang dikembalikan harus identik dengan f. Namun, ketika "panggilan terminasi" terjadi, fseharusnya mengembalikan jumlah semua bilangan bulat yang dilewati.

Misalnya, g=f(4)(jika ffungsi pertama) harus diatur gke fungsi lain. h=g(3)akan melakukan hal yang sama. Namun, ketika Anda memanggil htanpa argumen (lihat di bawah untuk perincian), itu harus menghasilkan 7, karena itu adalah jumlah dari argumen fungsi sebelumnya. Dengan kata lain f(3)(4)() == 7,.

Perhatikan bahwa ini tidak sama dengan f(3,4)().

"Panggilan pemutusan" adalah salah satu opsi berikut (pilihan Anda):

  • panggilan tanpa argumen
  • null sebagai argumen
  • nilai non-positif

Jumlah panggilan fungsi yang sewenang-wenang harus didukung, tidak ada batasan yang telah ditentukan.

Dijamin bahwa jumlah total tidak akan lebih besar dari 1'000.

Kita dapat berasumsi bahwa setidaknya ada satu panggilan dilakukan sebelum "panggilan penghentian".

Kode Anda tidak boleh menggunakan variabel statis, per-program, sehingga harus dimungkinkan untuk menjalankan percobaan beberapa kali dalam runtime yang sama dan mengamati perilaku yang persis sama.

Contoh:

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

4
@LuisMendo Secara umum berarti f(4)mengembalikan fungsi baru. Jika fungsi baru itu disebut tanpa argumen, ia kembali 4, tetapi jika itu disebut dengan argumen lain maka ia akan kembali mengembalikan fungsi baru dengan semantik yang sama tetapi dengan argumen baru ditambahkan ke 4dan seterusnya.
Martin Ender

6
@LuisMendo Memang terserah Eugene, tapi saya pikir membiarkan panggilan berulang akan secara signifikan menghilangkan tantangan, karena bagian yang menarik bukan untuk membuat fungsi stateful tetapi untuk membuat fungsi tingkat tinggi.
Martin Ender

6
@ MartinEnder Itu sangat masuk akal. Eugene, jika itu maksudnya, silakan ubah kata-kata tantangannya. Menulis fungsi yang dapat dipanggil tanpa batas sama sekali tidak menyarankan bahwa fungsi tersebut harus mengembalikan fungsi
Luis Mendo

4
Bisakah kita berasumsi bahwa hanya akan ada satu contoh dari rantai panggilan pada suatu waktu? Misalnya tidak q = f(2)(3); b = f(1)(2)(3); q(); b()?
Conor O'Brien

3
Baru saja mengambil Haskell, saya tertarik apakah ini mungkin di Haskell. Sistem tipe yang kuat membuat saya berpikir mungkin tidak.
CAD97

Jawaban:


49

JavaScript (ES6), 18 byte

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

Berikan nilai palsu untuk mengambil jumlahnya. Nol dapat diizinkan dengan biaya 2 byte.

Cobalah online

Tidak Disatukan:

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

Pengiriman brilian!
Eugene D. Gubenkov

21

Haskell (GHC), 118 byte

Ini adalah 98 byte untuk kode dan 20 byte untuk flag compiler GHC -XFlexibleInstances, yang memungkinkan ekstensi sistem tipe.

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

Ini mendefinisikan "fungsi" f, yang dapat dipanggil dengan bilangan bulat sembarang diikuti oleh unit (), setelah itu mengembalikan bilangan bulat. Diperlukan jenis anotasi. Cobalah online!

Penjelasan

Memaksa sistem jenis ketat Haskell untuk memungkinkan ini memerlukan beberapa keajaiban, yaitu, memungkinkan ekstensi GHC untuk instance typeclass fleksibel. Cara kerjanya adalah ffungsi polimorfik parametrik yang dibatasi oleh batasan kelas tipe: tipenya F a => Int -> a. Ini berarti fmengambil integer dan mengembalikan nilai tipe a, untuk semua tipe ayang termasuk dalam typeclass F. Fhanyalah nama dari typeclass yang menyediakan fungsi f; itu dinyatakan pada baris pertama.

Dua baris berikutnya adalah dua instance Funtuk tipe yang berbeda a. Baris kedua menyatakan bahwa jenis fungsi dari ()ke bilangan bulat milik F(di mana ()adalah tipe unit yang hanya anggota nilai ()), dan implementasinya adalah f n () = n; fungsi mengembalikan argumen pertamanya. Baris terakhir menyatakan bahwa jika amilik F, maka demikian juga jenis fungsi dari bilangan bulat ke a: dari suatu fungsi f :: Int -> akita dapat menghasilkan fungsi lain f :: Int -> Int -> a. Implementasinya adalah f m n = f (m+n)(kode menggunakan kombinator untuk membuatnya lebih pendek), di mana fdi sebelah kiri adalah yang baru, dan fdi sebelah kanan adalah yang lama. Ini pada dasarnya memberifargumen integer baru, yang ditambahkan ke yang berikutnya. Beragam argumen dijumlahkan seperti ini:

  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

Pada fsetiap baris memiliki tipe yang berbeda.

Fungsi Haskell digulung secara otomatis, jadi jika Anda fhanya memberikan bilangan bulat, Anda mendapatkan sebuah fungsi.


1
Mungkin aku penipu, tapi itu bukan tantangan yang diminta. Anda mendefinisikan dua fungsi (!), Keduanya disebut f, bukan fungsi tunggal yang melakukan pekerjaan. Namun, ini sedekat yang bisa Anda dapatkan di Haskell. Saya tidak berpikir itu mungkin untuk menyelesaikan tugas dengan fungsi tunggal karena sistem tipe yang ketat.
nimi

3
@nimi Ini mendefinisikan bukan dua fungsi yang dipanggil f, tetapi banyak sekali fungsi yang dipanggil f. (Satu untuk setiap jumlah argumen yang mungkin.) Fungsi-fungsi ini (dari keluarga tak terbatas ini) memiliki dua jenis definisi, satu jenis ketika jumlah argumen adalah nol, dan yang lain ketika tidak.
ShreevatsaR

@ ShreevatsaR: Saya melihat dua definisi, f n()=ndan f=(f.).(+), jadi saya akan menyebutnya mendefinisikan dua fungsi.
nimi

7
@nimi Ada dua definisi, tetapi bukan dua fungsi. Jumlah definisi tidak harus berupa jumlah fungsi. Misalnya, Anda dapat mendefinisikan fungsi faktorial dengan dua definisi g 0 = 1dan g n = g (n-1) * n, di mana ada dua definisi tetapi hanya satu fungsi. Di sini kita memiliki dua definisi tetapi banyak sekali fungsi. (Masing-masing dari jenis yang berbeda.)
ShreevatsaR

1
@nimi BTW ghcimemuat di atas dan mencoba :t f- itu akan mengatakan f :: F a => Int -> a(artinya jika aadalah instance dari kelas f, maka fadalah fungsi Int -> a) Jadi kita dapat menganggap ini sebagai salah satu fungsi atau banyak sekali, tetapi meskipun memiliki dua jenis definisi (seperti fungsi faktorial), saya tidak melihat dasar yang baik untuk menganggapnya sebagai dua fungsi.
ShreevatsaR

15

Python 2, 42 41 36 byte

Solusi ini tidak akan pernah mengalami overflow, karena Python mendukung bilangan bulat presisi-sewenang-wenang. Nol adalah "nilai spesial".

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

Cobalah online

Tidak Disatukan:

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

14

C, 62 58 byte, bersaing dengan garis batas

Disimpan 4 byte berkat Kevin! (Masih tidak menghapus typedef karena itu adalah sesuatu yang diperlukan untuk dipanggil.)

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

Fungsi untuk memanggil adalah f; Anda berhenti memanggilnya dan mendapatkan hasilnya dengan memanggilnya dengan nomor non-positif seperti 0. Coba test harness online!

Jadi, sejauh yang saya tahu, satu-satunya cara untuk "kari" fungsi yang memiliki beberapa tipe pengembalian adalah dengan melakukan salah satu dari yang berikut:

  1. Keluarkan hasilnya ke fungsi untuk memberi tahu kompiler bahwa Anda ingin memanggil hasilnya lagi;
  2. atau membuat union/ structtipe yang memiliki intsubtipe fungsi / referensial diri.

Saya mencoba melakukan (2), tetapi tampaknya agak bertentangan dengan semangat pertanyaan dan, terus terang, hampir tidak dapat dihilangkan. Jadi, sesuai dengan semangat tantangan, saya telah memilih opsi (1). Ini membutuhkan casting setiap fungsi yang dikembalikan ke fungsi, agar dapat digunakan.

Sintaks "currying" ini terlihat agak aneh, tetapi sangat mirip. Untuk meniru f(21)(1), seseorang harus menulis ((B)((B)f(21))(1))(0). Saya mendefinisikan Btipe sebagai fungsi yang mengambil integer dan mengembalikan pointer ke fungsi yang mengambil integer. Diperluas, ini terlihat seperti:

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

Jika Anda mengatakan itu hanya berakhir pada 0, Anda akan memerlukan casting (yang Anda lakukan dalam C karena C tidak dapat dengan tepat mendefinisikan fungsi yang mengembalikan dirinya sendiri), dan Anda membiarkan kliring global antara menjalankan ke pemanggil (yang Saya pikir sangat masuk akal), Anda dapat menyederhanakan semuanya q;f(x){return x?(q+=x,f):q;}.
Kevin


1
@Kevin, sesuai aturan situs, fungsi harus dapat digunakan kembali. Jika saya tidak nol qsetelah menjalankan masing-masing, maka fungsi tidak akan lagi bisa digunakan
Conor O'Brien

Mungkin pointer fungsi? Anda harus de referensi setiap kali tetapi mungkin layak
dicoba

1
@ ConorO'Brien Saya baru saja menerapkan pendekatan serikat Anda. Lebih panjang dari yang ini, tapi tidak jauh.
Jakob

13

Mathematica, 25 byte

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

Cobalah online! (Menggunakan Matematika.)

Dimungkinkan untuk melakukan tiga byte lebih sedikit dengan porting jawaban JavaScript, tapi saya ingin menyajikan solusi Mathematica yang lebih idiomatis. Ini @hanya sedikit gula sintaksis, yang membuat solusinya setara dengan:

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

Jadi ya idenya adalah bahwa di Mathematica Anda tidak bisa hanya mendefinisikan suatu fungsi f[x_]tetapi Anda dapat secara langsung melampirkan nilai ke ekspresi yang lebih rumit f, misalnya melalui f[x_]argumen lain. Dengan menyiapkan dua definisi untuk ini, kita bisa mendapatkan perilaku yang diinginkan:

  • Definisi pertama runtuh satu f[x][y]panggilan ke f[x+y], sehingga mengkonsumsi satu "panggilan" dan menambahkan argumen di dalamnya. Aturan ini berlaku sampai kita tersisa f[sum][].
  • Definisi kedua membongkar kasus terakhir ini dengan mendefinisikan seluruh hal untuk dievaluasi sum.

1
<3 pemrograman simbolik
Julian Wolf

8

C ++, 72 byte

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

Ini mendefinisikan tipe Fyang bertindak sebagai fungsi yang diminta, dan variabel ftipe yang akan dipanggil. Ini berlaku pada C ++ 11 dan bekerja dengan versi online GCC, clang, icc dan VC ++.

Pemakaian:

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

Penjelasan:

Setelah preprocessing dan memformat ulang, sepertinya:

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

Ini biasanya ditulis:

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

return a;dan return {+a};melakukan hal yang sama, karena unary +tidak mengubah nilai, dan kawat gigi redundan di sekitar nilai kembali diperbolehkan. int mdan int(m)melakukan hal yang sama, karena kurung redundan di sekitar nama variabel diizinkan, termasuk parameter fungsi. return {m+a};dan return {int(m)+a};melakukan hal yang sama, sebagai pemeran mdari intke inttidak mengubah nilainya. Perubahan ini membuat dua operator()kelebihan beban lebih dekat dalam sintaks, memungkinkan definisi makro tunggal untuk dipanggil dua kali. Memilih urutan yang tepat untuk ketiga anggota memungkinkan kata pertama dari baris berikutnya ( int) juga dimasukkan dalam definisi makro.


1
Cantik. Dan bukan hanya solusi golf ... kelebihan beban operator()untuk membuat pekerjaan ini sangat keren.
Ray Toal

6

Ruby, 23 byte

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

Pemakaian:

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

6

C, 104 96 byte

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

Menggunakan metode dari tautan yang dibagikan @JulianWolf. Argumen terakhir harus 0.

Cobalah online!


Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Dennis

4

Math.JS, 38 Bytes

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

Sebut saja dengan f(number_a)(number_b)(...)(negative_number)

Jika kami diizinkan menentukan panggilan awal, 12 byte ( f(x)=i(x,0)\n) dapat dijatuhkan, dan itu bisa dipanggil dengani(number_one,0)(number_two)(...)(negative_number)

Cobalah!

Penjelasan

Getah!

Seperti yang ditunjukkan pada LaTex di atas, f(x)cukup panggil i(x,0), lalu, i(x,y)mengembalikan nilai yif xkurang dari 0, atau fungsi j(z)=i(z,x+y), yang mengambil satu argumen, yang loop. Menambah nilai y.


4

C, 232 206 byte

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

Ini mungkin dapat di-golf secara signifikan, tetapi harus berfungsi sebagai bukti konsep bahwa C dapat digunakan, tanpa ekstensi bahasa *, untuk menyelesaikan masalah ini dengan menelepon tanpa argumen daripada dengan nilai ajaib.

* @hvd telah mencatat bahwa, sementara ini bekerja di luar kotak menggunakan gcc, beberapa perilaku tidak didefinisikan dalam standar C, yang berarti bahwa ini mungkin tidak portabel. Gunakan dengan risiko Anda sendiri!

Tidak Disatukan:

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

Mengkompilasi dan menjalankan dengan gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-curryingoutput (setelah beberapa peringatan)

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

"tanpa ekstensi bahasa apa pun" - Trik bolak-balik antara gdan huntuk melanjutkan rangkaian permintaan makro tidak dijamin berfungsi, karena tidak ditentukan apakah yang berikutnya gmuncul dalam konteks ekspansi yang pertama g. C11 menambahkan contoh ke 6.10.3.4 untuk menjelaskan bahwa itu tidak ditentukan. (IIRC, preprocessor TenDRA adalah yang tidak akan mengembangkannya seperti yang Anda inginkan.) Selain itu, tidak ada versi bahasa yang mendukung argumen makro kosong dan int implisit, sehingga program C yang valid tidak dapat menggunakan keduanya. :) Tetap saja, jawaban yang bagus. Apakah Anda ingin bermain golf lebih jauh?
hvd

@ DVD: ya, mungkin akan kembali ke sana dalam beberapa hari dan melihat apakah saya bisa menurunkannya. Anda pasti benar bahwa ini adalah perilaku yang tidak ditentukan, tetapi saya pikir perlakuan standar di sini adalah bahwa bahasa ditentukan oleh implementasinya, jadi selama ia bekerja dengan gcc, saya senang.
Julian Wolf

Saya hanya menanggapi komentar yang Anda masukkan dalam jawaban Anda yang tidak bergantung pada ekstensi bahasa apa pun. Ya, bahkan dengan ekstensi bahasa, itu sangat valid sebagai jawaban di sini, tidak bermaksud menyarankan sebaliknya.
hvd

Ah, itu pasti adil. Anda benar bahwa saya harus menetapkan bahwa, sementara tidak ada bendera tambahan yang diperlukan, ini mungkin tidak portabel.
Julian Wolf

Anda dapat menguji untuk string kosong dengan *sbukan strlen(s). String C adalah panjang implisit, diakhiri chardengan nilai with 0. Peretasan makro yang bagus untuk memungkinkan panggilan dengan / tanpa argumen!
Peter Cordes

4

8086 kode mesin, 27 byte

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

Kode mesin ini harus di alamat 0x100, dan mengasumsikan model kode kecil (cs = ds = es = ss). Lokasi fungsi dapat diubah tanpa biaya byte tambahan. Menempatkannya di offset 0akan menghemat satu byte ( xor si,sibukan mov si, 0x100)

Diperlukan konvensi panggilan

Ini mengasumsikan penelepon telah mengalokasikan setidaknya 27 byte pada stack. Dibutuhkan angka ax, dan mengembalikan penunjuk fungsi bx. Memanggil penunjuk ini dengan ax=0mengakhiri rantai, dan mengembalikan jumlahnya bx.
Jadi untuk panggilan pertama:

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

Kemudian, untuk setiap panggilan selanjutnya:

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

Untuk mengakhiri:

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

Ungolfed (berkomentar pembongkaran kode mesin):

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

Setelah memanggil ini dengan AX yang bukan nol, bx = spdan buffer diisi dengan salinan kode mesin yang dimodifikasi function. 16-bit langsung dalam instruksi pertama menampung total. (Ini ditulis oleh instruksi terakhir sebelum ret.)

push diSaya pop bxbisa diganti dengan mov bx, di(sebelum rep movsb), membuatnya lebih sederhana tetapi tanpa penghematan.

Membutuhkan pemanggil untuk meneruskan pointer ke buffer dst di diakan menghemat 4 byte vs menghitungnya relatif terhadap sp.

Membuat fungsi alamat mulai sama dengan ukuran fungsi akan menghemat byte ( mov cx, si).


Ini akan menjadi jawaban yang lebih baik jika Anda memasukkan pembongkaran byte kode mesin. jawaban kode mesin pasti membutuhkan versi yang tidak diklik. mis. gunakan objdump -b binaryalih-alihhexdump -C
Peter Cordes

Diperbarui dengan komentar pembongkaran. Kemungkinan penghematan: mengharuskan penelepon untuk mengirimkan pointer pertama di(4 byte). Buat fungsi start address = size: mov cx, sialih-alih mov cx, 0x1b.
Peter Cordes

2

C #, 62 byte

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

Untuk mengakhiri panggilan masuk dalam nomor negatif misalnya

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

Saya ingin membuatnya berfungsi dengan memasukkan nullatau tidak ada parameter untuk mengakhiri. Namun, semua cara yang saya coba jauh lebih lama
TheLethalCoder

Bisakah Anda menggunakan !malih-alih m<0dan meneruskan nullatau 0sebagai parameter terakhir?
betseg

@ Betseg Tidak dalam C # hanya Booleandapat digunakan sebagai Boolean... Saya mencoba dengan nulltetapi hanya saja lebih lama. Saya ingin menggunakan ??yang berarti jika LHS adalah null do RHS, tetapi seperti yang saya butuhkan jika LHS tidak null lakukan ini lagi lakukan RHS saya tidak bisa.
TheLethalCoder

2

Scala, 58 karakter

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

Cobalah online

Tidak Disatukan:

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

Penjelasan:

Kode ini mendefinisikan case classf yang dipanggil dengan konstruktor yang mengambil int. Tentukan kelas kasus yang akan menghasilkan metode equals, hashcode, toString dan salin, dan objek pendamping dengan nama yang sama untuk mengaktifkan pembuatan objek tanpa newkata kunci.

Kelas ini memiliki metode terapkan berlebih: Satu mengambil integer lain untuk menambah dan membuat objek baru dengan jumlah yang diperbarui, dan satu tanpa argumen untuk mendapatkan jumlah.

Dalam Scala, objek apa pun dengan metode terapkan dapat disebut seperti metode, yang o.apply(x)dapat ditulis sebagai o(x). Ini digunakan dalam perpustakaan standar untuk array, daftar, peta dan Function1sifat yang diimplementasikan oleh fungsi anonim


2

Pyth, 19 byte

DhdDebR?bh+dbdR$end

Cobalah online!

Saya terkesan bahwa Javascript mengalahkan Pyth, tetapi sekali lagi Pyth tidak cukup dirancang untuk menjadi fungsi yang lewat.


2

Perl 5, 36 byte

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

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

Bagaimana dengan ini -M5.016? Sepertinya Anda harus bisa drop -M5.016dan kemudian juga drop mydan menyimpan beberapa byte. Jika itu hanya say, Anda dapat menggunakan flag -Esebagai gantinya, yang tidak aktif use strict, sehingga Anda masih dapat menghapus flag my.
Chris

@ Chris Anda benar, tidak perlu 5.16, revisi awal saya berhasil (menggunakan __SUB__) tetapi saya mengubahnya sebelum mengirim dan tidak menghapus sedikit tentang 5.16. Saya akan menghapusnya. Saya tidak berpikir bahwa menjatuhkan myakan benar.
hobbs

(dan tidak, saya tidak menghitung saysebagai bagian dari kode, itu hanya untuk tujuan ilustrasi)
hobbs

1
Jika Anda menghapus mytanpa use strict, $nsecara implisit merupakan variabel global. Ini bentuk yang buruk dalam skrip perl yang tepat, tetapi cukup umum di one-liners, dan tampaknya berfungsi di sini.
Chris

2

Brain-Flak , 6 byte

Sebenarnya saya hanya memperhatikan bahwa karena ToS adalah format pengembalian yang valid, maka 0 tidak benar-benar diperlukan yang menghemat 2 byte:

({{}})

Cobalah online!

Pengiriman asli, 8 byte

Gunakan 0sebagai nilai khusus:

({{}}{})

Cobalah online!

Penjelasan

Mengingat argumen suatu 1 , sebuah 2 , ..., a n , 0 tumpukan awalnya terlihat seperti ini:

                                                       a n

                                                       

                                                       a 2

                                                       a 1

                                                       0

Kode kemudian melanjutkan, muncul setiap satu i , terakumulasi mereka, muncul dengan 0 menambahkan mereka dan mendorong hasilnya:

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

Solusi alternatif, 8 byte

Alih-alih memunculkan 0 dan menambahkannya ke jumlah, kita juga dapat menukar tumpukan karena yang benar awalnya kosong:

({{}}<>)

Cobalah online!

Menggunakan -rflag, 0 ada di bagian atas stack, jadi kita bisa pop dulu:

({}{{}})

Cobalah online!

{}({{}})

Cobalah online!


Ya ampun ... Bagus!
Eugene D. Gubenkov

2

C (GCC), 83 byte

Golf C pertama saya! Ada beberapa solusi C lain, tetapi yang ini agak berbeda. Penggunaan preprosesor adalah murni kosmetik. Pendekatan ini pertama kali dibahas dalam jawaban Conor O'Brien di sini .

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

Nilai terminal adalah nol. Nilai kembali adalah gabungan, jadi untuk memanggil hasilnya, gunakan bidang f, dan untuk mengakses nilai akhir, gunakan bidang v, misalnya

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

Cobalah secara Online

Keterbatasan

Variabel global memegang total running. Meskipun hal ini secara eksplisit dilarang, pengajuan tersebut mendukung pemanggilan berulang (totalnya diatur ulang dalam panggilan terminal), yang tampaknya menjadi alasan untuk larangan negara global.

Pointer ke fdisimpan ke serikat kembali melalui intanggota, jadi ini jelas tidak portabel. Saya tidak yakin apakah ini berfungsi pada GCC di semua platform atau hanya di Linux atau hanya di x86 atau hanya dengan ELF atau ... Jika ada yang tahu detail tentang ini, silakan komentar atau kirim pesan!


2

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

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

0f

Cobalah online!

Berakhir dengan melewati nol. Sintaks panggilan:((0 f 1) 2) 0

-15 byte terima kasih kepada @ngn

Membutuhkan ⎕IO←0

Setiap kiat bermain golf dipersilakan!


jika Anda dapat menggunakan 0 sebagai nilai terminator, ubah :If x<0ke :If×xdan tukar klausul "jika" dan "lain"
ngn

Derp. Saya tidak melihat bahwa dikatakan "non-positif"
Zacharý

apakah kamu tahu trik ini? r←⍎condition⊃'else' 'then'
ngn


Pikir itu mengatakan 22 ...> _ <
Zacharý


1

Dyvil , 34 byte

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

Penggunaan :

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

Jejak ()dapat dihilangkan.

Penjelasan :

Menentukan operator penjajaran yang mengambil dua int dan menambahkannya. Parameter jmemiliki nilai default 0untuk mendukung panggilan tanpa argumen. Dalam 0contoh di atas bukan nama, tetapi literal.


1

Julia v0.5 +, 52 byte

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

Sebut sebagai F. Ini mungkin bisa dibuat jauh lebih pendek dengan mengadopsi metode OO yang lebih sedikit, tapi saya selalu suka mendapatkan kesempatan untuk menggunakan idiom ini.

Jika dapat diasumsikan bahwa "setidaknya satu panggilan akan dilakukan sebelum panggilan terminasi", baris kedua dapat dihilangkan untuk menghemat 6 byte.



1

R, 40 byte

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

0 bertindak sebagai nilai berhenti di sini. Untuk dua byte lagi, kita bisa menghilangkannya.

Masalahnya adalah bahwa R tidak memiliki lambda bawaan yang ringkas. Tetapi jika kita menambahkan satu , kita bisa mendapatkan kode hingga 26 byte :

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

(Ya, itu sah R. Itu hanya perlu impor.)


1

PHP, 44 Bytes

Sebuah Ide dari @ user63956

Panggilan penghentian 0

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

Versi Online

Panggilan pemutusan dengan NULLkebutuhan [$i]untuk[+$i]

PHP, 47 Bytes

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

Versi Online

PHP, 52 Bytes

Pemutusan panggilan NULLatau nilai lain yang salah dalam PHP

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

jika program harus berakhir setelah Output ganti print$sdengan die("$s")+ 2 Bytes

Versi Online


1
Saya pikir fungsinya harus kembali (bukan cetak) $s. sehingga Anda dapat melakukan sesuatu seperti return$i?f:$spada akhirnya
Conor O'Brien

@ ConorO'Brien Saya tidak yakin tetapi jika Pemikiran Anda benar, itu bisa menghemat 5 Bytes Terima Kasih
Jörg Hülsermann

1
Beberapa byte dapat disimpan dengan variabel superglobal: function f($i){return[$_GET[0]+=$i][$i]?:f;}.
user63956

@ user63956 ide yang sangat bagus
Jörg Hülsermann

1

PowerShell, 86 byte

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

Cobalah online!

Kode uji:

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

Output: 20


Sangat bagus. Selamat datang di PPCG! Anda dapat menyimpan byte dengan melakukan $n="$args"alih - alih $n=$args[0]. Itu tidak akan bekerja pada yang lain $args[0], karena, maka Anda akan mendapatkan rangkaian string daripada penambahan.
AdmBorkBork


1

Python, 69 byte

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

1
Saya berasumsi ini python? Anda harus menyatakan bahasa yang digunakan dalam jawaban Anda.
corvus_192

Bisakah Anda mencoba menjawab lebih banyak? Seperti berdiri, tidak golf dengan baik.
Rɪᴋᴇʀ

1

Oktaf, 39 byte

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

* Argumen panggilan terminasi adalah 0.

Cobalah online!

* endfunctiondiperlukan untuk menambahkan beberapa kode lainnya.


1

R, 54 52 byte

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

Disimpan 2 byte berkat MickyT!

Mirip dengan salah satu jawaban python. Tidak Disatukan:

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

Berjalan sebagai

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

1
Kerja bagus. Anda dapat menyingkirkan kawat gigi internal di sekitar klausa if. f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
MickyT

Saya agak bingung mengapa versi "ungolfed" Anda belum return. returndi R tidak sama dengan di bahasa lain, ia melakukan pembatalan prematur. Tidak menggunakan returnidiom. Di sisi lain versi ungolfed Anda masih memiliki golf if.
Konrad Rudolph

@KonradRudolph Golf ifadalah kemalasan, tetapi returnhanya untuk keterbacaan - itu memberikan hasil yang sama dengan atau tanpa return.
BLT

@ BLT Hm. Saya merasa kuat bahwa serampangan dalam R return mengurangi keterbacaan karena menandakan hal yang salah (keluar prematur) dan merupakan contoh pemrograman pemujaan kargo .
Konrad Rudolph

Keren, saya belajar sesuatu yang baru lagi. Itulah salah satu alasan saya terus kembali. Terima kasih @KonradRudolph, juga pertanyaan Stack Overflow ini menarik: stackoverflow.com/questions/11738823/…
BLT

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.