Ripetuto! Fattoriali!


34

Da non confondere con Trova il fattoriale!

introduzione

Il fattoriale di un numero intero npuò essere calcolato da

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

Questo è relativamente facile e niente di nuovo. Tuttavia, i fattoriali possono essere estesi a doppi fattoriali , in modo tale che

n!!=n×(n2)×(n4)×(...)×4×2
per i numeri pari e
n!!=n×(n2)×(n4)×(...)×3×1
per i numeri dispari. Ma non siamo limitati ai doppi fattoriali. Ad esempio
n!!!=n×(n3)×(n6)×(...)×6×3
o
n!!!=n×(n3)×(n6)×(...)×5×2
o
n!!!=n×(n3)×(n6)×(...)×4×1
in funzione del valore iniziale.

In sintesi:

n!(k)={1if n=0nif 0<nkn((nk)!(k))if n>k
dove
n!(k)=n!!k
Oppure, in parole povere :Sottrarre ripetutamente il conteggio fattoriale dal numero di base e moltiplicare tutti gli interi positivi risultanti.

La sfida

Scrivi una funzione che calcolerà qualsiasi tipo di fattoriale ripetuto per qualsiasi numero intero non negativo.

Ingresso

O

  • Una stringa contenente un numero intero di base dieci non negativo, seguito da 1 o più punti esclamativi. Ad esempio "6!"o "9!!"o "40!!!!!!!!!!!!!!!!!!!!".

o

  • Gli stessi valori rappresentati da due numeri interi: un valore di base non negativo e un valore positivo che rappresenta il conteggio fattoriale. Questo può essere fatto in qualsiasi formato dalle regole I / O predefinite.

Produzione

Il risultato di detto calcolo.

Commenti sulla sfida

  • 0!è uguale 1per definizione. Il tuo codice deve tener conto di questo.
  • Il conteggio fattoriale è limitata da
    0<factorial countbase value
    fuori di questo intervallo, si è liberi di uscita qualunque. A parte 0!, che è l'unica eccezione a questa regola.

Esempi

Input                              Output

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

Provalo con un'implementazione Python non golfata: provalo online!

Revisione generale


6
L'elenco degli esempi 0!ma le osservazioni della sfida indicano che il conteggio fattoriale sarà inferiore o uguale al valore di base.
Jonathan Allan,

1
Non 3 !!! essere zero? n * (n-3) = 3 * (3-3) = 0.
ouflak

2
@ouflak Se funziona come 1 !, non proprio. È più simile a 1! = 1. 2 !! = 2. 3 !!! = 3. Non c'è calcolo, perché sei alla fine della ricorsività. No 0 nei prodotti oppure ogni singolo fattoriale scenderebbe a 0 alla fine.
V. Courtois,

4
3!!!!!!!non dovrebbe essere indefinito, dovrebbe solo dare la risposta 3. È lo stesso di 1!!=1(non definito). Inoltre la tua specifica di input dice che ce ne sarà sempre almeno una !, quindi il primo esempio 3non si adatta alla specifica.
Greg Martin,

3
@ FabianRöling: Ma non è questo. Non sta (3!)!invece rimuovendo i termini da un fattoriale. È un nome fuorviante; Sono arrivato supponendo che avrebbe applicato ripetutamente la funzione Fattoriale in una catena e ho dovuto leggere attentamente per vedere cosa fosse effettivamente. Fortunatamente la domanda lo spiega chiaramente. Un nome migliore potrebbe essere falcata fattoriale o step fattoriale o qualcosa del genere.
Peter Cordes,

Risposte:



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

Provalo online!

Tradotto in pseudocodice:

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

Nota: ArnoldC ha un solo tipo di dati: intero con segno a 16 bit. Quindi non posso testare il 420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!caso.


Sono solo curioso del tuo codice psued. A cosa serve la variabile 'c'?
ouflak,

@ouflak Ho modificato la mia risposta un paio di volte e l'ho dimenticata. La cvariabile memorizza effettivamente il valore del confronto tra ne 0.
Charlie,

+1 e l'ho preso in prestito (meno la 'c') per la mia risposta LUA.
ouflak,

12

Gelatina , 4 byte

RṚmP

Provalo online!

nkn,,1RṚmkthn,nk,n2k,,nn/kkP


Funziona bene e alla fine è così semplice. Non conosco affatto Jelly ma almeno sembra buono :)
V. Courtois,

1
nkn,,1RṚmkthn,nk,n2k,,nn/kkP

Ah, grazie mille. Un giorno potrei voler giocare a golf in questa lingua, quindi dovrò imparare quelle monadi, diade, ecc.
V. Courtois,

Alternative che assomiglia CJam: r1mP.
Erik the Outgolfer,

1
@KyeWShi Jelly ha una sua codepage , quindi ognuno dei 256 caratteri che contiene è codificato come 1 byte.
Mr. Xcoder

8

APL (Dyalog Extended) , 7 byte SBCS

Funzione prefisso tacito anonimo. Prende [n,b]come argomento.

×/-\…1¨

Provalo online!

 uno per ogni elemento dell'argomento; [1,1]

-\ differenza cumulativa; [n,n-b]

 intervallo usando il secondo elemento dell'argomento sinistro come indicatore del passo, ad esempio [9,7]continua con5

×/ Prodotto


7

Haskell , 21 byte

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

Provalo online!

Combinando la funzione di prodotto integrata con l'enumerazione a intervalli progressivi, ciò che potrei codificare in modo ricorsivo (anche con il salvataggio di flawr di un byte).

22 byte

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

Provalo online!

Ecco una soluzione che prende input in formato stringa come 9!!, che penso sia più interessante.

42 byte

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

Provalo online!


2
Penso che potresti abbreviare la soluzione ricorsiva an%a|n<1=1|m<-n-a=n*m%a
flawr


5

JavaScript (ES6), 21 byte

Accetta input come (k)(n).

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

Provalo online!

O 24 byte per supportare BigInts.


JavaScript (ES6), 55 byte

Prende l'input come stringa, utilizzando il formato descritto nella sfida.

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

Provalo online!


5

Spazio bianco , 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]

Lettere S(spazio), T(scheda) e N(nuova riga) aggiunti solo come evidenziazione.
[..._some_action]aggiunto solo come spiegazione.

Provalo online (solo con spazi non elaborati, schede e nuove righe).

Spiegazione in pseudo-codice:

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>*}

Provalo online!

Blocco codice anonimo che restituisce il prodotto dell'intervallo a partire dal primo input, diminuendo del secondo fino a quando non è inferiore 1, escluso l'ultimo numero. Questo funziona per 0, poiché il caso base di una riduzione per prodotto è 1, quindi l'output è 1.


4

05AB1E , 10 8 7 byte

ݦRIιнP

Input come due input separati: primo input essendo base; secondo input essere factorial.

Provalo online o verifica tutti i casi di test .

-2 byte grazie a @ Mr.Xcoder .
-1 byte grazie a @JonathanAllan .

Spiegazione:

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

Risposta originale di 10 byte :

L0KD¤-IÖÏP

Input come due input separati: primo input essendo base; secondo input essere factorial.

Provalo online o verifica tutti i casi di test .

Spiegazione:

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
Questo 6-byte: LR²ιнP( Provalo online! ) Funziona per ogni caso di test, tranne per 0.
Mr. Xcoder

Ma immagino che il caso 0 possa essere risolto al massimo in 2 byte. Se trovi un modo per risolverlo, potresti prenderlo :) MODIFICA: Forse LR²ιн0KPper 8 byte?
Mr. Xcoder,

@ Mr.Xcoder Bella risposta! Non ho nemmeno mai usato uninterleave con un determinato passaggio. :)
Kevin Cruijssen il

0Kdovrebbe essere superfluo in quanto 0!è un input non valido dalla specifica (anche se è stato incluso negli esempi) - Ho commentato questo.
Jonathan Allan,

1
... e se si 0! trova nel dominio di input ݦRXιнPsalva un byte.
Jonathan Allan,

4

codice macchina x86-64, 12 byte

Lo stesso codice macchina fa la stessa cosa in modalità a 32 bit e per numeri interi a 16 bit in modalità a 16 bit.

Questa è una funzione, richiamabile con args n=RCX, k=ESI. Valore di ritorno a 32 bit in EAX.

Callable da C con la convenzione di chiamata System V x86-64 con arg fittizi per ottenere i veri arg nei registri giusti. uint32_t factk(int, uint32_t k, int, uint64_t n); Non potevo semplicemente usare Windows x64 perché mulClobber RDX a 1 operando , e non vogliamo che i prefissi REX accedano a R8 / R9. nnon deve contenere alcun tipo di immondizia negli alti 32 bit, quindi JRCXZ funziona, ma a parte questo è tutto a 32 bit.

Elenco NASM (indirizzo relativo, codice macchina, sorgente)

 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


O 10 byte se non avessimo bisogno di gestire il n=0caso speciale, tralasciando il jrcxz.

Per fattoriale standard useresti loopinvece di sub / ja per salvare 2 byte, ma altrimenti lo stesso codice esatto.


Prova il chiamante che passa argccome k, con nhardcoded.

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) , SBCS da 11 byte

Funzione anonimo di tacita infissione. Prende ncome argomento giusto e bcome argomento sinistro.

×/1⌈⊢,⊢-×∘⍳

Provalo online!

×∘⍳ moltiplicare bper ɩ ntegers da 1 an

⊢- sottrailo da n

⊢, anteporre n

1⌈ massimo di uno e ciascuno di quelli

×/ Prodotto



3

Wolfram Language (Mathematica) , 22 21 byte

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

Provalo online!

-1 grazie ad attinat: Times --> 1##&

Spiegazione: usare Rangeper fare un elenco dei valori {n, n-k, n-2k, n-3k, ...}, fermandosi prima di scendere al di sotto di 1 (cioè fermandosi proprio nel modo giusto). Quindi moltiplicare tutti i numeri in questo elenco con Times(o 1##&).


-1 byte con 1##&al posto diTimes
attinat

3

Java 10, 44 byte

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

Prende il fattoriale come primo input, base come secondo.

Provalo online.

Questo sopra non funziona per il caso di test più grande a causa dell'intervallo limitato (32 bit). Per risolvere questo problema possiamo usare BigIntegers, che per coincidenza è esattamente il doppio della dimensione - 88 79 byte :

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

-9 byte grazie a @ OlivierGrégoire .

Provalo online.

Spiegazione:

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, e grazie! :)
Kevin Cruijssen



2

MathGolf , 7 6 byte

╙╒x%ε*

Provalo online!

Trovato un modo intelligente per gestire 0! senza cambiare gli altri casi di test. Prende l'input come k n(ordine inverso), che aiuta con lo scopping implicito.

Spiegazione

╙        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]}

Provalo online! Implementazione ricorsiva piuttosto diretta. (Nota: trueè essenzialmente 1, in quanto può essere utilizzato in operazioni aritmetiche come 1.) Questo è uno dei pochi programmi che ho scritto per questo sito in cui l'utilizzo di un operatore Unicode consente di risparmiare byte (1, per essere precisi).

alternative

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

Ruggine , 92 73 61 byte

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

Ho appena iniziato a studiare la ruggine, quindi sono sicuro che questo può essere più breve. Aggiornerò mentre imparo. Il valore restituito dovrebbe essere i128per calcolare l'ultimo test.

Modifica: la ricorsione è più breve.

Provalo online!

Puoi aggiungere il tuo test o modificarne uno già esistente.


2

q , 59 57 55 53 byte

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

spiegazione:

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

qui c'è anche una versione in k (stessa logica), 42 41 byte

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

Benvenuti nel sito! Ho aggiunto la formattazione del codice al tuo post che può essere fatto con quattro spazi prima della riga o racchiudendolo con tre backtick.
Wheat Wizard

@ SriotchilismO'Zaic ringrazia :-)
scarabocchio il

1
Consiglio di aggiungere una spiegazione e forse un link a un interprete online come TIO . Le risposte di solo codice vengono generalmente contrassegnate automaticamente come di bassa qualità.
mbomb007,

@ mbomb007 interessante. c'è un bot che segnala le risposte? cosa succede agli invii di bassa qualità? aggiornerò presto!
scarabocchio

Sì, c'è un bot. StackExchange utilizza i bot per cercare potenziali spam e risposte di bassa qualità. Le persone con una reputazione abbastanza elevata possono visualizzare la coda di revisione. meta.stackexchange.com/a/161391/285610
mbomb007

1

Physica , 22 byte

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

Provalo online!


26 byte

Riapprendimento di come usare la mia "lingua" \ o / ... Se avessi saputo scrivere un parser 2 anni fa, sarebbero stati 20 byte :(

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

o

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

Provalo online!


1

Retina , 66 byte

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

Provalo online! Il collegamento include casi di test più veloci. Numeri di Mauls senza punti esclamativi. Spiegazione:

^0
1

Risolvi 0!.

\d+
*!,

Converti nin unario e aggiungi un separatore.

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

Sottrai ripetutamente kda nwhile n>ke raccogli i risultati.

!+$
1

Sostituisci kcon 1(in decimale).

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

Moltiplicare per ciascun valore intermedio a sua volta, convertendolo in decimale.




1

Forth (gforth) , 50 byte

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

Provalo online!

Spiegazione del codice

: 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%Π

Provalo online!

Accetta input come n, kquindi input di 3 4sarebbe 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.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.