Tulis fungsi,, f
yang mengambil bilangan bulat positif dan mengembalikan fungsi.
Fungsi baru yang dikembalikan harus identik dengan f
. Namun, ketika "panggilan terminasi" terjadi, f
seharusnya mengembalikan jumlah semua bilangan bulat yang dilewati.
Misalnya, g=f(4)
(jika f
fungsi pertama) harus diatur g
ke fungsi lain. h=g(3)
akan melakukan hal yang sama. Namun, ketika Anda memanggil h
tanpa 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
sumber
f(4)
mengembalikan fungsi baru. Jika fungsi baru itu disebut tanpa argumen, ia kembali4
, tetapi jika itu disebut dengan argumen lain maka ia akan kembali mengembalikan fungsi baru dengan semantik yang sama tetapi dengan argumen baru ditambahkan ke4
dan seterusnya.q = f(2)(3); b = f(1)(2)(3); q(); b()
?Jawaban:
JavaScript (ES6), 18 byte
Berikan nilai palsu untuk mengambil jumlahnya. Nol dapat diizinkan dengan biaya 2 byte.
Cobalah online
Tidak Disatukan:
sumber
Haskell (GHC), 118 byte
Ini adalah 98 byte untuk kode dan 20 byte untuk flag compiler GHC
-XFlexibleInstances
, yang memungkinkan ekstensi sistem tipe.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
f
fungsi polimorfik parametrik yang dibatasi oleh batasan kelas tipe: tipenyaF a => Int -> a
. Ini berartif
mengambil integer dan mengembalikan nilai tipea
, untuk semua tipea
yang termasuk dalam typeclassF
.F
hanyalah nama dari typeclass yang menyediakan fungsif
; itu dinyatakan pada baris pertama.Dua baris berikutnya adalah dua instance
F
untuk tipe yang berbedaa
. Baris kedua menyatakan bahwa jenis fungsi dari()
ke bilangan bulat milikF
(di mana()
adalah tipe unit yang hanya anggota nilai()
), dan implementasinya adalahf n () = n
; fungsi mengembalikan argumen pertamanya. Baris terakhir menyatakan bahwa jikaa
milikF
, maka demikian juga jenis fungsi dari bilangan bulat kea
: dari suatu fungsif :: Int -> a
kita dapat menghasilkan fungsi lainf :: Int -> Int -> a
. Implementasinya adalahf m n = f (m+n)
(kode menggunakan kombinator untuk membuatnya lebih pendek), di manaf
di sebelah kiri adalah yang baru, danf
di sebelah kanan adalah yang lama. Ini pada dasarnya memberif
argumen integer baru, yang ditambahkan ke yang berikutnya. Beragam argumen dijumlahkan seperti ini:Pada
f
setiap baris memiliki tipe yang berbeda.Fungsi Haskell digulung secara otomatis, jadi jika Anda
f
hanya memberikan bilangan bulat, Anda mendapatkan sebuah fungsi.sumber
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.f
, tetapi banyak sekali fungsi yang dipanggilf
. (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.f n()=n
danf=(f.).(+)
, jadi saya akan menyebutnya mendefinisikan dua fungsi.g 0 = 1
dang 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.)ghci
memuat di atas dan mencoba:t f
- itu akan mengatakanf :: F a => Int -> a
(artinya jikaa
adalah instance dari kelasf
, makaf
adalah fungsiInt -> 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.Python 2,
424136 byteSolusi ini tidak akan pernah mengalami overflow, karena Python mendukung bilangan bulat presisi-sewenang-wenang. Nol adalah "nilai spesial".
Cobalah online
Tidak Disatukan:
sumber
C,
6258 byte, bersaing dengan garis batasDisimpan 4 byte berkat Kevin! (Masih tidak menghapus typedef karena itu adalah sesuatu yang diperlukan untuk dipanggil.)
Fungsi untuk memanggil adalah
f
; Anda berhenti memanggilnya dan mendapatkan hasilnya dengan memanggilnya dengan nomor non-positif seperti0
. 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:
union
/struct
tipe yang memilikiint
subtipe 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 mendefinisikanB
tipe sebagai fungsi yang mengambil integer dan mengembalikan pointer ke fungsi yang mengambil integer. Diperluas, ini terlihat seperti:sumber
q;f(x){return x?(q+=x,f):q;}
.q
setelah menjalankan masing-masing, maka fungsi tidak akan lagi bisa digunakanMathematica, 25 byte
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: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 rumitf
, misalnya melaluif[x_]
argumen lain. Dengan menyiapkan dua definisi untuk ini, kita bisa mendapatkan perilaku yang diinginkan:f[x][y]
panggilan kef[x+y]
, sehingga mengkonsumsi satu "panggilan" dan menambahkan argumen di dalamnya. Aturan ini berlaku sampai kita tersisaf[sum][]
.sum
.sumber
C ++, 72 byte
Ini mendefinisikan tipe
F
yang bertindak sebagai fungsi yang diminta, dan variabelf
tipe yang akan dipanggil. Ini berlaku pada C ++ 11 dan bekerja dengan versi online GCC, clang, icc dan VC ++.Pemakaian:
Penjelasan:
Setelah preprocessing dan memformat ulang, sepertinya:
Ini biasanya ditulis:
return a;
danreturn {+a};
melakukan hal yang sama, karena unary+
tidak mengubah nilai, dan kawat gigi redundan di sekitar nilai kembali diperbolehkan.int m
danint(m)
melakukan hal yang sama, karena kurung redundan di sekitar nama variabel diizinkan, termasuk parameter fungsi.return {m+a};
danreturn {int(m)+a};
melakukan hal yang sama, sebagai pemeranm
dariint
keint
tidak mengubah nilainya. Perubahan ini membuat duaoperator()
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.sumber
operator()
untuk membuat pekerjaan ini sangat keren.Ruby, 23 byte
Pemakaian:
sumber
C,
10496 byteMenggunakan metode dari tautan yang dibagikan @JulianWolf. Argumen terakhir harus 0.
Cobalah online!
sumber
Math.JS, 38 Bytes
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
Seperti yang ditunjukkan pada LaTex di atas,
f(x)
cukup panggili(x,0)
, lalu,i(x,y)
mengembalikan nilaiy
ifx
kurang dari 0, atau fungsij(z)=i(z,x+y)
, yang mengambil satu argumen, yang loop. Menambah nilaiy
.sumber
C,
232206 byteIni 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:
Mengkompilasi dan menjalankan dengan
gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-currying
output (setelah beberapa peringatan)sumber
g
danh
untuk melanjutkan rangkaian permintaan makro tidak dijamin berfungsi, karena tidak ditentukan apakah yang berikutnyag
muncul dalam konteks ekspansi yang pertamag
. 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?*s
bukanstrlen(s)
. String C adalah panjang implisit, diakhirichar
dengan nilai with0
. Peretasan makro yang bagus untuk memungkinkan panggilan dengan / tanpa argumen!8086 kode mesin, 27 byte
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
0
akan menghemat satu byte (xor si,si
bukanmov si, 0x100
)Diperlukan konvensi panggilan
Ini mengasumsikan penelepon telah mengalokasikan setidaknya 27 byte pada stack. Dibutuhkan angka
ax
, dan mengembalikan penunjuk fungsibx
. Memanggil penunjuk ini denganax=0
mengakhiri rantai, dan mengembalikan jumlahnyabx
.Jadi untuk panggilan pertama:
Kemudian, untuk setiap panggilan selanjutnya:
Untuk mengakhiri:
Ungolfed (berkomentar pembongkaran kode mesin):
Setelah memanggil ini dengan AX yang bukan nol,
bx = sp
dan buffer diisi dengan salinan kode mesin yang dimodifikasifunction
. 16-bit langsung dalam instruksi pertama menampung total. (Ini ditulis oleh instruksi terakhir sebelumret
.)push di
Sayapop bx
bisa diganti denganmov bx, di
(sebelumrep movsb
), membuatnya lebih sederhana tetapi tanpa penghematan.Membutuhkan pemanggil untuk meneruskan pointer ke buffer dst di
di
akan menghemat 4 byte vs menghitungnya relatif terhadapsp
.Membuat fungsi alamat mulai sama dengan ukuran fungsi akan menghemat byte (
mov cx, si
).sumber
objdump -b binary
alih-alihhexdump -C
di
(4 byte). Buat fungsi start address = size:mov cx, si
alih-alihmov cx, 0x1b
.C #, 62 byte
Untuk mengakhiri panggilan masuk dalam nomor negatif misalnya
sumber
null
atau tidak ada parameter untuk mengakhiri. Namun, semua cara yang saya coba jauh lebih lama!m
alih-alihm<0
dan meneruskannull
atau0
sebagai parameter terakhir?Boolean
dapat digunakan sebagaiBoolean
... Saya mencoba dengannull
tetapi 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.Scala, 58 karakter
Cobalah online
Tidak Disatukan:
Penjelasan:
Kode ini mendefinisikan
case class
f 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 tanpanew
kata 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 sebagaio(x)
. Ini digunakan dalam perpustakaan standar untuk array, daftar, peta danFunction1
sifat yang diimplementasikan oleh fungsi anonimsumber
Pyth, 19 byte
Cobalah online!
Saya terkesan bahwa Javascript mengalahkan Pyth, tetapi sekali lagi Pyth tidak cukup dirancang untuk menjadi fungsi yang lewat.
sumber
Perl 5, 36 byte
sumber
-M5.016
? Sepertinya Anda harus bisa drop-M5.016
dan kemudian juga dropmy
dan menyimpan beberapa byte. Jika itu hanyasay
, Anda dapat menggunakan flag-E
sebagai gantinya, yang tidak aktifuse strict
, sehingga Anda masih dapat menghapus flagmy
.__SUB__
) tetapi saya mengubahnya sebelum mengirim dan tidak menghapus sedikit tentang 5.16. Saya akan menghapusnya. Saya tidak berpikir bahwa menjatuhkanmy
akan benar.say
sebagai bagian dari kode, itu hanya untuk tujuan ilustrasi)my
tanpause strict
,$n
secara implisit merupakan variabel global. Ini bentuk yang buruk dalam skrip perl yang tepat, tetapi cukup umum di one-liners, dan tampaknya berfungsi di sini.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
0
sebagai 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:
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
-r
flag, 0 ada di bagian atas stack, jadi kita bisa pop dulu:Cobalah online!
Cobalah online!
sumber
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 .
Nilai terminal adalah nol. Nilai kembali adalah gabungan, jadi untuk memanggil hasilnya, gunakan bidang
f
, dan untuk mengakses nilai akhir, gunakan bidangv
, misalnyaCobalah 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
f
disimpan ke serikat kembali melaluiint
anggota, 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!sumber
APL (Dyalog Classic) ,
48474644 32 byteCobalah 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!
sumber
:If x<0
ke:If×x
dan tukar klausul "jika" dan "lain"r←⍎condition⊃'else' 'then'
Perl 6 , 31 byte
sumber
Dyvil , 34 byte
Penggunaan :
Jejak
()
dapat dihilangkan.Penjelasan :
Menentukan operator penjajaran yang mengambil dua int dan menambahkannya. Parameter
j
memiliki nilai default0
untuk mendukung panggilan tanpa argumen. Dalam0
contoh di atas bukan nama, tetapi literal.sumber
Julia v0.5 +, 52 byte
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.
sumber
Julia 0,5 , 18 byte
Cobalah online!
sumber
R, 40 byte
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 :
(Ya, itu sah R. Itu hanya perlu impor.)
sumber
PHP, 44 Bytes
Sebuah Ide dari @ user63956
Panggilan penghentian
0
Versi Online
Panggilan pemutusan dengan
NULL
kebutuhan[$i]
untuk[+$i]
PHP, 47 Bytes
Versi Online
PHP, 52 Bytes
Pemutusan panggilan
NULL
atau nilai lain yang salah dalam PHPjika program harus berakhir setelah Output ganti
print$s
dengandie("$s")
+ 2 BytesVersi Online
sumber
$s
. sehingga Anda dapat melakukan sesuatu sepertireturn$i?f:$s
pada akhirnyafunction f($i){return[$_GET[0]+=$i][$i]?:f;}
.PowerShell, 86 byte
Cobalah online!
Kode uji:
Output: 20
sumber
$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.Python 3 , 63 byte
Cobalah online!
Berakhir dengan 0
sumber
Python, 69 byte
sumber
Oktaf, 39 byte
* Argumen panggilan terminasi adalah 0.
Cobalah online!
*
endfunction
diperlukan untuk menambahkan beberapa kode lainnya.sumber
R,
5452 byteDisimpan 2 byte berkat MickyT!
Mirip dengan salah satu jawaban python. Tidak Disatukan:
Berjalan sebagai
sumber
f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
return
.return
di R tidak sama dengan di bahasa lain, ia melakukan pembatalan prematur. Tidak menggunakanreturn
idiom. Di sisi lain versi ungolfed Anda masih memiliki golfif
.if
adalah kemalasan, tetapireturn
hanya untuk keterbacaan - itu memberikan hasil yang sama dengan atau tanpareturn
.return
mengurangi keterbacaan karena menandakan hal yang salah (keluar prematur) dan merupakan contoh pemrograman pemujaan kargo .C ++ (gcc) ,
9591 byteCobalah online!
sumber