Ultima cifra diversa da zero di n!


22

Dato un numero intero 1 ≤ N ≤ 1.000.000 come input, emette l'ultima cifra diversa da zero di N! , Dove ! è il fattoriale (il prodotto di tutti i numeri da 1 a N , incluso). Questa è la sequenza OEIS A008904 .

Il programma deve terminare entro 10 secondi su una macchina ragionevole per qualsiasi input valido.

Casi test

1 => 1
2 => 2
3 => 6
4 => 4
5 => 2
6 => 2
7 => 4
8 => 2
9 => 8
10 => 8
100 => 4
1000 => 2
10000 => 8
100000 => 6
1000000 => 4

Questo è un quindi vince il codice più corto in byte!


Singola funzione o programma completo?
Joey,

@joey No, sono solo casi di test. Ingresso singolo, uscita singola.
fR0DDY,

@joey Programma completo.
fR0DDY,

1
Il requisito per un programma completo è scoraggiato ...
Erik the Outgolfer,

2
@EriktheOutgolfer è di ~ 7 anni fa, quindi non credo che sia stato determinato in quel momento
NoOneIsHere

Risposte:


8

Rubino - 63 caratteri

f=->n{n<2?1:6*[1,1,2,6,4,4,4,8,4,6][n%10]*3**(n/5%4)*f[n/5]%10}

Fonte: http://oeis.org/A008904

Gestisce f fino a mille cifre in meno di un secondo.

Test

irb(main):014:0> for n in 2..6
irb(main):015:1> puts f[10**n]
irb(main):016:1> end
4
2
8
6
4

11

Mathematica, 45 36 byte

Last@Select[IntegerDigits[#!],#>0&]&

Molto leggibile per una risposta vincente. :) (Ancora una volta, non c'è ancora nessun invio a GolfScript & Co.)

Questo gestisce input 1.000.000 in circa 5 secondi sulla mia macchina.


1
Mathematica è praticamente il linguaggio perfetto per questa domanda.
Michael Stern,

4

Python - 75

n=input()
g=1
while n:
 g*=n
 while g%10<1:g/=10
 g%=10**9
 n-=1
print g%10

3

PARI / GP - 27 byte

Questo scambia la velocità per dimensioni - il testcase impiega molto tempo (~ 6 secondi).

n->n!/10^valuation(n!,5)%10

Questa versione è molto più veloce (~ 15 microsecondi) ma richiede 81 byte:

n->r=1;while(n,r*=Mod(4,10)^(n\10%2)*[1,2,6,4,2,2,4,2,8][max(n%10,1)];n\=5);lift(r)

È possibile utilizzare questo codice (non golfato) per testare:

[%(10^n) | n <- [1..6]]

2

Windows PowerShell, 53 56 59 60 63 73 90

($a=1).."$input"|%{$a="$($a*$_)".trim('0')%1e7}
$a%10

Gli appunti:

  • Richiede più di un minuto per un numero vicino a 100.000. Tuttavia, la rimozione di zero alla fine richiede una conversione in stringa, l'esecuzione dei calcoli richiede un numero, quindi le conversioni sono inevitabili in ogni caso.

Storia:

  • 08/02/2011 10:31 (90) - Primo tentativo.
  • 2011-02-08 10:33 (73) - Il modulo è più corto di affettare e unire.
  • 2011-02-08 10:34 (63) - Trim non necessario.
  • 2011-02-08 10:37 (60) - Cast non necessario a un numero. Modulus lo fa già bene, già.
  • 08/02/2011 10:40 (59) - Alcuni inline.
  • 08/02/2011 11:00 (56) - Cosa ho detto prima sul modulo più corto? Si applica anche all'output.
  • 2011-02-08 11:01 (53) - Il casting $inputsu una stringa è sufficiente; il cast a intviene applicato implicitamente.

2

Perl, 53 58 61 personaggi

Tutto lo spazio bianco può essere rimosso, ma l'ho lasciato per "leggibilità". Nota: non usare una formula esplicita sciocca da Sloane.

sub f {
    $_ = $1 * ++$n || 1, /(.{1,7}?)0*$/ while $n < $_[0];
    $1 % 10
}

Calcola f (10 ^ 6) in 8,7 secondi sulla mia macchina.

Aggiornamento : OP voleva che fosse un intero programma:

$_ = $1 * ++$n || 1, /(.{1,7}?)0*$/ while $n < $ARGV[0];
print $1 % 10

Questo lo rende 55 caratteri.


2

CJam - 28

1ri{I)*_AbW%{}#A\#/1e7%}fIA%

Puoi provarlo su http://cjam.aditsu.net/ per valori fino a 10000 o giù di lì; per numeri più grandi dovresti usare l' interprete java . 1000000 funziona in circa 3 secondi sul mio laptop.

Spiegazione:

Sfortunatamente la soluzione semplice è troppo lenta, quindi mantengo solo le ultime 7 cifre (prima degli zeri finali) dopo ogni moltiplicazione.

1           push 1 on the stack
ri          read a token and convert to integer
{           loop (for I from 0 to N - 1)
    I)      push I and increment
    *       multiply with the previous value (initially 1)
    _Ab     duplicate and convert to array of digits
    W%      reverse array
    {}#     find the position of the first non-zero digit
    A\#     raise 10 to that power
    /       divide, thus removing all trailing zeros
    1e7%    keep the remainder modulo 10000000
}fI         end for loop
A%          get the last digit

Nota: questa lingua è molto più recente della domanda.



2

05AB1E , 4 byte

!0м¤

Provalo online!

Spiegazione

!0    # Push the factorial of the input and 0
  м   # Remove the occurences of 0 in the factorial
   ¤  # Push the last element, implicit display

1
La versione TIO è scaduta (anni '60) sull'ultimo caso di test: come è stata ottenuta entro 10 secondi su una "macchina ragionevole"?
Toby Speight,

2

Gelatina , 4 byte

!Ṛȯ/

Provalo online!

Spiegazione

Usa il fatto che quando (invertire un elenco; non vettorializzare) viene applicato a un numero intero, prende automaticamenteD (cifre) per primo.

Con l'ingresso 8:

!Ṛȯ/
!     Factorial: 8! = 40320
 Ṛ    Reverse: [0,2,3,0,4]
   /  Reduce by...
  ȯ   ...logical OR: ((((0ȯ2)ȯ3)ȯ0)ȯ4) = first truthy element = 2

Non credo che esista un "primo elemento di verità" a un byte (che ȯ/funge da) ma se esiste, questo può essere abbreviato in tre byte in totale.


2

Java (OpenJDK 8) , 62 byte

n->{long f=n;for(;n>1||f%10==0;)f=n>1?f*--n:f/10;return f%10;}

Provalo online!

Simile a @Kevin Cruijssen ma salva 5 byte combinando i loop.


Benvenuti in PPCG! Bel primo post! Spero che rimani in giro!
Rɪᴋᴇʀ

Benvenuti in PPCG! Sono d'accordo con @Riker, ottimo primo post. Ben fatto giocando a golf il mio codice combinando i loop. Puoi golf 1 byte in più nella tua risposta corrente sostituendo ||con |, e un byte aggiuntivo sostituendo ==0con <1. Goditi la permanenza!
Kevin Cruijssen,

2

C, 150 140 135 byte

r,d;f(k,x){r=x<5?3:f(k+1,x/5);return(d=x%5)?r*"33436"[d]*(1<<d*k%4)%5:r;}main(int c,char**v){c=atoi(*++v);printf("%d",c<2?1:2*f(0,c));}

Questa è la versione per sistemi ASCII; sostituire la stringa 33436con11214 per un sistema EBCDIC o con \1\1\2\1\4per un programma portatile.

Le soluzioni C sono un po 'ostacolate dall'obbligo di fornire un programma completo; tuttavia, questo risponde completamente alla domanda.

Provalo online (richiede Javascript):

Spiegazione

Si basa sull'algoritmo descritto nella cifra non zero meno significativa di n! , si voltò in modo da ricorrere per trovare la massima potenza di cinque e fare il calcolo all'uscita. Le tabelle delle costanti erano troppo grandi, quindi le ho ridotte trovando una relazione tra il residuo precedente r, la cifra corrente de la profondità di ricorsione k:

     0    1       2       3    4  =d
  0  0  3×2^k  1×2^2k  3×2^3k  2
  1  1  1×2^k  2×2^2k  1×2^3k  4
r 2  2  2×2^k  4×2^2k  2×2^3k  3
  3  3  3×2^k  3×2^2k  3×2^3k  2
  4  4  4×2^k  4×2^2k  4×2^3k  1

Per r>0, questo viene risolto in un costante volte rvolte 2^dk(mod 5); le costanti sono in a[]basso (indicate nel codice golf). Osserviamo anche che (2^4)%5è 1, quindi possiamo ridurre l'esponente per evitare di traboccare il range di int.

const int a[] = { 1, 1, 2, 1, 4 };
int f(int k, int x){
    int r = x<5 ? 3 : f(k+1,x/5); /* residue - from recursing to higher-order quinary digits */
    int d = x%5;
    if (!d)
        return r;
    return r * a[d] * (1<<d*k%4) % 5;
}

int main(int c, char **v)
{
    c = atoi(*++v);
    printf("%d",
           c<2
           ? 1                  /* special-case 0 & 1 */
           : 2*f(0,c));         /* otherwise, it's 2 times r */
}

test:

$ for i in 100 1000 10000 100000; do echo $i: `./694 $i`; done
100: 4
1000: 2
10000: 8
100000: 6
1000000: 4

Anche le prestazioni sono rispettabili. Ecco un input massimo per un sistema a 32 bit int:

$ time ./694 2147483647
8
real    0m0.001s
user    0m0.000s
sys     0m0.000s

Ho avuto gli stessi tempi anche con un massimo di 64 bit int.


1
Potrebbe essere interessante notare che 2147483647!ha oltre 19 miliardi di cifre e (2^63-1)!oltre 170.000.000.000.000.000.000 di cifre, quindi questa è una grande vittoria sul calcolo dei fattoriali. 1000000!come specificato nella domanda è possibile calcolare sull'hardware corrente; sono solo 5½ milioni di cifre. :-)
Toby Speight,

1

PHP - 105

 <?foreach(explode("\n",`cat`)as$n)if($n){$f=rtrim(gmp_strval(gmp_fact($n)),'0');echo substr($f,-1)."\n";}

Funziona meno di 10 secondi con il testcase indicato.


1

python3

239 caratteri

Può fare 10000 in ~ 3,2 secondi (Ideone mi interrompe a 8 secondi, sono sicuro che ci vorrà più di 10 secondi però :()

from functools import *
N=100
r=range
s=(p for p in r(2,N)if all(p%n>0for n in r(2,p)))
f=lambda n,x:n//x+(n//x>0and f(n//x,x)or 0)
e=list([p,f(N,p)]for p in s)
e[0][1]-=e[2][1]
e[2][1]=0
print(reduce(lambda x,y:x*y,map(lambda x:x[0]**x[1],e))%10)

python2.6

299 caratteri (un po 'più veloce)

from itertools import *
N=100000
r=xrange
def s(c=count(2)):
        while 1:p=c.next();c=ifilter(p.__rmod__,c);yield p
f=lambda n,x:n//x+(n//x>0and f(n//x,x)or 0)
e=[[p,f(N,p)]for p in takewhile(lambda x:x<N,s())]
e[0][1]-=e[2][1]
e[2][1]=0
print(reduce(lambda x,y:x*y,map(lambda x:pow(x[0],x[1],10),e))%10)

1

Haskell, 78 caratteri

f n=head$dropWhile(=='0')$reverse$show$product[1..n]
main=interact(show.f.read)

(Probabilmente avrebbe bisogno di essere compilato per calcolare 1.000.000! In 10 secondi).


Salva due caratteri, sostituiscili foldl1con product(vedi codegolf.stackexchange.com/questions/607/find-the-factorial/… ). Ma hai effettivamente provato con 1000000! ?
JB

PS: non un programma completo.
JB

Ci dispiace, lo ha fatto prima che fosse chiarito nei commenti. Lo aggiornerò.
Stusmith

1

J - 42 40 caratteri

Un intero programma. Salvare questo programma in un file ed eseguirlo con jconsole script.ijs 1234. Si noti che questo programma non esce dall'interprete dopo aver stampato un risultato. Digitare ^Do exit]0per uscire dall'interprete.

echo([:{:@(#~*)10&#.inv@*)/1+i.".>{:ARGV

Ecco una spiegazione:

  • x #. yinterpreta il vettore intero ycome xnumero base ; per esempio, i 10 #. 1 2 3 4rendimenti 1234.
  • u invproduce l' inverso di un verbo u. In particolare, x #. inv yrappresenta ycome un xnumero di base ; per esempio, i 10 #. 1234rendimenti 1 2 3 4. Si noti che invè definito come ^:_1, cioèu applicato -1 tempo.
  • x * yè il prodotto di xe y, quindi, x 10&#.inv@* yfornisce una rappresentazione in base 10 del prodotto di xe y.
  • x # ycopia il n voce -esimo di ytutte le volte che l' n -esimo punto di x; quando xè un vettore di booleani, xseleziona quali elementi yprendere. Ad esempio, i 1 0 1 0 # 1 2 3 4rendimenti 1 3.
  • * yproduce il signum di y.
  • x u~ yè il riflesso di u, cioè, lo stesso diy u x .
  • Pertanto, y #~ * yproduce un vettore di tutti gli elementi yche sono positivi. In tacita notazione, questo può essere scritto con un hook come (#~ *).
  • {: yrestituisce l'ultimo elemento in y.
  • assemblati insieme, otteniamo la frase tacita ([:{:@(#~*)10&#.inv@*).
  • u/ yè la riduzione di y, cioè, il verbo diadica uinserito tra gli elementi y. Ad esempio, +/1 2 3 4è come 1 + 2 + 3 + 4e cede 10.
  • Pertanto, la frase ([:{:@(#~*)10&#.inv@*)/ yindica l'ultima cifra del prodotto degli articoli di y.
  • ARGV è un vettore in box degli argomenti della riga di comando.
  • ".>{:ARGV è l'ultimo argomento unboxed e interpretato come un numero.
  • i. ycalcola i numeri naturali da 0a y - 1.
  • Così, 1+i. y produce numeri naturali da 1a y. Avrei potuto usare anche l' >: incremento qui, ma 1+è più chiaro allo stesso costo dei personaggi.
  • L'intero programma si applica 1+i.".>{:ARGV(il vettore di 1al numero nell'ultimo argomento della riga di comando) al verbo([:{:@(#~*)10&#.inv@*)/ e stampa il risultato con echo.

1

Pyt , 5 byte

!₫ą0⦋

Spiegazione:

         Implicit input (n)
!        n!
 ₫       Reverse the digits of (n!) - this disregards leading zeroes after reversal
  ą      Convert to array of digits
   0⦋    Get the first element

Provalo online!


1

R , 63 55 51 46 byte

Calcola fattoriale, estrae l'ultima cifra diversa da zero. Grazie a Giuseppe per aver fornito la struttura di base.

(y=(gamma(scan()+1))%/%10^(0:1e5)%%10)[!!y][1]

Provalo online!

In alternativa, la mia vecchia risposta a 51 byte:

Calcola fattoriale, converte in carattere, rimuove tutte le 0s, quindi prende il carattere finale. Salvato 2 byte grazie a Giuseppe.

substring(x<-gsub("0","",gamma(scan())+1),nchar(x))

Provalo online!


1
gamma(x+1)è più corto difactorial(x)
Giuseppe

senza la conversione di stringhe, il migliore che sono riuscito a ottenere era (y=(x<-gamma(scan()+1))%/%10^(0:nchar(x))%%10)[!!y][1]a 54 byte.
Giuseppe,

@Giuseppe Possiamo sostituirlo nchar(x)con 1e5una soluzione a 46 byte! Ben fatto.
rturnbull,

1

> <> , 25 byte

v:a%:?n-a,!
1
>$::?!.1-}*

Provalo online!

Maniglie 0! anche correttamente. Valore passato attraverso la -vbandiera.


Il test case 1000non produce alcun output su TIO - cosa c'è che non va?
Toby Speight,

1

Perl 6 ,  26  35 byte

{[*](1..$_)~~/.*<(<-[0]>/}

Provalo


Come programma completo:

put [*](1..@*ARGS[0])~~/.*<(<-[0]>/

Provalo

Allargato:

{
  [*]( 1..$_ ) # reduce using &infix:« * »
  ~~           # match with
  /
    .*         # any number of values (so it matches from the end)
    <(         # only capture the following
    <-[0]>     # any value but 0 (negated character class)
  /
}

1

C (gcc) , 72 byte (funzione)

f(n,d)long long n,d;{for(d=1;n;d%=10000)for(d*=n--;d%10<1;d/=10);d%=10;}

Provalo online!

C (gcc) , 101 99 byte (intero programma)

main(){long long n,d=1;for(scanf("%lld",&n);n;d%=10000)for(d*=n--;d%10<1;d/=10);printf("%d",d%10);}

Provalo online!

Questa domanda è poco meno di 8 anni, quindi "macchina ragionevole" non è la stessa di allora, ma sto ottenendo tempi di ~ 0,01 secondi sul mio computer quando faccio tutti i casi di test insieme, quindi a meno che i computer non siano aumentati di velocità di un fattore 1000 nell'ultimo decennio, dovrebbe andare bene.


La legge di Moore è ancora (un po ') sostenuta, quindi dovrebbe essere circa 16 volte più veloce
ASCII-only

Inoltre, una funzione va bene
ASCII solo l'


0

Attache , 26 byte

Last@`\&:(All@V)@Digits@`!

Provalo online!

Spiegazione

Last@`\&:(All@V)@Digits@`!

Questa è una composizione di 4 funzioni:

  • `! - questa è una versione funzionale dell'operatore fattoriale
  • Digits - questo ottiene le cifre del fattoriale
  • \&:(All@V)- Questa è una funzione di selezione. Funziona con il legame sinistro ( &:) la funzione All@Va \, che è selezionata. A sua volta, All@Vè un modo breve per verificare se un numero non è 0. Funziona lanciando il suo input su un vettore, 0 -> [0]quindi interrogando se tutti quei membri sono veritieri (cioè non 0). Questo dà le cifre del numero senza 0s.
  • Last - questo ottiene semplicemente l'ultimo membro di questo array.

Sembra incredibilmente lento - il TIO è scaduto (1 minuto) sul test case 100000 - come hai ottenuto il risultato 1000000 in 10 secondi?
Toby Speight,

@TobySpeight Quando ho risposto a questa sfida, quel particolare requisito non c'era (controlla la cronologia delle revisioni).
Conor O'Brien,

Ah, avrei dovuto guardare la storia! Hai verificato tutti i test in questione, però?
Toby Speight,

Sembra che ci sia stata una raffica di risposte durante il periodo in cui il limite di tempo è stato rimosso dalla domanda - è un peccato, davvero.
Toby Speight,

@TobySpeight Sì, l'ho fatto. È un peccato, e non sono sicuro della politica in merito.
Conor O'Brien,

0

APL (Dyalog Unicode) , 18 15 byte

{⊢/⍵/⍨0≠⍎¨⍵}⍕∘!

Provalo online!

Funzione prefisso tacita. Restituisce la cifra corretta per un singolo caso di test o una stringa di cifre per più casi di test.

Grazie a @ Adám e @ErikTheOutgolfer per 3 byte ciascuno.

Come?

{⊢/⍵/⍨0≠⍎¨⍵}⍕∘!  Main function. Argument is a number following the !.
              !  Factorial
                then
                Format (stringify)
        ⍎¨⍵}     Execute (turn to number) each digit of the argument
      0         Check if each is 0. This returns a boolean vector
                Swap arguments for the following fn/op
   ⍵/            Replicate. This takes a boolean vector as left arg and returns the truthy elements of the right arg. E.g.: 1 1 0/1 2 3  1 2.
{⊢/              Reduce. This returns the rightmost (last) element of a vector argument.

0

APL NARS, 28 byte, 14 caratteri

{↑≠v/v←⌽⍎¨⍕!⍵}

Non so perché ma questo supera il test:

  q←{↑≠v/v←⌽⍎¨⍕!⍵}       
  q¨1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 6 4 2 2 4 2 8 8 8 6 8 2 

0

AWK , 47 57 byte

{for(p=$1;--$1;p=(p*$1)%1e4)while(!(p%10))p/=10;$0=p%10}1

Provalo online!

La soluzione originale non ha gestito molto bene valori di input "grandi". Potrebbe aggiungere -Mper forzarlo a funzionare, ma ciò richiede anche molto più tempo di elaborazione.


Sì, @TobySpeight, infnon %molto bene. :(
Robert Benson,

Ah ... guardando la versione della domanda a cui ho risposto, non era necessario un gran numero.
Robert Benson,

-2

Japt , 6 byte

Sono venuto con alcuni 6-byters diversi ma questo mi è piaciuto di più. Sono convinto che ci debba essere un modo per farlo in 5, però.

Êsw ìv

Provalo


Spiegazione

Êcalcola il fattoriale dell'input, lo sconverte in una stringa e lo restituisce in un numero intero dopo waverlo invertito, ìconverte il risultato in una matrice di cifre e vrestituisce il primo elemento.


alternative

Êì w æ
ÊìÈf Ì
Êì f o
Êsw sg
Êìf ìo
Êìf ìÌ

Quanto tempo richiede l'esecuzione di tutti i casi di test?
Toby Speight,

@TobySpeight; è molto facile testarlo seguendo il link per provarlo. Si noti che gli ultimi 4 casi di test falliranno poiché i loro fattoriali sono più grandi dell'intero massimo di JavaScript.
Shaggy

Quindi non risolve davvero il problema allora? La domanda dice che deve avere successo per 1 ≤ N ≤ 1.000.000 . Altre risposte dimostrano che non è necessario essere in grado di memorizzare il fattoriale per calcolare la risposta.
Toby Speight,

Ho provato il test online, ma scade il primo caso di test che ho provato (1000).
Toby Speight,

-2

Perl 5 , 36 + 10 ( -p -Mbigint) = 46 byte

$"=$_;$_*=$"while$"-=1;($_)=/(.)0*$/

Provalo online!


La versione TIO fallisce i primi due casi di test che ho provato: 1000000 ⇒ f(dovrebbe essere 4 ) e 100 ⇒ 7(dovrebbe essere 4 )
Toby Speight,

Straripa la dimensione di un int. La nuova versione funziona usando bigint. Le prestazioni lasciano ancora a desiderare in quanto è un calcolo della forza bruta. Ciò significa che va in timeout su TIO per numeri maggiori.
Xcali,
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.