Powtarzający się! Czynniki!


34

Nie mylić z Znajdź silnię!

Wprowadzenie

Silnia liczby całkowitej nmożna obliczyć przez

n!=n×(n-1)×(n-2))×(...)×2)×1

Jest to stosunkowo łatwe i nic nowego. Jednak silnie można rozszerzyć do podwójnych silni , tak że

n!!=n×(n-2))×(n-4)×(...)×4×2)
o parzystych numerach, a
n!!=n×(n-2))×(n-4)×(...)×3)×1
dla liczb nieparzystych. Ale nie ograniczamy się do podwójnych silni. Na przykład
n!!!=n×(n-3))×(n-6)×(...)×6×3)
i
n!!!=n×(n-3))×(n-6)×(...)×5×2)
lub
n!!!=n×(n-3))×(n-6)×(...)×4×1
w zależności od wartości wyjściowej.

Podsumowując:

n!(k)={1Jeśli n=0nJeśli 0<nkn((n-k)!(k))Jeśli n>k
gdzie
n!(k)=n!!k
Lub, w prostym języku angielskim:Kilkakrotnie odejmij liczbę czynnikową od liczby podstawowej i pomnóż wszystkie uzyskane liczby całkowite dodatnie.

Wyzwanie

Napisz funkcję, która obliczy każdy rodzaj powtarzanej silni dla dowolnej nieujemnej liczby całkowitej.

Wkład

Zarówno

  • Ciąg zawierający nieujemną liczbę całkowitą dziesiętną, po której następuje 1 lub więcej wykrzykników. Np "6!"lub "9!!"lub "40!!!!!!!!!!!!!!!!!!!!".

lub

  • Te same wartości reprezentowane przez dwie liczby całkowite: jedną nieujemną wartość bazową i jedną wartość dodatnią reprezentującą liczbę czynnikową. Można to zrobić zgodnie z dowolnym formatem z domyślnych reguł we / wy.

Wydajność

Wynik wspomnianych obliczeń.

Uwagi na temat wyzwania

  • 0!równa się 1z definicji. Twój kod musi to uwzględniać.
  • Silnia liczba jest ograniczona
    0<fazadotorjazal doountbzasmi przeciwkozalumi
    poza tego zakresu, można w nich produkcji, co. Poza tym 0!, co jest jedynym wyjątkiem od tej reguły.

Przykłady

Input                              Output

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

Wypróbuj z nieogoloną implementacją Pythona: Wypróbuj online!

Uwagi ogólne


6
Lista przykładów, 0!ale uwagi dotyczące wyzwania mówią, że liczba czynnikowa będzie mniejsza lub równa wartości podstawowej.
Jonathan Allan

1
Nie 3! być zero? n * (n-3) = 3 * (3-3) = 0.
ouflak

2
@ouflak Jeśli to działa jak 1 !, nie bardzo. To bardziej jak 1! = 1. 2 !! = 2,3 !!! = 3. Nie ma obliczeń, ponieważ jesteś na końcu rekurencyjności. Brak 0 w produktach, bo w końcu każdy czynnik będzie spadał do 0.
V. Courtois,

4
3!!!!!!!nie powinno być niezdefiniowane - powinno po prostu dać odpowiedź 3. Jest taki sam jak 1!!=1(nieokreślony). Również twoja specyfikacja wejściowa mówi, że zawsze będzie co najmniej jeden !, więc pierwszy przykład 3nie pasuje do specyfikacji.
Greg Martin

3
@ FabianRöling: Ale to nie to. To nie (3!)!zamiast to usuwając terminy z silni. To mylące imię; Przyszedłem, zakładając, że będzie ona wielokrotnie stosować funkcję czynnikową w łańcuchu i musiałem uważnie przeczytać, aby zobaczyć, co to właściwie jest. Na szczęście pytanie wyjaśnia to jasno. Lepszą nazwą może być silnia krokowa, silnia krokowa lub coś takiego.
Peter Cordes,

Odpowiedzi:



13

ArnoldC , 702 698 634 bajtów

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

Wypróbuj online!

Przetłumaczone na pseudokod:

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

Uwaga: ArnoldC ma tylko jeden typ danych: 16-bitowa liczba całkowita ze znakiem. Dlatego nie mogę przetestować 420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!sprawy.


Po prostu ciekawy twojego kodu psuedocode. Do czego służy zmienna „c”?
ouflak

@ouflak Kilka razy zredagowałem swoją odpowiedź i zapomniałem. cZmienna faktycznie przechowuje wartość porównania pomiędzy ni 0.
Charlie

+1 i pożyczyłem go (minus „c”) dla mojej odpowiedzi LUA.
ouflak

12

Galaretka , 4 bajty

RṚmP

Wypróbuj online!

nkn,,1RṚmkth element tego zakresu (tzw n,n-k,n-2)k,,n-n/kk), a na koniec mnoży je za pomocą P.


Działa dobrze, a na koniec tak proste. W ogóle nie znam galaretki, ale przynajmniej wygląda dobrze :)
V. Courtois

1
@ V.Courtois Podane n i k, najpierw generuje zakres n,,1 (with RṚ), then with m it keeps every kth element of this range (so n,nk,n2k,,nn/kk), and finally multiplies them using P. Just the straightforward approach. Edit: I added this explanation in the answer.
Mr. Xcoder

Hah thank you very much. One day I might want to golf in this language so I'll have to learn those monads, dyads etc.
V. Courtois

Alternative that looks like CJam: r1mP.
Erik the Outgolfer

1
@KyeWShi Jelly has its own codepage, so each of the 256 characters it contains is encoded as 1 byte.
Mr. Xcoder

8

APL (Dyalog Extended), 7 bytesSBCS

Anonymous tacit prefix function. Takes [n,b] as argument.

×/-\…1¨

Try it online!

 one for each element of the argument; [1,1]

-\ cumulative difference; [n,n-b]

 range using second element of left argument as indicator of step, e.g. [9,7] continues with 5

×/ product


7

Haskell, 21 bytes

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

Try it online!

Combining the built-in product function with stepped range enumeration beats what I could code up recursively (even with flawr saving a byte).

22 bytes

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

Try it online!

Here's a solution taking input in string format like 9!!, which I think is more interesting.

42 bytes

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

Try it online!


2
I think you could shorten the recursive solution to n%a|n<1=1|m<-n-a=n*m%a
flawr


5

JavaScript (ES6), 21 bajtów

Pobiera dane wejściowe jako (k)(n).

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

Wypróbuj online!

Lub 24 bajty do obsługi BigInts.


JavaScript (ES6), 55 bajtów

Pobiera dane wejściowe jako ciąg znaków, używając formatu opisanego w wyzwaniu.

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

Wypróbuj online!


5

Biała spacja , 91 bajtów

[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]

Litery S(spacja), T(tab) i N(nowa linia) dodane tylko jako wyróżnienia.
[..._some_action]dodano tylko jako wyjaśnienie.

Wypróbuj online (tylko z surowymi spacjami, tabulatorami i nowymi wierszami).

Objaśnienie w pseudo-kodzie:

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 bajtów

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

Wypróbuj online!

Anonymous codeblock that returns the product of the range starting from the first input, decreasing by the second until it is below 1, excluding the last number. This works for 0, since the base case of a the reduce by product is 1, so the output is 1.


4

05AB1E , 10 8 7 bajtów

ݦRIιнP

Wejście jako dwa oddzielne wejścia: pierwsze wejście jest base; drugie wejście jest factorial.

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

-2 bajty dzięki @ Mr.Xcoder .
-1 bajt dzięki @JonathanAllan .

Wyjaśnienie:

Ý        # 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)

Oryginalna odpowiedź 10 bajtów :

L0KD¤-IÖÏP

Wejście jako dwa oddzielne wejścia: pierwsze wejście jest base; drugie wejście jest factorial.

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

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
Ten 6-bajtowy: LR²ιнP( Wypróbuj online! ) Działa dla każdego przypadku testowego, z wyjątkiem 0.
Pan Xcoder

Ale wydaje mi się, że 0 przypadków można naprawić maksymalnie w 2 bajtach. Jeśli wymyślisz sposób, aby to naprawić, możesz wziąć to :) EDYCJA: Może LR²ιн0KPna 8 bajtów?
Pan Xcoder,

@ Mr.Xcoder Ładna odpowiedź! Nigdy nie używał rozplatania z danym krokiem. :)
Kevin Cruijssen

0Kpowinno być niepotrzebne, ponieważ 0!jest to nieprawidłowe wejście specyfikacji (nawet jeśli zostało to uwzględnione w przykładach) - skomentowałem to.
Jonathan Allan

1
... a jeśli 0! jest w domenie wejściowej ݦRXιнPzapisuje bajt.
Jonathan Allan

4

kod maszynowy x86-64, 12 bajtów

Ten sam kod maszynowy robi to samo w trybie 32-bitowym, a dla 16-bitowych liczb całkowitych w trybie 16-bitowym.

Jest to funkcja, wymagalne z args n=RCX, k=ESI. 32-bitowa wartość zwracana w EAX.

Można wywoływać z C za pomocą konwencji wywoływania Systemu x86-64 System V z fałszywymi argumentami, aby wprowadzić prawdziwe argumenty do odpowiednich rejestrów. uint32_t factk(int, uint32_t k, int, uint64_t n); Nie mogłem po prostu użyć systemu Windows x64, ponieważ 1-operand mulblokuje RDX i nie chcemy, aby prefiksy REX miały dostęp do R8 / R9. nnie może zawierać śmieci w wysokich 32 bitach, więc JRCXZ działa, ale poza tym wszystko jest 32-bitowe.

Lista NASM (adres względny, kod maszynowy, źródło)

 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 bajtów


Lub 10 bajtów, jeśli nie musieliśmy obsługiwać n=0specjalnego przypadku, pomijając jrcxz.

Dla standardowego silnia użyłbyś loopzamiast sub / ja do zapisania 2 bajtów, ale poza tym dokładnie ten sam kod.


Testuj dzwoniącego, który przechodzi argcjako kz nzakodowanym na stałe.

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 bajtów SBCS

Anonimowa funkcja ukrytej poprawki. Przyjmuje njako prawy argument i blewy argument.

×/1⌈⊢,⊢-×∘⍳

Wypróbuj online!

×∘⍳ pomnóż bprzez ɩ ntegers od 1 don

⊢- odejmij to od n

⊢, prepend n

1⌈ maksymalnie jeden i każdy z nich

×/ produkt



3

Wolfram Language (Mathematica) , 22 21 bajtów

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

Wypróbuj online!

-1 dzięki attinat: Times --> 1##&

Objaśnienie: użyj, Rangeaby utworzyć listę wartości {n, n-k, n-2k, n-3k, ...}, zatrzymując się przed zejściem poniżej 1 (tj. Zatrzymując się dokładnie w prawo). Następnie pomnóż wszystkie liczby na tej liście przez Times(lub 1##&).


-1 bajt z 1##&zamiastTimes
attinat

3

Java 10, 44 bajty

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

Pobiera silnię jako pierwsze wejście, podstawa jako drugie.

Wypróbuj online.

Powyższe nie działa w przypadku największego przypadku testowego ze względu na ograniczony zakres liczb całkowitych (32 bity). Aby to naprawić, możemy użyć BigIntegers, który przypadkowo jest dokładnie dwa razy większy - 88 79 bajtów :

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

-9 bajtów dzięki @ OlivierGrégoire .

Wypróbuj online.

Wyjaśnienie:

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, i dzięki! :)
Kevin Cruijssen



2

MathGolf , 7 6 bajtów

╙╒x%ε*

Wypróbuj online!

Znaleziono sprytny sposób na obsługę 0! bez zmiany innych przypadków testowych. Pobiera dane wejściowe jakok n (odwrotna kolejność), co pomaga w domyślnym poppingu.

Wyjaśnienie

╙        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 bajtów

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

Wypróbuj online! Dość bezpośrednie wdrożenie rekurencyjne. (Uwaga: truejest zasadniczo 1, ponieważ można go używać w operacjach arytmetycznych jako 1.) Jest to jeden z niewielu programów, które napisałem dla tej witryny, w których użycie operatora Unicode zapisuje bajty (a dokładniej 1).

Alternatywy

20 bajtów: ${x<y or x*$[x-y,y]}

21 bajtów: Prod@${{_%y=x%y}\1:x}

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

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

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

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


2

Rdza , 92 73 61 bajtów

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

Właśnie zaczynam uczyć się rdzy, więc jestem pewien, że może być krótsza. Będzie się aktualizować w miarę nauki. Wartość zwracana powinna wynosići128 w celu obliczenia ostatniego testu.

Edycja: Rekursja jest krótsza.

Wypróbuj online!

Możesz dodać własny test lub edytować jeden z już istniejących.


2

Q , 59 57 55 53 bajtów

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

wyjaśnienie:

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

tutaj jest także wersja w k (ta sama logika), 42 41 bajtów

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

Witamy na stronie! Dodałem formatowanie kodu do twojego postu, które można zrobić za pomocą czterech spacji przed linią lub poprzez włączenie potrójnego backsticka.
Wheat Wizard

@ SriotchilismO'Zaic dzięki :-)
bazgranina

1
Polecam dodanie wyjaśnienia i może linku do tłumacza internetowego, takiego jak TIO . Odpowiedzi zawierające tylko kod są zwykle automatycznie oznaczane jako niskiej jakości.
mbomb007

@ mbomb007 ciekawe. czy jest jakiś bot oznaczający odpowiedzi? co dzieje się z materiałami niskiej jakości? wkrótce zaktualizuję!
bazgroły

Tak, jest bot. StackExchange używa botów do wyszukiwania potencjalnego spamu i odpowiedzi niskiej jakości. Osoby o odpowiednio wysokiej reputacji mogą przeglądać Kolejkę recenzji.meta.stackexchange.com/a/161391/285610
mbomb007

1

Physica , 22 bajty

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

Wypróbuj online!


26 bajtów

Ponowne uczenie się, jak używać własnego „języka” \ o / ... Gdybym wiedział, jak napisać parser 2 lata temu, byłoby to 20 bajtów :(

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

lub

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

Wypróbuj online!


1

Siatkówka , 66 bajtów

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

Wypróbuj online!Link zawiera szybsze przypadki testowe. Liczby Maulsa bez wykrzykników. Wyjaśnienie:

^0
1

Naprawić 0! .

\d+
*!,

Konwertować n na unary i dodaj separator.

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

Wielokrotnie odejmuj kodn czasu n>ki zbieraj wyniki.

!+$
1

wymienić kz1 (dziesiętnie).

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

Pomnóż kolejno każdą wartość pośrednią, przeliczając na dziesiętne.




1

Dalej (gforth) , 50 bajtów

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

Wypróbuj online!

Objaśnienie kodu

: 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 bajtów

…)¦v%Π

Wypróbuj online!

Pobiera dane wejściowe jako n, kwięc dane wejściowe 3 4byłyby 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.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.