Apakah angka ini faktorial?

38

Tugas

Diberi nomor alami sebagai input, tugas Anda adalah menampilkan nilai kebenaran atau falsey berdasarkan apakah input tersebut merupakan faktorial dari nomor alami mana pun. Anda dapat mengasumsikan bahwa nomor input akan selalu berada dalam kisaran angka yang didukung oleh bahasa Anda, tetapi Anda tidak boleh menyalahgunakan tipe nomor asli untuk meremehkan masalah .

Berlaku celah standar .


Memasukkan

Anda akan diberi nomor alami (tipe Integeratau serupa).

Anda dapat mengambil input dengan cara apa pun yang Anda inginkan kecuali dengan asumsi itu berada dalam variabel yang telah ditentukan. Membaca dari file, konsol, kotak dialog ( prompt), kotak input dll diperbolehkan. Input sebagai argumen fungsi juga diizinkan!


Keluaran

Program Anda harus menampilkan nilai kebenaran atau falsey berdasarkan apakah nomor input merupakan faktorial dari nomor alami.

Pastikan nilai kebenaran / falsey Anda konsisten untuk semua input, yaitu, jika Anda menggunakan pasangan 1 dan 0 untuk masing-masing menyatakan nilai kebenaran dan falsey, maka program Anda harus menampilkan 1 untuk semua input yang harus memiliki nilai kebenaran dan 0 untuk semua input yang harus memiliki nilai falsey.

Anda dapat mengambil output dengan cara apa pun yang Anda inginkan kecuali menuliskannya ke variabel. Menulis ke file, konsol, layar dll. Diperbolehkan. Fungsinya returnjuga diizinkan!

Program Anda tidak boleh menghasilkan kesalahan untuk input apa pun!


Uji Kasus

Input     Output

1         Truthy (0! or 1!)
2         Truthy (2!)
3         Falsey
4         Falsey
5         Falsey
6         Truthy (3!)
7         Falsey
8         Falsey
24        Truthy (4!)
120       Truthy (5!)

Kriteria Kemenangan

Ini adalah , jadi kode terpendek dalam byte menang!

Arjun
sumber
2
Jika bahasa hanya mendukung angka dalam rentang {0,1}, dapatkah saya berharap inputnya selalu 1?
eush77
11
@ eush77 Menyalahgunakan jenis nomor asli untuk menyepelekan masalah dilarang secara default.
Dennis
1
adalah 4! sebuah kebenaran?
tuskiomi
Pertanyaan: Mengapa Anda tidak menggunakan standar I / O?
CalculatorFeline

Jawaban:

37

Brachylog , 1 byte

Cobalah online!

Penjelasan

adalah built-in yang menyatakan hubungan berikut: outputnya adalah faktorial dari inputnya. Kami cukup memberikannya set output dan melihat apakah itu sesuai atau tidak dengan input variabel.

Fatalisasi
sumber
6
@BetaDecay Itu karena cara itu dicetak dalam Prolog (ini ada hubungannya dengan fakta yang true.merupakan pernyataan dan truebukan)
Fatalize
6
Ini solusi sepele, tetapi pintar karena cara prolog bekerja.
Buah Esolanging
5
@Nayuki Yang ini, yang merupakan kebiasaan
Fatalize
17
Bahasa khusus pertama, lalu penyandian khusus ... golf kode sudah mati. Kami benar-benar telah menumbangkan seluruh pokok masalah yang mengasyikkan ini
Alexander - Reinstate Monica
13
@Alexander Penyandian khusus tidak relevan dengan masalah apa pun yang Anda bicarakan. Saya bisa menggunakan pengkodean "yang ada" sebagai gantinya dan itu masih akan menjadi 1 byte. Itu akan jauh lebih mudah dibaca.
Fatalkan
19

Jelly , 3 byte

!€ċ

Cobalah online!

1 untuk ya, 0 untuk tidak.

Bagaimana itu bekerja

!€ċ  argument as z
!€   [1!, 2!, 3!, ..., z!]
  ċ  count the number of occurrence of z
Biarawati Bocor
sumber
19

Jelly , 4 byte

Œ?IE

Bukan jawaban Jelly terpendek, tapi agak efisien.

Cobalah online!

Bagaimana itu bekerja

Œ?IE  Main link. Argument: n

Œ?    Yield the n-th permutation of the positive integers, without the sorted tail.
      For 120, this yields [5, 4, 3, 2, 1], the tail being [6, 7, 8, ...].
  I   Increments; compute all forward differences.
      For 120, this yields [-1, -1, -1, -1].
   E  Check if all differences are equal.
Dennis
sumber
2
Karena kami pegolf kode peduli efisiensi.
Okx
12
Ini peningkatan kompleksitas yang dramatis dengan biaya satu byte dan ini adalah penggunaan yang pintar dari built-in jika saya dapat mengatakannya sendiri. ¯ \ _ (ツ) _ / ¯
Dennis
Menariknya, ini mengembalikan true untuk 0, sedangkan jawaban 3 byte @ LeakyNun, sementara jauh lebih lambat secara umum, mengembalikan false dengan benar untuk 0. Apakah byte tambahan diperlukan untuk mengembalikan false untuk 0 dalam jawaban waktu eksekusi yang efisien?
Deadcode
@Deadcode Memeriksa 0 akan membutuhkan dua byte tambahan. Jika tidak yakin apakah definisi OP tentang "bilangan asli" termasuk 0 atau tidak. Kasing uji tidak ...
Dennis
17

ECMAScript Regex, 733+ 690+ 158 119 118 (117🐌) byte

Ketertarikan saya pada regex telah dipicu dengan semangat baru setelah lebih dari 4½ tahun tidak aktif. Karena itu, saya mencari set angka dan fungsi yang lebih alami agar sesuai dengan regeks ECMAScript unary, melanjutkan meningkatkan engine regex saya, dan mulai menyikat PCRE juga.

Saya terpesona oleh keterasingan membangun fungsi matematika di ECMAScript regex. Masalah harus didekati dari perspektif yang sama sekali berbeda, dan sampai kedatangan wawasan kunci, tidak diketahui apakah mereka dapat dipecahkan sama sekali. Ini memaksa casting jaring yang jauh lebih luas dalam menemukan properti matematika mana yang mungkin dapat digunakan untuk membuat masalah tertentu dapat dipecahkan.

Mencocokkan angka faktorial adalah masalah yang bahkan tidak saya pertimbangkan untuk ditangani pada tahun 2014 - atau jika saya melakukannya, hanya sebentar, mengabaikannya sebagai hal yang tidak mungkin terjadi. Tetapi bulan lalu, saya menyadari bahwa itu bisa dilakukan.

Seperti dengan posting regex ECMA saya yang lain, saya akan memberikan peringatan: Saya sangat merekomendasikan belajar bagaimana memecahkan masalah matematika unary di ECMAScript regex. Ini merupakan perjalanan yang menarik bagi saya, dan saya tidak ingin merusaknya bagi siapa pun yang mungkin ingin mencobanya sendiri, terutama mereka yang tertarik pada teori bilangan. Lihat posting ini sebelumnya untuk daftar masalah yang direkomendasikan untuk ditandai dengan spoiler bertanda satu per satu.

Jadi jangan membaca lebih jauh jika Anda tidak ingin beberapa sihir regex unary canggih dimanjakan untuk Anda . Jika Anda ingin mencoba mencari tahu sendiri keajaiban ini, saya sangat menyarankan memulai dengan menyelesaikan beberapa masalah dalam ECMAScript regex sebagaimana diuraikan dalam pos yang ditautkan di atas.

Ini ideku:

Masalah dengan pencocokan set angka ini, seperti kebanyakan yang lain, adalah bahwa dalam ECMA biasanya tidak mungkin untuk melacak dua angka yang berubah dalam satu lingkaran. Kadang-kadang mereka dapat multiplexing (mis. Kekuatan dari basis yang sama dapat ditambahkan bersama-sama dengan jelas), tetapi itu tergantung pada propertinya. Jadi saya tidak bisa hanya mulai dengan nomor input, dan membaginya dengan dividen yang meningkat secara bertahap sampai mencapai 1 (atau jadi saya pikir, setidaknya).

Kemudian saya melakukan penelitian tentang banyaknya faktor utama dalam bilangan faktorial, dan mengetahui bahwa ada formula untuk ini - dan itu salah satu yang mungkin bisa saya implementasikan dalam regex ECMA!

Setelah mengunyahnya sebentar, dan membangun beberapa regex lain sementara itu, saya mengambil tugas untuk menulis regex faktorial. Butuh beberapa jam, tetapi akhirnya bekerja dengan baik. Sebagai bonus tambahan, algoritme dapat mengembalikan faktorial terbalik sebagai pertandingan. Tidak ada yang menghindarinya, bahkan; dengan sifat bagaimana itu harus diimplementasikan dalam ECMA, perlu untuk menebak apa faktor terbalik sebelum melakukan hal lain.

The downside adalah bahwa algoritma ini dibuat untuk regex yang sangat panjang ... tapi saya senang bahwa akhirnya membutuhkan teknik yang digunakan dalam regex multiplikasi 651 byte saya (yang akhirnya usang, karena metode yang berbeda dibuat untuk 50 byte regex). Saya berharap masalah akan muncul yang memerlukan trik ini: Beroperasi pada dua angka, yang keduanya kekuatan dari basis yang sama, dalam satu lingkaran, dengan menambahkan mereka bersama-sama dengan jelas dan memisahkan mereka di setiap iterasi.

Tetapi karena kesulitan dan panjangnya algoritma ini, saya menggunakan lookaheads molekuler (dari bentuk (?*...)) untuk mengimplementasikannya. Itu adalah fitur yang tidak ada dalam ECMAScript atau mesin regex utama lainnya, tetapi yang saya miliki implementasikan di mesin saya . Tanpa tangkapan apa pun di dalam molekul lookahead, secara fungsional setara dengan lookahead atom, tetapi dengan tangkapan itu bisa sangat kuat. Mesin akan mundur ke lookahead, dan ini dapat digunakan untuk memperkirakan nilai yang berputar melalui semua kemungkinan (untuk pengujian nanti) tanpa menggunakan karakter input. Menggunakannya dapat menghasilkan implementasi yang jauh lebih bersih. (Variable-length lookbehind setidaknya memiliki kekuatan yang sama dengan molekuler lookahead, tetapi yang terakhir cenderung membuat implementasi yang lebih mudah dan elegan.)

Jadi panjang 733 dan 690 byte sebenarnya tidak mewakili inkarnasi solusi yang kompatibel dengan ECMAScript - karenanya "+" setelahnya; tentu saja mungkin untuk mem-port algoritma itu ke ECMAScript murni (yang akan menambah panjangnya sedikit) tetapi saya tidak menyadarinya ... karena saya memikirkan algoritma yang jauh lebih sederhana dan lebih ringkas! Salah satu yang dapat dengan mudah diimplementasikan tanpa melihat molekul. Ini juga jauh lebih cepat.

Yang baru ini, seperti yang sebelumnya, harus menebak faktor terbalik, bersepeda melalui semua kemungkinan dan mengujinya untuk pertandingan. Ini membagi N dengan 2 untuk memberikan ruang bagi pekerjaan yang perlu dilakukan, dan kemudian membuat lingkaran di mana ia akan berulang kali membagi input dengan pembagi yang dimulai pada 3 dan bertambah setiap kali. (Dengan demikian, 1! Dan 2! Tidak dapat dicocokkan dengan algoritme utama, dan harus ditangani secara terpisah.) Pembagi ini terus dilacak dengan menambahkannya ke hasil bagi; dua angka ini dapat dipisahkan secara jelas karena, dengan asumsi M! == N, hasil bagi berjalan akan terus dibagi oleh M sampai sama dengan M.

Regex ini melakukan pembagian-oleh-variabel di bagian paling dalam dari loop. Algoritma pembagian sama dengan di regex saya yang lain (dan mirip dengan algoritma multiplikasi): untuk A≤B, A * B = C jika ada hanya jika C% A = 0 dan B adalah angka terbesar yang memenuhi B≤C dan C% B = 0 dan (CB- (A-1))% (B-1) = 0, di mana C adalah dividen, A adalah pembagi, dan B adalah hasil bagi. (Algoritma yang sama dapat digunakan untuk kasus yang A≥B, dan jika tidak diketahui bagaimana A dibandingkan dengan B, satu tes keterbagian tambahan adalah semua yang diperlukan.)

Jadi saya suka bahwa masalahnya dapat dikurangi menjadi bahkan lebih sedikit kompleksitas daripada regex Fibonacci dioptimalkan golf saya , tapi saya mengeluh dengan kekecewaan bahwa teknik multiplexing-power-of-the-same-base saya harus menunggu masalah lain yang sebenarnya membutuhkannya, karena yang ini tidak. Ini adalah kisah tentang algoritma multiplikasi 651 byte saya yang digantikan oleh 50 byte, sekali lagi!

Sunting: Saya dapat menjatuhkan 1 byte (119 → 118) menggunakan trik yang ditemukan oleh Grimy yang dapat memperpendek pembagian dalam kasus bahwa hasil bagi dijamin lebih besar dari atau sama dengan pembagi.

Tanpa basa-basi lagi, inilah regex:

Versi benar / salah (118 byte):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$|^xx?$

Cobalah online!

Kembalikan faktorial terbalik atau tidak cocok (124 byte):

^(?=((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$)\3|^xx?$

Cobalah online!

Kembalikan faktorial terbalik atau tidak cocok, dalam ECMAScript +\K (120 byte):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\K\3$|^xx?$

Dan versi bebas spasi dengan komentar:

  ^
  (?=                           # Remove this lookahead and the \3 following it, while
                                # preserving its contents unchanged, to get a 119 byte
                                # regex that only returns match / no-match.
    ((x*)x*)(?=\1$)             # Assert that tail is even; \1 = tail / 2;
                                # \2 = (conjectured N for which tail == N!)-3; tail = \1
    (?=(xxx\2)+$)               # \3 = \2+3 == N; Assert that tail is divisible by \3
    # The loop is seeded: X = \1; I = 3; tail = X + I-3
    (
      (?=\2\3*(x(?!\3)xx(x*)))  # \5 = I; \6 = I-3; Assert that \5 <= \3
      \6                        # tail = X
      (?=\5+$)                  # Assert that tail is divisible by \5
      (?=
        (                       # \7 = tail / \5
          (x*)                  # \8 = \7-1
          (?=\5(\8*$))          # \9 = tool for making tail = \5\8
          x
        )
        \7*$
      )
      x\9                       # Prepare the next iteration of the loop: X = \7; I += 1;
                                # tail = X + I-3
      (?=x\6\3+$)               # Assert that \7 is divisible by \3
    )*
    \2\3$
  )
  \3                            # Return N, the inverse factorial, as a match
|
  ^xx?$                         # Match 1 and 2, which the main algorithm can't handle

Sejarah lengkap optimalisasi golf saya di regex ini ada di github:

regex untuk mencocokkan nomor faktorial - metode perbandingan multiplisitas, dengan molekuler lookahead.txt
regex untuk mencocokkan nomor faktorial.txt (yang ditunjukkan di atas)

((x*)x*)((x*)+)((x+)+)n=3!\233=0

Mesin .NET regex tidak meniru perilaku ini dalam mode ECMAScript-nya, dan dengan demikian, 117 byte regex berfungsi:

Cobalah online! (versi eksponensial-perlambatan, dengan mesin .NET regex + emulasi ECMAScript)

Kode mati
sumber
14

JavaScript (ES6), 30 29 28 byte

Mengharapkan bilangan bulat positif. Pengembalian -1untuk kepalsuan dan -2untuk kebenaran.

f=(n,k=2)=>n>1?f(n/k,k+1):~n

console.log(1,  '-->',f(1))   // Truthy (0! or 1!)
console.log(2,  '-->',f(2))   // Truthy (2!)
console.log(3,  '-->',f(3))   // Falsey
console.log(4,  '-->',f(4))   // Falsey
console.log(5,  '-->',f(5))   // Falsey
console.log(6,  '-->',f(6))   // Truthy (3!)
console.log(7,  '-->',f(7))   // Falsey
console.log(8,  '-->',f(8))   // Falsey
console.log(24, '-->',f(24))  // Truthy (4!)
console.log(120,'-->',f(120)) // Truthy (5!)

Catatan : Fungsi ini mendukung input yang cukup besar (Anda harus membaca ini sebagai: 'cukup besar untuk JS'). Ini harus bekerja dengan aman hingga 2 53 - 1 . Pasti akan gagal mulai dari N = 121.645.100.408.831.992 , input ini dibulatkan menjadi 19! = 121.645.100.408.832.000 karena pengkodean IEEE-754-nya. Ada mungkin menjadi hasil positif palsu lain sebelum 121.645.100.408.831.991 karena kesalahan pembulatan, tapi saya tidak tahu pasti.

Arnauld
sumber
Bagus - sangat suka penggunaan ~di akhir.
Steve Bennett
Bisakah Anda mengedit sehingga saya dapat undownvote? (Jika Anda ingin tahu mengapa saya menurunkan suara, itu karena saya lupa tentang aturan I / O yang tidak biasa dari pertanyaan ini.)
CalculatorFeline
@Arnauld Undownvoted.
CalculatorFeline
11

Python 3 , 39 38 byte

f=lambda n,i=1:n>1and f(n/i,i+1)or n<1

Fungsi rekursif mengambil integer, n, mengembalikan nilai boolean inversley mewakili hasilnya (truthy: False, falsey: True)

Cobalah online!

Membagi berulang kali ndengan i, dengan nilai awal 1, sampai sisanya kurang dari atau sama dengan 1kemudian menguji apakah sisanya kurang dari 1, hanya faktorial yang akan berakhir dengan sisa sama dengan 1, dan <satu byte lebih pendek dari ==.

Jonathan Allan
sumber
@ovs kita telah dibatasi pada dua output yang konsisten. Itu, sayangnya, kembali 1untuk semua faktorial kecuali 1yang dikembalikan True.
Jonathan Allan
11

Java 8, 46 byte

i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;}

Ini didasarkan pada entri Roman Gräf yang saya dapat membuat selusin byte dari. Saya akan menyarankan itu di sana tetapi saya belum memiliki reputasi yang cukup untuk berkomentar! Kode pelari ujian saya yang dimodifikasi:

import java.util.function.Function;
import java.util.stream.IntStream;

public class IsFactorial {
    public static Function<Integer, Boolean> isFactorial = i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;};
    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};
    public static void main(String[] args){
        System.out.println(
            IntStream.of(truthyCases).allMatch(i->isFactorial.apply(i)) &&
            IntStream.of(falsyCases).allMatch(i->!isFactorial.apply(i)));
    }
}
Computronium
sumber
9

Retina , 50 38 byte

12 byte disimpan berkat @Neil dengan menggabungkan memperpendek loop dan dengan menyingkirkan ;

.+
1¶$&$*
+`^(1+)¶(\1)+$
1$1¶$#2$*
¶.$

Cobalah online!

Output 1untuk benar dan 0salah.

.+ cocok dengan seluruh nomor

1¶$&$*menggantinya dengan 1diikuti oleh baris baru dan pertandingan dikonversi ke unary

Program yang tersisa membagi angka unary di garis bawah dengan berturut-turut meningkatkan bilangan bulat positif, terus melacak di baris atas, sementara dimungkinkan untuk melakukannya.

+` loop sampai string tetap sama

  • ^(1+)¶(\1)+$cocok dengan baris atas banyak 1s dan kelipatannya banyak 1s di baris bawah dan ganti dengan

  • 1$1¶$#2$*garis atas banyak 1s dengan yang lain 1, yaitu, meningkatkan jumlah yang diwakili oleh garis atas oleh 1, diikuti oleh baris baru dan jumlah kecocokan dari garis atas di garis bawah (mis. jumlah pertandingan dari kelompok penangkap kedua ) 1s banyak , yaitu, membagi angka bawah dengan angka teratas

Setelah tidak mungkin lagi melakukannya,

¶.$berikan jumlah korek api regex ini, yaitu. apakah ada satu-satunya 1di garis bawah, yang hanya terjadi jika angka adalah faktorial


Jika no-crash / crash dibolehkan alih-alih nilai true / falsy, maka saya bisa mendapatkan 36 34 byte.

^
1¶
{`.+$
$*
^(1+)¶(\1)+$
1$1¶$#2

Ini berjalan dengan pendekatan yang sama, tetapi menggabungkan ke $*dalam garis ketiga dan keempat. Baris ketiga dan seterusnya adalah bagian dari loop yang sama, {adalah kependekan dari +(mana (grup mengelompokkan baris yang tersisa ke dalam loop. Faktorial berakhir pada program yang keluar dari loop, sementara non-faktorial terjebak dalam loop selamanya sampai Retina melempar OverflowException yang disebabkan oleh penggantian terakhir yang gagal sehingga memiliki bagian bawah unary bukan dalam desimal, dan penggantian pertama dari loop mengubah garis bawah dari desimal ke unary, sehingga meledak dengan cepat.

Kritixi Lithos
sumber
Simpan byte dengan menghapus 1seperti yang tersirat saat $*di akhir penggantian.
Neil
Lebih baik lagi, gabungkan $*dengan dua garis lainnya.
Neil
3
Saya terkesan bahwa Anda menemukan cara untuk crash Retina bersyarat. :)
Martin Ender
2
Bisakah Anda menambahkan penjelasan?
CalculatorFeline
8

05AB1E , 4 byte

L!QO

Cobalah online!

Penjelasan

L      # range [1 ... input]
 !     # calculate factorial of each
  Q    # compare with input for equality
   O   # sum
Emigna
sumber
1
Tidakkah Anda perlu menduplikasi input terlebih dahulu karena Lmuncul inputnya? Juga, Å!memberi Anda daftar faktorial kurang dari atau sama dengan input.
Neil A.
@NeilA. Untungnya input muncul lagi jika tidak ada cukup argumen di stack untuk operasi, jadi saya tidak perlu di Dsini. Tangkapan bagus tentang Å!. Saya selalu lupa tentang daftar-perintah. Itu tidak akan menyimpan byte, tetapi pasti lebih efisien.
Emigna
Saya tidak tahu tentang input yang muncul lagi ... yang pasti bisa menghemat banyak byte.
Neil A.
@NeilA. Ini adalah fitur yang cukup baru. Itu ditambahkan kurang dari sebulan yang lalu saya pikir.
Emigna
8

C ++, 102 100 92 Bytes

#include<cmath>
int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}

Loop melalui semua nilai dari 0ke ndan menghitung faktorial dan kemudian memeriksa apakah itu sama dengan n.

Terima kasih Christoph! (disimpan 8 byte)

Technocoder
sumber
Hai! Selamat datang di PPCG! Jawaban pertama yang bagus! Semoga sukses untuk masa depan!
Arjun
Jawaban pertama yang bagus! Anda dapat menyimpan beberapa byte seperti ini: int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}. lrounddan lgammasudah C ++ 11 jadi bisa saja #include<cmath>. Mungkin Anda dapat lebih meningkatkan saran saya :)
Christoph
7

Haskell , 43 26 byte

f n=elem n$scanl1(*)[1..n]

Cobalah online!

  • Disimpan 17 byte, terima kasih kepada Laikoni
sudee
sumber
2
f n=elem n$scanl1(*)[1..n]konyol tidak efisien tetapi lebih pendek.
Laikoni
Apakah tidak ada aturan tentang efisiensi kode?
sudee
1
Tidak ada yang saya sadari. code-golf meminta solusi sesedikit mungkin byte tanpa pernyataan efisiensi. Juga di mesin saya fungsi berfungsi hingga 40430tanpa penundaan yang nyata.
Laikoni
Saya bermaksud sesuatu di sepanjang baris "solusi harus berakhir dalam jangka waktu yang masuk akal", tapi saya kira itu cocok dengan persyaratan. Terima kasih!
sudee
1
Bagus dan sederhana. Saya pikir saya bisa melakukan yang lebih baik dengan pembagian — katakanlah, divModdengan [1..]berturut-turut sampai mencapai nol sisa dengan hasil bagi 1 (faktorial) atau sisanya bukan nol (non-faktorial), tetapi tampaknya itu bukan pendekatan yang tepat. Aku menemukan solusi 46-karakter lucu ini, meskipun: f|let x%n=mod n x==0&&(x+1)%div n x||n==1=(1%).
Jon Purdy
6

Haskell , 38 byte

m#n=n<2||mod n m<1&&(m+1)#div n m
(2#)

Cobalah online! Contoh penggunaan: (2#) 24. Pengembalian Trueatau False.

Ini adalah yang terpendek yang bisa saya dapatkan sementara masih sangat efisien. Bahkan untuk angka sebesar

145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000

hasilnya segera diberikan. Solusinya bekerja dengan membagi input noleh m = 2,3,4,5,...sampai baik hasilnya adalah satu atau ntidak habis dibagi m.

Untuk solusi 26-byte yang lebih pendek namun tidak efisien yang menghitung n!input yang bukan faktorial lihat di sini .

Laikoni
sumber
5

MATL , 5 byte

t:Ypm

Cobalah online!

Penjelasan

t     % Implicit input. Duplicate
:     % Range from 1 to that
Yp    % Cumulative product
m     % Ismember. Implicit display
Luis Mendo
sumber
5

Fourier , 40 39 byte

I~Q1~N(i^~i*N~N{Q}{1~Xo}N>Q{1}{1~X0o}X)

Cobalah di FourIDE!

Pada dasarnya mengalikan jumlah N dengan jumlah yang meningkat hingga N sama dengan (output 1) atau lebih besar dari (output 0) input.

Pseudocode Penjelasan:

Q = Input
N = 1
While X != 1
    i += 1
    N = N*i
    If N = Q Then
        Print 1
        X = 1
    End If
    If N > Q Then
        Print 0
        X = 1
    End If
End While
Peluruhan Beta
sumber
5

Japt , 8 6 byte

ol x¥U

Cobalah online!

Ini menghasilkan 0 untuk false dan 1 untuk true.

Penjelasan

 ol x¥ U
Uol x==U
Uo       # Create the range [0 ... input]
  l      # Replace each element by its factorial
     ==U # Compare each element to the input (yielding 1 if equal and 0 otherwise)
    x    # And sum the result
Luke
sumber
1
Saya benar-benar harus menambahkan "berisi" built-in: P
ETHproduksi
1
Oh hei, Anda dapat mengubah aU ¦Jke x¥U(memetakan masing X- masing ke X==Udan jumlah), meskipun itu tidak akan berfungsi pada TIO.
ETHproduksi
Gagal 2karena ohanya akan memberi Anda [0,1]. Inilah perbaikan dengan penghematan 1 byte.
Shaggy
4

Perl 5, 31 byte

$a=<>;$a/=++$i while$a>1;exit$a

Input diambil melalui STDIN, output diberikan melalui kode keluar (1 untuk faktorial, 0 untuk non-faktorial).

Input dibagi oleh bilangan bulat berturut-turut sampai 1 atau beberapa fraksi kurang dari satu, yang dipotong ke dalam hasilnya.

faubi
sumber
-5 bytes TIO
Nahuel Fouilleul
4

Perl 6 , 29 byte

{($_,{$_/++$}...2>*).tail==1}

Menguji

Diperluas:

{   # bare block lambda with implicit parameter 「$_」

  (              # generate a sequence

    $_,          # starting with the input

    {
      $_ / ++$   # divide previous element by an ever increasing number
                 # 1,2,3,4,5,6,7,8 ... *
    }

    ...          # keep generating until

    2 > *        # 2 is greater than what was generated
                 # ( 1 or a fractional number )

  ).tail == 1    # check if it ended at 1
}
Brad Gilbert b2gills
sumber
17 byte: {$_∈[\*] 1..$_}. Pendekatan lain yang menarik adalah 2>*.polymod(1..*).sum.
nwellnhof
4

setlX , 32 byte

f:=n|=>exists(x in{0..n}|n==x!);

Menciptakan fungsi yang disebut f mana Anda menggunakan faktorial potensial Anda sebagai parameter.

Ia bekerja dengan ukuran bilangan bulat sembarang tetapi itu cukup tidak efisien.

(Ngomong-ngomong: ini adalah partisipasi pertama saya di puzzle pemrograman)

BlueWizard
sumber
4

C (gcc), 33 byte

e;f(n){n=n%++e?n==!(e=0):f(n/e);}

Perhatikan bahwa beberapa penulis mendefinisikan "bilangan asli" sebagai bilangan bulat positif . Karena itu saya tidak peduli yang f(0)menyebabkan rekursi tak terbatas.

Hagen von Eitzen
sumber
Dapat diturunkan hingga 32 byte: Cobalah secara online! atau 31 byte dengan mengembalikan bukan nol untuk false: Coba online!
Deadcode
4

R , 28 22 byte

scan()%in%gamma(1:171)

Cobalah online!

ngm
sumber
Jadikan program lengkap 22 byte ?
JayCe
1
Saya khawatir saya akan mulai menggunakan barang-barang ini dalam kode produksi.
ngm
4

C # (.NET Core) , 68 byte

bool f(System.Numerics.BigInteger n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

Cobalah online!

Bukan solusi terpendek, tetapi bekerja dengan angka yang sangat besar. TIO Link menyertakan contoh dengan10000! .

Berikut adalah versi yang lebih pendek yang menggunakan intyang memiliki nilai maksimum 2147483647 .

C # (.NET Core) , 45 byte

bool f(int n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

Cobalah online!

Kredit ke @KevinCruijssen untuk total bermain golf 3 byte dari kedua jawaban!

dana
sumber
2
The &&dapat golfed untuk &, dan trailing ;tidak harus dihitung untuk fungsi lambda. Juga, tidak bisakah ulong k=2berada uint k=2di jawaban 50-byte Anda?
Kevin Cruijssen
1
Baik menangkap pada &vs &&. Saya pikir saya mendapatkan stack overflow, tapi sepertinya berhasil juga. ulongadalah 64 bit sedangkan uint32. Sepertinya orang lain menggunakan intjadi mungkin saya hanya akan menggunakannya untuk versi singkat. Sehubungan dengan trailing ;, ini adalah fungsi penuh, bukan lambda, jadi saya pikir saya perlu memasukkannya?
dana
Itu benar-benar aneh bagaimana .NET dapat menyelesaikan /dan di %antara ulongdan uint, tetapi tidak ulongdan int. Tidak tahu itu :)
dana
1
@Liver - Dengan doubleAnda mulai melihat pembulatan di beberapa titik - misalnya, 24! dan 120! gagal. Meskipun System.Numerics.BigIntegermemiliki ketepatan yang paling, intadalah jawaban terpendek :)
dana
1
@Deadcode - Anda benar tentang 0 :) Berdasarkan contoh dalam tantangan, saya mengartikan "bilangan asli" berarti 1,2, ... Saya setuju bahwa di dunia nyata, lebih baik menggunakan &&operator hubungan arus pendek. . Tapi ini golf kode;) Senang Anda suka 10000!contohnya!
dana
4

C ++ (dentang), 51 byte

Rekursi menang sejauh bermain golf.

51 byte, nol benar:

int f(int n,int i=2){return n<2?!n:n%i|f(n/i,i+1);}

Ini mengorbankan kecepatan yang cukup banyak untuk penghematan 1 byte. Ganti |dengan|| untuk membuatnya cepat, karena evaluasi hubung singkat OR logis.

Cobalah online! (Versi lambat 51 byte)
Cobalah secara online!(Versi cepat 52 byte)

Versi lambat tidak digabungkan:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    // Because any nonzero value represents "false", using "|" here is equivalent
    // to "||", provided that the chain of recursion always eventually ends. And
    // it does always end, because whether or not "n" is factorial, the "n / i"
    // repeated division will eventually give the value of zero or one, satisfying
    // the above condition of termination.
    return (n % i) | isFactorial(n / i, i+1);
}

Versi cepat tidak disatukan:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    if (n % i != 0)
        return 1; // not factorial
    else
        return isFactorial(n / i, i+1);
}

Ada banyak cara untuk mengatur ulang ini.

52 byte, bukan nol adalah benar:

int f(int n,int i=2){return n<2?n:n%i?0:f(n/i,i+1);}

Cobalah online!

52 byte, nol benar:

int f(int n,int i=2){return!n?1:n%i?n-1:f(n/i,i+1);}

Cobalah online!

Sebelum beralih ke rekursi, saya mencoba membuat beberapa versi berulang, dan mereka mendekati.

54 byte, bukan nol benar:

int f(int n){for(int i=2;n>1;)n=n%i?0:n/i++;return n;}

Cobalah online!

54 byte, nol adalah benar (berdasarkan pengiriman Java 8 Roman Gräf ):

int f(int n){int a=1,i=0;for(;a<n;a*=++i);return a-n;}

Cobalah online!

Sekarang, untuk bagian bawah laras, versi rekursif tanpa n==0 penanganan (saya menganggap ini tidak valid, karena 0 adalah bilangan alami, dan definisi apa pun yang tidak digunakan untuk "bilangan asli" dari penggunaan yang sangat terbatas). Dalam versi di bawah ini, rekursi tak terbatasf(0) salah satu memicu segfault karena meluap tumpukan, atau dengan kompiler yang mengoptimalkannya untuk iterasi, loop tanpa henti:

48 byte, nol benar:

int f(int n,int i=2){return n%i?n-1:f(n/i,i+1);}

Cobalah online!

48 byte, nol adalah benar (berdasarkan pengiriman 33 byte C (gcc) Hagen von Eitzen ):

int f(int n,int e=0){return n%++e?n-1:f(n/e,e);}

Cobalah online!

Kode mati
sumber
50 EDIT: 49 , tanpa rekursi.
Grimmy
Kembali ke rekursi untuk 48 . Dan Anda mungkin tidak akan seperti ini, tapi 44 dengan menggunakan var global.
Grimmy
3

Mathematica, 20 byte

!FreeQ[Range[#]!,#]&

versi lain untuk menguji angka besar (lihat komentar)

Range[10^3]!~MemberQ~#&

menguji hingga 1000!

J42161217
sumber
2
Seperti yang saya pahami pertanyaannya, apakah Mathematica mampu mengambil 1001! sebagai input maka ini tidak memenuhi spesifikasi.
Peter Taylor
2
Anda bahkan dapat menyimpan tiga byte sambil membuatnya valid untuk semua input. Cukup ganti 10 ^ 3 dengan #; Anda dapat menyimpan byte lain dengan menggunakan Range @ #
Julien Kluge
@Julien Klugethen mencari 1243234 akan membutuhkan waktu lama ...
J42161217
1
Saya pikir Anda dapat menyimpan byte lain dengan mengganti Range[#]dengan Range@#:)
numbermaniac
3
Looks seperti Anda dapat menyimpan belum byte lain dengan sintaks infiks: !Range@#!~FreeQ~#&.
numbermaniac
3

Cubix , 24 byte

U0O@1I1>-?1u>*w;W;@Orq)p

Cobalah online

Kubus

    U 0
    O @
1 I 1 > - ? 1 u
> * w ; W ; @ O
    r q
    ) p

Kita mulai dengan mendorong 1, Input, 1ke stack. Ini akan menjadi indeks kami, target kami, dan akumulator kami, masing-masing.

Kami kemudian mengulang. Pada setiap iterasi, kami mengurangi akumulator dari input. Jika hasilnya 0, kita selesai, jadi kita tekan 1, Output, dan keluar. Jika negatif, kami sudah melangkah terlalu jauh, jadi kami dorong 0,O mengucapkan, dan keluar. Kalau tidak, kita lihat

;p)*rq;
;         Pop the difference off the stack.
 p)       Move the index to the top of the stack and increment it.
   *      Multiply the accumulator by the index to get the next factorial.
    rq;   Put the stack back in the right order.
Mnemonik
sumber
3

Neim , 8 byte

𝐈Γ𝐈𝐩₁𝔼)𝐠

Penjelasan:

Example input: 6
𝐈         Inclusive range [1 .. input]
          [1, 2, 3, 4, 5, 6]
 Γ        For each...
  𝐈         Inclusive range [1 .. element]
            [[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6]]
   𝐩        Product
            [1, 2, 6, 24, 120, 720]
     𝔼      Check for equality with
    ₁       the first line of input
            [[0, 0, 1, 0, 0, 0]]
      )   End for each
       𝐠  Select largest element
          [1]

Cobalah!

Neim , 3 byte (tidak bersaing)

Non-bersaing sebagai token berisi dan token faktorial ditambahkan setelah tantangan dibuat.

𝐈𝐓𝕚

Penjelasan:

Example input: 6
𝐈     Inclusive range [1 .. input]
      [[1, 2, 3, 4, 5, 6]
 𝐓    Factorial each
      [[1, 2, 6, 24, 120, 720]]
  𝕚   Check that the [cycled] input is in the list
      [1]

Cobalah!

Okx
sumber
3

> <> , 24 22 byte

-2 byte terima kasih kepada @Aaron

Saya mencoba bahasa baru (karena lisensi Mathematica saya kedaluwarsa ...)

01\{=n;
?!\$1+:@*:{:}(

Cobalah secara online , atau di taman bermain ikan

Mengasumsikan nomor input sudah ada di stack , dan mengembalikan 0 atau 1. Ia bekerja dengan mengalikan n angka pertama sampai berhenti menjadi kurang dari input, dan kemudian mencetak 1 jika sama dengan input, dan 0 jika tidak t.

Bukan pohon
sumber
Anda bisa mengubah Anda v>\n<^menjadi \\n/; lihat di sini
Aaron
@ Harun, itu brilian, terima kasih!
Bukan pohon
3

APL (Dyalog Unicode) , 5 6 7 byte

Golfed byte dengan mengubah ×/ke !berkat Erik yang Outgolfer

⊢∊!∘⍳

Cobalah online!

Penjelasan

                          Range of numbers from 1 to argument, 1 2 3 4 .. n
   !                       Factorial; 1! 2! 3! 4! .. n!
⊢∊                         Is the right argument a member of this list?
Kritixi Lithos
sumber
Jumlah kumulatif?
Leaky Nun
@LeakyNun Tetap
Kritixi Lithos
Satu byte tambahan di GNU APL 1.2 N∊×\⍳N←⎕Bagaimana ini mengambil argumen? Saya tidak melihat di nmana pun. Apakah ini hal yang spesifik Dyalog?
Arc676
2
@ Arc676 Solusi saya adalah kereta api dan Anda menyebutnya seperti itu: (⊢∊(×/⍳)) right_argumentseperti yang Anda lihat di tautan TIO. Dan merujuk pada argumen yang benar.
Kritixi Lithos
Catatan: AGL akan menghemat satu byte; ⊢∊×\ä⍳. Solusi "benar" (tetapi lebih lama) adalah 0=1|!⍣¯1; "Apakah faktor pembalik bilangan bulat?"
Adám
2

JavaScript (ES6), 71 byte

Ini mengambil input sebagai argumen fungsi dan alertoutput. Keluaran 0untuk falsey dan 1untuk kebenaran.

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}alert(r)}

Penjelasan

Program ini terdiri dari dua fungsi, fdan g. fadalah fungsi komputasi faktorial rekursif, dan gmerupakan fungsi utama program. g mengasumsikan memiliki argumen tunggal n. Ini mendefinisikan argumen default rdengan nilai 0 dan argumen default lain dengan nilai 0. Itu, kemudian, mengulangi semua bilangan bulat dari 0 ke n, dan, di setiap iterasi, memeriksa apakah fungsi yang fditerapkan lebih dari i(indeks saat ini) sama n, yaitu apakah nmerupakan faktorial dari i. Jika itu terjadi menjadi kasus, r's nilai diatur ke 1. Pada akhir fungsi, ryang alerted.

Cuplikan Tes

( Catatan: Potongan keluaran digunakan console.log()karena tidak ada yang suka terlalu banyak dari sial alert()itu. )

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}console.log(r)}

g(1)
g(2)
g(3)
g(4)
g(5)
g(6)
g(7)
g(8)
g(24)
g(120)

Arjun
sumber
Eval mungkin lebih pendek daripada menggunakan blok kode.
Downgoat
@Downgoat Bagaimana saya harus melakukan itu? Maaf jika terlalu jelas! : P
Arjun
2

QBIC , 21 19 byte

[:|q=q*a~q=b|_x1}?0

Penjelasan

[:|     Start a FOR loop from 1 to n
q=q*a   q starts as 1 and is multiplied by the FOR loop counter
        consecutively: q=1*1, *2, *3, *4 ... *n
~q=b|   If that product equals n
_x1     Then quit, printing a 1
}       Close the IF and the FOR
?0      If we're here, we didn't quit early and didn't find a factorial, print 0

Sebelumnya

[:|q=q*a┘c=c+(q=b)}?c

Penjelasan:

[:|         Start a FOR loop from 1 to n
q=q*a       q starts as 1 and is multiplied by the FOR loop counter
            consecutively: q=1*1, *2, *3, *4 ... *n
┘           Syntactic line break
c=c+        c starts out at 0 and then keeps track of 
    (q=b)       how often our running total == n
}           Closes the FOR-loop
?c          Print c, which is 0 fir non-factorials and -1 otherwise.
steenbergh
sumber
2

Java 8, 59 byte

i->{for(int j=1,c=0;j<=i;j*=++c)if(j==i)return 1;return 0;}

Kode uji

import java.util.function.IntFunction;
import java.util.stream.IntStream;

public class IsFactorial
{
    public static IntFunction<Integer> isFactorial = i->
    {
        for(int j=1,c=0;j<=i;j*=++c)
            if(j==i)return 1;return 0;
    };

    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};

    public static void main(String[] args)
    {
        System.out.println
        (
            IntStream.of(truthyCases)
                .allMatch(i->isFactorial.apply(i)==1)
            && IntStream.of(falsyCases)
                .allMatch(i->isFactorial.apply(i)==0)
        );
    }
}
Roman Gräf
sumber