Ulang! Faktorial!


34

Jangan bingung dengan Cari faktorial!

pengantar

Faktorial bilangan bulat ndapat dihitung dengan

n!=n×(n1)×(n2)×(...)×2×1

Ini relatif mudah dan bukan hal yang baru. Namun, faktorial dapat diperluas menjadi faktorial ganda , sehingga untuk bilangan genap, dan untuk angka ganjil. Tapi kami tidak terbatas pada faktorial ganda. Misalnya atau atau tergantung pada nilai awal.

n!!=n×(n2)×(n4)×(...)×4×2
n!!=n×(n2)×(n4)×(...)×3×1
n!!!=n×(n3)×(n6)×(...)×6×3
n!!!=n×(n3)×(n6)×(...)×5×2
n!!!=n×(n3)×(n6)×(...)×4×1

Secara ringkas: mana Atau, dalam bahasa Inggris polos: Kurangi jumlah faktorial dari angka dasar berulang kali dan gandakan semua bilangan bulat positif yang dihasilkan.

n!(k)={1if n=0nif 0<nkn((nk)!(k))if n>k
n!(k)=n!!k

Tantangan

Tulis fungsi yang akan menghitung segala faktorial berulang untuk bilangan bulat non-negatif.

Memasukkan

Antara

  • Sebuah string yang mengandung bilangan bulat basis-non-negatif, diikuti oleh 1 atau lebih tanda seru. Misalnya "6!"atau "9!!"atau "40!!!!!!!!!!!!!!!!!!!!".

atau

  • Nilai yang sama diwakili oleh dua bilangan bulat: satu nilai dasar non-negatif dan satu nilai positif yang mewakili jumlah faktorial. Ini dapat dilakukan sesuai dengan format apa pun dari aturan I / O default.

Keluaran

Hasil perhitungan tersebut.

Komentar tantangan

  • 0!sama 1dengan definisi. Kode Anda harus menjelaskan hal ini.
  • Hitungan faktorial dibatasi oleh nilai luar rentang ini, Anda bebas untuk menghasilkan apa pun. Selain itu , yang merupakan satu-satunya pengecualian untuk aturan ini.
    0<factorial countbase value
    0!

Contohnya

Input                              Output

3!!!                               3
0!                                 1
6!                                 720
9!!                                945
10!!!!!!!!                         20
40!!!!!!!!!!!!!!!!!!!!             800
420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  41697106428257280000000000000000

Cobalah dengan implementasi Python yang ungolfed: Cobalah online!

Komentar umum


6
Daftar contoh 0!tetapi pernyataan tantangan mengatakan bahwa jumlah faktorial akan kurang dari atau sama dengan nilai dasar.
Jonathan Allan

1
Bukankah 3 !!! menjadi nol? n * (n-3) = 3 * (3-3) = 0.
ouflak

2
@ouflak Jika berfungsi seperti 1 !, tidak juga. Ini lebih seperti 1! = 1. 2 !! = 2. 3 !!! = 3. Tidak ada perhitungan, karena Anda berada di akhir perulangan. Tidak ada 0 dalam produk atau setiap faktorial tunggal akan turun menjadi 0 pada akhirnya.
V. Courtois

4
3!!!!!!!seharusnya tidak didefinisikan — itu hanya akan menghasilkan jawaban 3. Itu sama dengan 1!!=1(tidak terdefinisi). Spesifikasi input Anda juga mengatakan bahwa akan selalu ada setidaknya satu !, jadi contoh pertama 3tidak sesuai dengan spesifikasi.
Greg Martin

3
@ FabianRöling: Tapi bukan itu masalahnya. Bukannya (3!)!malah menghapus istilah dari faktorial. Itu nama yang menyesatkan; Saya datang dengan asumsi itu akan menerapkan fungsi faktorial berulang kali dalam sebuah rantai dan harus membaca dengan cermat untuk melihat apa itu sebenarnya. Untungnya pertanyaan itu menjelaskannya dengan jelas. Nama yang lebih baik mungkin adalah langkah faktorial atau faktorial langkah atau sesuatu.
Peter Cordes

Jawaban:



13

ArnoldC , 702 698 634 byte

LISTEN TO ME VERY CAREFULLY f
I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE n
I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE p
GIVE THESE PEOPLE AIR
HEY CHRISTMAS TREE r
YOU SET US UP 1
HEY CHRISTMAS TREE c
YOU SET US UP 0
STICK AROUND n
GET TO THE CHOPPER r
HERE IS MY INVITATION r
YOU'RE FIRED n
ENOUGH TALK
GET TO THE CHOPPER n
HERE IS MY INVITATION n
GET DOWN p
ENOUGH TALK
GET TO THE CHOPPER c
HERE IS MY INVITATION 0
LET OFF SOME STEAM BENNET n
ENOUGH TALK
BECAUSE I'M GOING TO SAY PLEASE c
GET TO THE CHOPPER n
HERE IS MY INVITATION 0
ENOUGH TALK
YOU HAVE NO RESPECT FOR LOGIC
CHILL
I'LL BE BACK r
HASTA LA VISTA, BABY

Cobalah online!

Diterjemahkan ke pseudocode:

f(n,p) {
  r=1;
  c=0;
  while (n) {
    r=r*n;
    n=n-p;
    c=n<0;
    if (c) n=0;
  }
  return r;
}

Catatan: ArnoldC hanya memiliki satu jenis data: integer bertanda 16-bit. Karena itu saya tidak dapat menguji 420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!kasus ini.


Hanya ingin tahu tentang kode-kode Anda. Untuk apa variabel 'c'?
ouflak

@ouflak Saya mengedit jawaban saya beberapa kali dan melupakannya. The cvariabel sebenarnya menyimpan nilai perbandingan antara ndan 0.
Charlie

+1 dan saya meminjamnya (minus 'c') untuk jawaban LUA saya.
ouflak

12

Jelly , 4 byte

RṚmP

Cobalah online!

Bagaimana? Dengan dan , ia pertama-tama menghasilkan kisaran (with ), lalu dengan itu membuat setiap elemen dari rentang ini (jadi ), dan akhirnya mengalikannya dengan menggunakan .nkn,,1k th n , n - k , n - 2 k , , n - n / k kRṚmkthn,nk,n2k,,nn/kkP


Bekerja dengan baik, dan sangat sederhana pada akhirnya. Saya tidak tahu Jelly sama sekali tapi setidaknya itu terlihat bagus :)
V. Courtois

1
@ V.Courtois Diberikan dan , ia pertama-tama menghasilkan kisaran (with ), lalu dengan itu membuat setiap elemen dari rentang ini (jadi ), dan akhirnya mengalikannya dengan menggunakan . Hanya pendekatan sederhana. Sunting: Saya menambahkan penjelasan ini dalam jawabannya. k n , , 1 k th n , n - k , n - 2 k , , n - n / k knkn,,1RṚmkthn,nk,n2k,,nn/kkP
Tn. Xcoder

Hah terima kasih banyak. Suatu hari saya mungkin ingin bermain golf dalam bahasa ini jadi saya harus belajar monad, diad, dll.
V. Courtois

Alternatif yang terlihat seperti CJam: r1mP.
Erik the Outgolfer

1
@KyeWShi Jelly memiliki codepage sendiri , sehingga masing-masing dari 256 karakter yang dikandungnya dikodekan sebagai 1 byte.
Tn. Xcoder

8

APL (Dyalog Extended) , 7 byte SBCS

Fungsi awalan diam-diam anonim. Dibawa [n,b]sebagai argumen.

×/-\…1¨

Cobalah online!

 satu untuk setiap elemen argumen; [1,1]

-\ perbedaan kumulatif; [n,n-b]

 rentang menggunakan elemen kedua dari argumen kiri sebagai indikator langkah, misalnya [9,7]dilanjutkan dengan5

×/ produk


7

Haskell , 21 byte

n%a=product[n,n-a..1]

Cobalah online!

Menggabungkan fungsi produk bawaan dengan enumerasi range melangkah mengalahkan apa yang saya bisa kode secara rekursif (bahkan dengan flawr menyimpan byte).

22 byte

n%a|n<1=1|m<-n-a=n*m%a

Cobalah online!

Inilah solusi mengambil input dalam format string seperti 9!!, yang menurut saya lebih menarik.

42 byte

(\[(n,a)]->product[n,n-length a..1]).reads

Cobalah online!


2
Saya pikir Anda bisa mempersingkat solusi rekursif ken%a|n<1=1|m<-n-a=n*m%a
flawr


5

JavaScript (ES6), 21 byte

Mengambil input sebagai (k)(n).

k=>g=n=>n<1||n*g(n-k)

Cobalah online!

Atau 24 byte untuk mendukung BigInts.


JavaScript (ES6), 55 byte

Mengambil input sebagai string, menggunakan format yang dijelaskan dalam tantangan.

s=>(a=s.split`!`,k=a.length-1,g=n=>n<1||n*g(n-k))(a[0])

Cobalah online!


5

Spasi , 91 byte

[S S S T    N
Push_1][S N
S _Duplicate_1][S N
S _Duplicate_1][T   N
T   T   _Read_STDIN_as_integer_(base)][T    T   T   _Retrieve_base][S S S N
_Push_0][T  N
T   T   _Read_STDIN_as_integer_(factorial)][N
S S N
_Create_Label_LOOP][S N
S _Duplicate_base][S S S T  N
_Push_1][T  S S T   _Subtract][N
T   T   S N
_If_negative_jump_to_Label_PRINT_RESULT][S N
S _Duplicate_base][S T  S S T   S N
_Copy_0-based_2nd_(result)][T   S S N
_Multiply][S N
T   _Swap_top_two][S S S N
_Push_0][T  T   T   _Retrieve_factorial][T  S S T   _Subtract][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_PRINT_RESULT][S N
N
_Discard_top][T N
S T _Print_result_as_integer]

Huruf S(spasi), T(tab), dan N(baris baru) ditambahkan hanya sebagai penyorotan.
[..._some_action]ditambahkan sebagai penjelasan saja.

Cobalah online (dengan spasi, tab, dan baris baru saja).

Penjelasan dalam pseudo-code:

Integer result = 1
Integer base = STDIN as integer
Integer factorial = STDIN as integer
Start LOOP:
  If(base <= 0):
    Call function PRINT_RESULT
  result = result * base
  base = base - factorial
  Go to next iteration of LOOP

function PRINT_RESULT:
  Print result as integer to STDOUT


4

Perl 6 , 22 byte

{[*] $^a,*-$^b...^1>*}

Cobalah online!

Kode kunci anonim yang mengembalikan produk dari rentang mulai dari input pertama, menurun oleh yang kedua sampai di bawah 1, tidak termasuk nomor terakhir. Ini berfungsi untuk 0, karena kasus dasar dari pengurangan oleh produk adalah 1, jadi outputnya adalah 1.


4

05AB1E , 10 8 7 byte

ݦRIιнP

Input sebagai dua input yang terpisah: input pertama adalah base; input kedua adalah factorial.

Cobalah secara online atau verifikasi semua kasus uji .

-2 byte terima kasih kepada @ Mr.Xcoder .
-1 byte terima kasih kepada @JonathanAllan .

Penjelasan:

Ý        # Create a list in the range [0, (implicit) base-input]
 ¦       # And remove the first item to make it the range [1, base]
         # (NOTE: this is for the edge case 0. For the other test cases simply `L` instead
         #  of `ݦ` is enough.)
  R      # Reverse this list so the range is [base, 1]
   Iι    # Uninterleave with the second input as step-size
         #  i.e. base=3, factorial=7: [[3],[2],[1],[],[],[],[]]
         #  i.e. base=10, factorial=8: [[10,2],[9,1],[8],[7],[6],[5],[4],[3]]
         #  i.e. base=420, factorial=30: [[420,390,360,...,90,60,30],[419,389,359,...],...]
     н   # Only leave the first inner list
      P  # And take the product of its values
         # (which is output implicitly as result)

Jawaban 10 byte asli :

L0KD¤-IÖÏP

Input sebagai dua input yang terpisah: input pertama adalah base; input kedua adalah factorial.

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

L           # Create a list in the range [1, (implicit) base-input]
 0K         # Remove all 0s (edge case for input 0, which will become the list [1,0])
   D        # Duplicate this list
    ¤       # Get the last value (without popping)
            # (could also be `Z` or `¹` for max_without_popping / first input respectively)
     -      # Subtract it from each item in the list
      IÖ    # Check for each if they're divisible by the second factorial-input
        Ï   # In the list we copied, only leave the values at the truthy indices
         P  # And take the product of those
            # (which is output implicitly as result)

1
6-byter ini: LR²ιнP( Coba online! ) Berfungsi untuk setiap test case, kecuali 0.
Mr. Xcoder

Tapi saya kira 0 case bisa diperbaiki paling banyak 2 byte. Jika Anda mencari cara untuk memperbaikinya, Anda dapat mengambilnya :) EDIT: Mungkin LR²ιн0KPselama 8 byte?
Tn. Xcoder

@ Mr.Xcoder Jawaban yang bagus! Bahkan tidak pernah menggunakan uninterleave dengan langkah tertentu. :)
Kevin Cruijssen

0Kseharusnya tidak perlu karena 0!merupakan input yang tidak valid oleh spesifikasi (meskipun sudah termasuk dalam contoh) - Saya telah berkomentar tentang ini.
Jonathan Allan

1
... dan jika 0! ada dalam domain input ݦRXιнPmenghemat satu byte.
Jonathan Allan

4

kode mesin x86-64, 12 byte

Kode mesin yang sama melakukan hal yang sama dalam mode 32-bit, dan untuk bilangan bulat 16-bit dalam mode 16-bit.

Ini adalah fungsi, callable dengan args n=RCX, k=ESI. Nilai pengembalian 32-bit dalam EAX.

Dapat dihubungi dari C dengan konvensi pemanggilan Sistem V x86-64 dengan dummy args untuk memasukkan args yang sebenarnya ke dalam register yang benar. uint32_t factk(int, uint32_t k, int, uint64_t n); Saya tidak bisa hanya menggunakan Windows x64 karena 1-operan mulclobbers RDX, dan kami tidak ingin awalan REX mengakses R8 / R9. ntidak boleh ada sampah di 32 bit tinggi sehingga JRCXZ berfungsi, tetapi selain itu semuanya 32-bit.

Daftar NASM (alamat relatif, kode mesin, sumber)

 1                         factk:
 2 00000000 6A01             push 1
 3 00000002 58               pop rax             ; retval = 1
 4 00000003 E306             jrcxz  .n_zero      ; if (n==0) return
 5                         .loop:                ; do {
 6 00000005 F7E1              mul   ecx            ; retval *= n  (clobbering RDX)
 7 00000007 29F1              sub   ecx, esi       ; n -= k
 8 00000009 77FA              ja   .loop         ; }while(sub didn't wrap or give zero)
 9                         .n_zero:
10 0000000B C3               ret

0xc = 12 byte


Atau 10 byte jika kita tidak perlu menangani n=0case khusus, meninggalkan jrcxz.

Untuk faktorial standar, Anda akan menggunakan loopalih-alih sub / ja untuk menyimpan 2 byte, tetapi sebaliknya kode yang sama persis.


Uji penelepon yang lolos argcsebagai k, dengan nhard-coded.

align 16
global _start
_start:
  mov  esi, [rsp]
;main:
  mov  ecx, 9
  call factk

  mov  esi, eax
  mov  edx, eax
  lea  rdi, [rel print_format]
  xor  eax, eax
extern printf
  call printf
extern exit
  call exit

section .rodata
print_format: db `%#x\t%u\n`

```

3

APL (Dyalog Unicode) , 11 byte SBCS

Fungsi infiks diam-diam anonim. Dibawa nsebagai argumen kanan dan bsebagai argumen kiri.

×/1⌈⊢,⊢-×∘⍳

Cobalah online!

×∘⍳ kalikan bdengan ɩ ntegers 1 sampain

⊢- kurangi itu dari n

⊢, lebih dulu n

1⌈ maks satu dan masing-masing

×/ produk



3

Bahasa Wolfram (Mathematica) , 22 21 byte

1##&@@Range[#,1,-#2]&

Cobalah online!

-1 terima kasih untuk attinat: Times --> 1##&

Penjelasan: gunakan Rangeuntuk membuat daftar nilai {n, n-k, n-2k, n-3k, ...}, berhenti sebelum pergi di bawah 1 (yaitu, berhenti tepat). Kemudian gandakan semua angka dalam daftar ini dengan Times(atau 1##&).


-1 byte dengan 1##&bukannyaTimes
attinat

3

Java 10, 44 byte

f->b->{int r=1;for(;b>0;b-=f)r*=b;return r;}

Mengambil faktorial sebagai input pertama, basis sebagai kedua.

Cobalah online.

Ini di atas tidak berfungsi untuk kasus uji terbesar karena rentang integer terbatas (32-bit). Untuk mengatasinya kita bisa menggunakan BigIntegers, yang kebetulan adalah tepat dua ukuran - 88 79 bytes :

f->b->{var r=f.ONE;for(;b.signum()>0;b=b.subtract(f))r=r.multiply(b);return r;}

-9 byte terima kasih kepada @ OlivierGrégoire .

Cobalah online.

Penjelasan:

f->b->{       // Method with two integer parameters and integer return-type
  int r=1;    //  Result-integer, starting at 1
  for(;b>0;   //  Loop as long as the base is still larger than 0
      b-=f)   //    After every iteration: decrease the base by the factorial
    r*=b;     //   Multiply the result by the base
  return r;}  //  Return the result


@ OlivierGrégoire Np, dan terima kasih! :)
Kevin Cruijssen



2

MathGolf , 7 6 byte

╙╒x%ε*

Cobalah online!

Menemukan cara cerdas untuk menangani 0! tanpa mengubah kasus uji lainnya. Mengambil input sebagai k n(urutan terbalik), yang membantu dengan muncul secara implisit.

Penjelasan

╙        maximum of two elements (pops largest of k and n,
         which is n for every valid case except 0!, where 1 is pushed)
 ╒       range(1,n+1)
  x      reverse int/array/string
   %     slice every k:th element
    ε*   reduce list with multiplication

2

Attache , 21 19 byte

${x<y∨x*$[x-y,y]}

Cobalah online! Implementasi rekursif yang cukup langsung. (Catatan: truepada dasarnya 1, karena dapat digunakan dalam operasi aritmatika sebagai 1.) Ini adalah salah satu dari beberapa program yang saya tulis untuk situs ini di mana menggunakan operator unicode menghemat byte (1, tepatnya).

Alternatif

20 byte: ${x<y or x*$[x-y,y]}

21 byte: Prod@${{_%y=x%y}\1:x}

27 byte: ${x*[`1,$][x>y][x-y,y]∨1}

27 byte: ${If[x>y,x*$[x-y,y],_or 1]}

27 byte: ${x*[`1,$][x>y][x-y,y]or 1}

29 byte: ${If[x>y,x*$[x-y,y],_+not _]}


2

Rust , 92 73 61 byte

fn f(n:i128,k:i128)->i128{if n<=0{return 1}return n*f(n-k,k)}

Saya baru mulai belajar karat, jadi saya yakin ini bisa lebih pendek. Akan diperbarui saat saya belajar. Nilai pengembalian harus i128untuk menghitung tes terakhir.

Sunting: Rekursi lebih pendek.

Cobalah online!

Anda dapat menambahkan tes Anda sendiri, atau mengedit salah satu yang sudah ada.


2

q , 59 57 55 53 byte

{prd 2+(&)1_i=last i:("J"$x(&)not[n])#(!)sum n:"!"=x}

penjelasan:

q)x:"12!!" / let our input be 12!!, assign to x
q)sum n:"!"=x / count "!"s
2i
q)(!)sum n:"!"=x / (!)m -> [0,m)
0 1
q)("J"$x(&)not[n]) / isolate the number in input
12
q)("J"$x(&)not[n])#(!)sum n:"!"=x / x#y means take x items from list y, if x>y, circle around
0 1 0 1 0 1 0 1 0 1 0 1
q)i:("J"$x(&)not[n])#(!)sum n:"!"=x / assign to i
q)i
0 1 0 1 0 1 0 1 0 1 0 1
q)(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / take last elem of i and see which are equal in i
010101010101b
q)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / drop first elem
10101010101b
q)(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / indices of 1b (boolean TRUE)
0 2 4 6 8 10
q)2+(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / add 2 across array
2 4 6 8 10 12
q)prd 2+(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / product across array
46080

di sini juga adalah versi dalam k (logika yang sama), 42 41 byte

{*/2+&1_i=last i:("J"$x@&~:n)#!+/n:"!"=x}

Selamat datang di situs ini! Saya telah menambahkan pemformatan kode pada posting Anda yang dapat dilakukan dengan empat spasi sebelum baris atau dengan melampirkannya dengan backticks tiga kali lipat.
Wheat Wizard

@ SriotchilismO'Zaic terima kasih :-)
coretan

1
Saya sarankan menambahkan penjelasan dan mungkin tautan ke juru bahasa online seperti TIO . Jawaban khusus kode biasanya ditandai sebagai kualitas rendah.
mbomb007

@ mbomb007 menarik. apakah ada bot yang menandai jawaban? apa yang terjadi pada pengiriman berkualitas rendah? saya akan segera memperbarui!
coretan

Ya, ada bot. StackExchange menggunakan bot untuk mencari potensi spam dan jawaban berkualitas rendah. Orang dengan reputasi cukup tinggi dapat melihat Antrean Ulasan. meta.stackexchange.com/a/161391/285610
mbomb007

1

Physica , 22 byte

f=>n;k:n<1||n*f[n-k;k]

Cobalah online!


26 byte

Belajar kembali bagaimana menggunakan "bahasa" saya sendiri \ o / ... Jika saya tahu cara menulis parser 2 tahun yang lalu, ini akan menjadi 20 byte :(

->n;k:GenMul##[n…1]{%%k}

atau

->n;k:GenMul##Range[n;1;k]

Cobalah online!


1

Retina , 66 byte

^0
1
\d+
*!,
+`(!+)(!+),\1$
$1$2,$2,$1
!+$
1
+`(!+),(\d+)
$.($2*$1

Cobalah online! Tautan mencakup test case yang lebih cepat. Nomor maul tanpa tanda seru. Penjelasan:

^0
1

Perbaiki 0!.

\d+
*!,

Konversikan nke unary dan tambahkan pemisah.

+`(!+)(!+),\1$
$1$2,$2,$1

Berulang kali kurangi kdari nsementara n>k, dan mengumpulkan hasil.

!+$
1

Ganti kdengan 1(dalam desimal).

+`(!+),(\d+)
$.($2*$1

Kalikan dengan masing-masing nilai perantara secara bergantian, konversikan ke desimal.




1

Keempat (gforth) , 50 byte

: f 1 1 2over / 1+ 0 do 2over i * - 1 max * loop ;

Cobalah online!

Penjelasan Kode

: f                \ start a new word definition
  1 1              \ add placeholder and accumulator to stack
  2over / 1+       \ get the number of times to run the loop (num/factorial + 1)
  0 do             \ start loop from 0 to num/factorial
    2over          \ copy num and factorial to the top of the stack
    i * -          \ get the current number to multiply by (num - factorial * i)
    1 max          \ make sure it can't be 0 or negative [set to 1 if it is]
    *              \ multiply accumulator by result
  loop             \ end loop
;                  \ end the word definition           



1

Gaia , 6 byte

…)¦v%Π

Cobalah online!

Mengambil input sebagai n, ksehingga masukan dari 3 4akan 3!!!!.

…	 push [0...n-1], or [] if n == 0
 )¦	 increment each value (does nothing if [])
   v	 reverse list
    %	 take every k'th element
     Π	 product; product([]) = 1.
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.