Buat program atau fungsi terpendek yang menemukan faktorial dari integer non-negatif.
Faktorial, diwakili dengan !
didefinisikan sebagai demikian
Dalam bahasa Inggris biasa faktorial 0 adalah 1 dan faktorial n, di mana n lebih besar dari 0 adalah n kali faktorial satu kurang dari n.
Kode Anda harus melakukan input dan output menggunakan metode standar.
Persyaratan:
- Tidak menggunakan perpustakaan bawaan yang dapat menghitung faktorial (ini termasuk segala bentuk
eval
) - Dapat menghitung faktorial untuk angka hingga 125
- Dapat menghitung faktorial untuk angka 0 (sama dengan 1)
- Selesai dalam waktu kurang dari satu menit untuk angka hingga 125
Pengajuan terpendek menang, dalam kasus seri, jawabannya dengan suara terbanyak pada saat menang.
code-golf
arithmetic
factorial
Kevin Brown
sumber
sumber
Jawaban:
Golfscript - 12 karakter
Memulai dengan Golfscript - Faktorial selangkah demi selangkah
Ini ada sesuatu untuk orang-orang yang mencoba belajar skrip golf. Prasyarat adalah pemahaman dasar tentang skrip golf, dan kemampuan untuk membaca dokumentasi skrip golf.
Jadi kami ingin mencoba skrip golf alat baru kami . Itu selalu baik untuk memulai dengan sesuatu yang sederhana, jadi kita mulai dengan faktorial. Berikut ini adalah upaya awal, berdasarkan kodesemu imperatif sederhana:
Spasi sangat jarang digunakan dalam skrip golf. Trik termudah untuk menyingkirkan spasi putih adalah dengan menggunakan nama variabel yang berbeda. Setiap token dapat digunakan sebagai variabel (lihat halaman sintaks ). Token berguna untuk digunakan sebagai variabel karakter khusus seperti
|
,&
,?
- umumnya apa pun tidak digunakan di tempat lain dalam kode. Ini selalu diuraikan sebagai token karakter tunggal. Sebaliknya, variabel sepertin
akan membutuhkan ruang untuk mendorong nomor ke tumpukan setelahnya. Angka pada dasarnya adalah variabel yang diinisialisasi.Seperti biasa, akan ada pernyataan yang bisa kita ubah, tanpa mempengaruhi hasil akhirnya. Dalam golfscript, semuanya mengevaluasi untuk benar kecuali
0
,[]
,""
, dan{}
(lihat ini ). Di sini, kita dapat mengubah kondisi keluar loop menjadi sederhana{n}
(kita loop waktu tambahan, dan berakhir ketika n = 0).Seperti halnya bermain golf bahasa apa pun, ada baiknya mengetahui fungsi yang tersedia. Untungnya daftar ini sangat pendek untuk skrip golf. Kita dapat mengubah
1-
untuk(
menyelamatkan karakter lain. Saat ini kodenya terlihat seperti ini: (kita bisa menggunakan1
alih-alih di|
sini jika kita mau, yang akan menghilangkan inisialisasi.)Penting untuk menggunakan tumpukan dengan baik untuk mendapatkan solusi terpendek (latihan praktik praktik). Secara umum, jika nilai hanya digunakan dalam segmen kode yang kecil, mungkin tidak perlu menyimpannya ke dalam variabel. Dengan menghapus variabel produk yang sedang berjalan dan hanya menggunakan tumpukan, kita dapat menyimpan cukup banyak karakter.
Ada hal lain untuk dipikirkan. Kami menghapus variabel
n
dari tumpukan di akhir badan loop, tetapi kemudian mendorongnya segera setelah itu. Bahkan, sebelum loop dimulai kami juga menghapusnya dari stack. Kita seharusnya membiarkannya di stack, dan kita bisa menjaga kondisi loop kosong.Mungkin kita bahkan bisa menghilangkan variabel sepenuhnya. Untuk melakukan ini, kita harus menyimpan variabel di stack setiap saat. Ini berarti bahwa kita memerlukan dua salinan variabel pada tumpukan di akhir pemeriksaan kondisi sehingga kita tidak kehilangannya setelah pemeriksaan. Yang berarti bahwa kita akan memiliki redundan
0
pada stack setelah loop berakhir, tetapi itu mudah diperbaiki.Ini membawa kita ke
while
solusi loop optimal kami !Sekarang kami masih ingin membuat ini lebih pendek. Target yang jelas harus menjadi kata
while
. Melihat dokumentasi, ada dua alternatif yang layak - buka dan lakukan . Ketika Anda memiliki pilihan rute yang berbeda untuk diambil, coba dan timbang manfaat keduanya. Buka lipatan adalah 'cukup banyak loop sementara', sehingga sebagai perkiraan kami akan memotong 5 karakterwhile
dengan 4 menjadi/
. Adapundo
, kami memotongwhile
3 karakter, dan bisa menggabungkan dua blok, yang mungkin menyimpan satu atau dua karakter lain.Sebenarnya ada kelemahan besar untuk menggunakan
do
loop. Karena pemeriksaan kondisi dilakukan setelah tubuh dieksekusi sekali, nilai0
akan salah, jadi kita mungkin perlu pernyataan if. Saya akan memberi tahu Anda sekarang bahwa lipatan lebih singkat (beberapa solusi dengando
disediakan di akhir). Silakan dan coba, kode yang sudah kita miliki membutuhkan perubahan minimal.Bagus! Solusi kami sekarang sangat singkat dan kami selesai di sini, kan? Nggak. Ini adalah 17 karakter, dan J memiliki 12 karakter. Jangan pernah mengakui kekalahan!
Sekarang Anda berpikir dengan ... rekursi
Menggunakan rekursi berarti kita harus menggunakan struktur percabangan. Sayangnya, tetapi karena faktorial dapat diekspresikan dengan ringkas secara rekursif, ini sepertinya merupakan alternatif yang layak untuk iterasi.
Yah itu mudah - seandainya kita mencoba rekursi sebelumnya kita mungkin bahkan tidak pernah melihat menggunakan
while
loop Namun, kami hanya memiliki 16 karakter.Array
Array umumnya dibuat dalam dua cara - menggunakan karakter
[
dan]
, atau dengan,
fungsi. Jika dieksekusi dengan integer di bagian atas tumpukan,,
mengembalikan array dengan panjang itu dengan arr [i] = i.Untuk iterating over array, kami memiliki tiga opsi:
{block}/
: push, block, push, block, ...{block}%
: [push, block, push, block, ...] (ini memiliki beberapa nuansa, misalnya nilai menengah dihapus dari tumpukan sebelum setiap dorongan){block}*
: push, push, block, push, block, ...Dokumentasi skrip golf memiliki contoh penggunaan
{+}*
untuk menjumlahkan isi dari suatu array. Ini menyarankan kita dapat menggunakan{*}*
untuk mendapatkan produk dari array.Sayangnya, itu tidak sesederhana itu. Semua elemen dimatikan oleh satu (
[0 1 2]
bukan[1 2 3]
). Kita dapat menggunakan{)}%
untuk memperbaiki masalah ini.Ya tidak cukup. Ini tidak menangani nol dengan benar. Kita dapat menghitung (n +1)! / (N +1) untuk memperbaiki ini, meskipun ini biayanya terlalu banyak.
Kami juga dapat mencoba menangani n = 0 dalam keranjang yang sama dengan n = 1. Ini sebenarnya sangat singkat untuk dilakukan, coba dan kerjakan sesingkat mungkin.
Jika kita ingin memiliki kenaikan dan perkalian di blok yang sama, kita harus mengulangi setiap elemen dalam array. Karena kita tidak membangun array, ini berarti kita harus menggunakan
{)*}/
, yang membawa kita ke implementasi skrip golf terpendek dari faktorial! Panjangnya 12 karakter, ini terkait dengan J!Solusi bonus
Dimulai dengan
if
solusi langsung untuk satudo
loop:Kita bisa memeras beberapa tambahan dari ini. Agak rumit, jadi Anda harus meyakinkan diri sendiri bahwa ini berhasil. Pastikan Anda memahami semua ini.
Alternatif yang lebih baik adalah menghitung (n +1)! / (N +1), yang menghilangkan kebutuhan akan suatu
if
struktur.Tetapi
do
solusi terpendek di sini membutuhkan beberapa karakter untuk memetakan 0 ke 1, dan yang lainnya untuk dirinya sendiri - jadi kita tidak perlu bercabang. Optimalisasi semacam ini sangat mudah untuk dilewatkan.Bagi siapa pun yang tertarik, beberapa solusi rekursif alternatif dengan panjang yang sama seperti di atas disediakan di sini:
* catatan: Saya belum benar-benar menguji banyak bagian kode dalam posting ini, jadi jangan ragu untuk memberi tahu jika ada kesalahan.
sumber
Haskell, 17
sumber
[1..0] ==> []
danproduct [] ==> 1
f 0=1;f n=n*f$n-1
adalah 17 karakter juga.product
dan, katakanlah,(*)
atau(-)
"dapat menghitung faktorial", dan semuanya ditentukan melalui Pendahuluan. Mengapa yang satu keren dan yang lainnya tidak?Python - 27
Cukup sederhana:
sumber
0**x
.math.factorial
? Itu bukan built-in, kan?0**x
?APL (4)
Berfungsi sebagai fungsi anonim:
Jika Anda ingin memberi nama, 6 karakter:
sumber
⍳
membuat vektor indeks, yaitu⍳5
adalah1 2 3 4 5
.×
adalah (jelas) bertambah banyak,/
mengurangi, dan∘
merupakan komposisi fungsi. Jadi,×/∘⍳
adalah fungsi yang mengambil argumenx
dan memberikan produk angka[1..x]
.J (12)
Definisi standar dalam J:
Kurang dari 1detik untuk 125!
Misalnya:
sumber
([:*/1+i.)
untuk 10 poin, atau bahkan 8 sebagai tanda kurung hanya diperlukan untuk memanggil fungsi, bukan untuk definisi.f 125x
apa fungsinyax
? Apakah ini nomor khusus?Golfscript - 13 karakter (SYM)
mendefinisikan fungsi
!
alternatif versi 13 char
seluruh versi program adalah 10 karakter
testcases membutuhkan waktu kurang dari 1/10 detik:
memasukkan:
keluaran
memasukkan
keluaran
sumber
Perl 6: 13 karakter
[*]
sama dengan Haskellproduct
, dan1..$_
merupakan hitungan dari 1 hingga$_
, argumen.sumber
[*]
lagi (pesan kesalahan "Dua istilah dalam satu baris").Matlab, 15
Uji Kasus
sumber
Python, 28 byte
(berdasarkan solusi Alexandru)
sumber
MATL , 2 byte
Dijelaskan:
Cobalah online!
sumber
Ruby - 21 karakter
Uji
sumber
Java, 85 Karakter
sumber
import java.math.*;
(jadi, +19 byte).PostScript, 26 karakter
Contoh:
Fungsi itu sendiri hanya membutuhkan 21 karakter; sisanya untuk mengikatnya ke variabel. Untuk menyimpan byte, seseorang juga dapat mengikatnya ke digit, seperti:
sumber
1.#INF
. (Saya menggunakan stock GNU Ghostscript 9.0.7 yang dikompilasi untuk Windows x64.)JavaScript, 25
CoffeeScript, 19
Mengembalikan
true
dalam kasus n = 0, tetapi JavaScript akan mengetik-memaksa itu menjadi 1.sumber
return
pernyataan dalam fungsi JavaScript?return
! Namun mengapa tidak?function f(n)n?n*f(--n):1
f=n=>!n||n*f(n-1)
Ambil itu, CoffeeScript!Ruby -
3029 karakterUji
sumber
end
langsung setelah:*
tanpa baris baru atau titik koma.(1..10).inject :*
# => 3628800f(0)
?f=->n{(1..n).inject 1,:*}
. Sebut saja denganf[n]
.F #: 26 karakter
Tidak ada fungsi produk bawaan di F #, tetapi Anda dapat membuatnya dengan lipatan
sumber
C #, 20 atau 39 karakter tergantung pada sudut pandang Anda
Sebagai metode contoh tradisional (39 karakter; diuji di sini ):
Sebagai ungkapan lambda (20 karakter, tetapi lihat penafian; diuji di sini ):
Kami harus menggunakan
double
karena 125! == 1.88 * 10 209 , yang jauh lebih tinggi dariulong.MaxValue
.Penafian tentang jumlah karakter versi lambda:
Jika Anda rekursi dalam C # lambda, Anda jelas harus menyimpan lambda dalam variabel bernama sehingga dapat memanggil dirinya sendiri. Tetapi tidak seperti (misalnya) JavaScript, lambda referensi-diri harus dideklarasikan dan diinisialisasi pada baris sebelumnya. Anda tidak dapat memanggil fungsi dalam pernyataan yang sama di mana Anda mendeklarasikan dan / atau menginisialisasi variabel.
Dengan kata lain, ini tidak berhasil :
Tapi ini memang :
Tidak ada alasan yang baik untuk pembatasan ini, karena
f
tidak pernah dapat ditetapkan pada saat dijalankan. PerlunyaFunc<int,double> f=null;
baris adalah kekhasan dari C #. Apakah itu membuatnya adil untuk mengabaikannya dalam hitungan karakter, tergantung pada pembaca.CoffeeScript,
2119 karakter nyataDiuji di sini: http://jsfiddle.net/0xjdm971/
sumber
Brachylog ,
76 byteDengan membuat rentang dan mengalikannya
Tangki -1 byte ke ovs memiliki ide untuk menggunakan fungsi max ()
Penjelasan
Cobalah online!
Brachylog ,
109 bytepengulangan
Penjelasan
Cobalah online!
sumber
;
bukannya,
memungkinkan untuk hanya input numerik biasa. -1byte anywayC (39 karakter)
sumber
double f(n){return!n?1:n*f(n-1);}
- 33 karakter.f(125)
akan meluapD: 45 Karakter
Lebih jelas:
Pendingin (meskipun versi yang lebih panjang) adalah templatized yang mengerjakan semuanya pada waktu kompilasi ( 64 karakter ):
Lebih jelas:
Template Eponim cukup bertele-tele, jadi Anda tidak bisa menggunakannya dalam kode golf dengan sangat baik. D sudah cukup verbose dalam hal jumlah karakter menjadi agak buruk untuk kode golf (meskipun sebenarnya sangat baik mengurangi ukuran program keseluruhan untuk program yang lebih besar). Ini adalah bahasa favorit saya, jadi saya pikir saya mungkin juga mencoba dan melihat seberapa baik saya bisa melakukannya di golf kode, bahkan jika orang-orang seperti GolfScript terikat untuk memperbaikinya.
sumber
PowerShell - 36
Naif:
Uji:
sumber
Scala, 39 karakter
Sebagian besar karakter memastikan bahwa
BigInt
s digunakan sehingga persyaratan untuk nilai hingga 125 terpenuhi.sumber
(x:Int)=>(BigInt(1)to x).product
def f(x:Int)=(BigInt(1)to x).product
def f(x:BigInt)=(x.to(1,-1)).product
def f(x:BigInt)=(-x to-1).product.abs
Javascript, ES6 17
ES6:
sumber
PowerShell, 42 byte
(disimpan 2 karakter menggunakan filter bukan fungsi )
Keluaran:
sumber
filter f($x){if($x){$x*(f($x-1))}else{1}}
. Dan itu dapat dikurangi lebih lanjut untuk 36 karakter jika itu disebut melalui pipa karena itu filter (misalnya125|f
):filter f{if($_){$_*($_-1|f)}else{1}}
Racket (skema)
403529 byteMenghitung 0! menjadi 1, dan menghitung 125! dalam 0 detik sesuai dengan timer. Pendekatan rekursif reguler
Versi baru untuk mengalahkan lisp umum: mengalikan semua elemen daftar (sama dengan solusi Haskell)
Versi yang lebih baru untuk mengalahkan solusi skema lainnya dan menghitung solusi raket lainnya dengan menggunakan foldl alih-alih menerapkan dan menggunakan rentang alih-alih buildlist
sumber
Mornington Crescent ,
18271698 karakterSaya merasa ingin belajar bahasa baru hari ini, dan inilah yang saya gunakan ... (Mengapa saya melakukan ini sendiri?) Entri ini tidak akan memenangkan hadiah apa pun, tetapi mengalahkan semua 0 jawaban lain sejauh ini menggunakan bahasa yang sama!
Cobalah online!
Siapa pun yang bepergian di London tentu akan mengerti hal itu secara instan, jadi saya yakin saya tidak perlu memberikan penjelasan lengkap.
Sebagian besar pekerjaan di awal adalah dalam menangani 0 case. Setelah menginisialisasi produk pada 1, saya dapat menggunakannya untuk menghitung maks (input, 1) untuk mendapatkan input baru, mengambil keuntungan dari fakta bahwa 0! = 1! Kemudian loop utama dapat dimulai.
(EDIT: Sejumlah besar perjalanan telah diselamatkan dengan melepaskan 1 dari "Terminal Heathrow 1, 2, 3" alih-alih menghasilkannya dengan membagi 7 (Sisters) dengan sendirinya. Saya juga menggunakan metode yang lebih murah untuk menghasilkan -1 dalam langkah selanjutnya.)
Pengurangan mahal di Mornington Crescent (meskipun lebih murah daripada Tube itu sendiri). Untuk membuat hal-hal lebih efisien, saya menghasilkan -1 dengan mengambil BUKAN dari 0 diurai dan menyimpannya di Hammersmith untuk sebagian besar loop.
Saya melakukan beberapa pekerjaan penting dalam hal ini, tetapi karena ini adalah upaya pertama saya bermain golf di Mornington Crescent (sebenarnya upaya pertama saya dalam bahasa apa pun ), saya berharap saya melewatkan beberapa optimisasi di sana-sini. Jika Anda tertarik untuk memprogram dalam bahasa ini sendiri (dan mengapa Anda tidak?), Esoteric IDE - dengan mode debug dan jendela arlojinya - adalah suatu keharusan!
sumber
Befunge - 2x20 = 40 karakter
Ini adalah fungsi karena merupakan blok kode mandiri yang tidak menggunakan sampul. Anda harus menempatkan argumen di atas tumpukan kemudian masuk dari kiri kanan ke kanan, fungsi akan keluar dari kanan bawah ke kanan dengan hasil di atas tumpukan.
Misalnya untuk menghitung faktorial dari 125
Pengujian 0
sumber
&:!#@_>:# 1# -# :# _$>\# :#* _$.@
(di mana & harus diganti dengan input). Ini 32 chars / byteJ - 6 karakter
Apakah ini masuk hitungan? Saya tahu ini sangat mirip dengan contoh J sebelumnya, tetapi sedikit lebih pendek :)
Saya seorang pemula dengan J, tapi sejauh ini sangat menyenangkan!
sumber
In C (23 Karakter)
Ini menyalahgunakan "fitur" GCC yang menjadikan tugas terakhir dianggap sebagai pengembalian jika tidak ada pengembalian yang ditentukan.
Dalam C yang tepat, 28 karakter
sumber
0 == ({printf("Hello, world!"); 0;});
Kona (
116)K bekerja dari kanan ke kiri (sebagian besar), jadi kami menghitung
x
(membuat daftar / larik angka dari0
kex-1
), menambahkannya1
(rentang daftar0
kex
), lalu mengalikan semua angka bersama. Jika bukan persyaratan untuk menghitung125!
, saya bisa menghemat 1 byte lagi dengan menghilangkan.
sebelah1
. Bagaimanapun, 125! dihitung dalam milidetik belaka:sumber
*/1.+!
: 6 byte.