Sıfır olmayan son rakamı n!


22

Giriş olarak 1 ≤ N ≤ 1,000,000 bir tamsayı verildiğinde , N'nin sıfır olmayan son basamağını verin . nerede ? faktördür ( 1 ile N arasındaki tüm sayıların ürünü ( dahil). Bu, OEIS dizisi A008904'tür .

Herhangi bir geçerli giriş için programınızın makul bir makinede 10 saniye içinde bitmesi gerekir.

Test Kılıfları

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

Bu bir yani bayttaki en kısa kod kazanır!


Tek işlevli mi yoksa komple program mı?
Joey,

@joey Hayır, sadece test durumları. Tek Giriş, Tek Çıkış.
fR0DDY

@joey Programı tamamlayın.
fR0DDY

1
Tam bir program
için gereklilik

2
@EriktheOutgolfer bu ~ 7 yıl öncesine ait, bu yüzden o zamanın tespit edildiğini sanmıyorum
NoOneIsHere

Yanıtlar:


8

Yakut - 63 karakter

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}

Kaynak - http://oeis.org/A008904

Kollar bir saniyenin altında bin basamağa kadar.

Ölçek

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 bayt

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

Kazanan bir cevap için çok okunabilir. :) (Sonra tekrar, henüz GolfScript & Co. gönderimi yok.)

Bu benim makinede yaklaşık 5 saniye içinde 1.000.000 girişini işler.


1
Mathematica, bu soru için hemen hemen mükemmel bir dildir.
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 bayt

Bu boyut için işlem yapar - test çantası uzun zaman alır (~ 6 saniye).

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

Bu sürüm çok daha hızlı (~ 15 mikrosaniye) ancak 81 bayt alır:

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)

Test etmek için bu (golf oynamayan olmayan) kodu kullanabilirsiniz:

[%(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

Notlar:

  • 100.000'e yakın bir sayı için bir dakikadan uzun sürüyor. Ancak, sonunda sıfırların kaldırılması, dizgeye dönüştürmeyi gerektirir, hesaplamalar yapmak için bir sayı gerekir, bu nedenle dönüşümler kaçınılmazdır.

Tarihçe:

  • 2011-02-08 10:31 (90) - İlk deneme.
  • 2011-02-08 10:33 (73) - Modül, dilimleme ve birleştirme işleminden daha kısa.
  • 2011-02-08 10:34 (63) - Gereksiz kesim.
  • 2011-02-08 10:37 (60) - Bir sayıya gereksiz oyuncu seçimi. Modulus bunu zaten iyi yapıyor.
  • 2011-02-08 10:40 (59) - Bazı satırlar.
  • 2011-02-08 11:00 (56) - Modülün daha kısa olması konusunda ne söylemiştim? Çıktı için de geçerlidir.
  • 2011-02-08 11:01 (53) - $inputBir dizeye döküm yapmak yeterli; için döküm intörtük olarak uygulanır.

2

Perl, 53 58 61 karakterler

Tüm boşluklar kaldırılabilir ancak “okunabilirlik” için bıraktım. Not: Sloane'dan bazı aptalca açık formüller kullanmamak.

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

Makinemde f (10 ^ 6) 8,7 saniyede hesaplar.

Güncelleme : OP bütün bir program olmasını istedi:

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

Bu 55 karakter yapar.


2

CJam - 28

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

10000'e kadar değerler için http://cjam.aditsu.net/ adresinde deneyebilirsiniz ; Daha büyük sayılar için java tercümanı kullanmalısınız . 1000000, dizüstü bilgisayarımda yaklaşık 3 saniye içinde çalışıyor.

Açıklama:

Ne yazık ki basit çözüm çok yavaş, bu yüzden her çarpmadan sonra sadece son 7 haneyi tutuyorum (sondaki sıfırlardan önce).

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

Not: Bu dil, sorudan çok daha yeni.



2

05AB1E , 4 bayt

!0м¤

Çevrimiçi deneyin!

açıklama

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

1
TIO versiyonu son testte zaman aşımına uğradı (60s) - "makul bir makinede" 10s içinde nasıl elde ettin?
Toby Speight

2

Jöle , 4 bayt

!Ṛȯ/

Çevrimiçi deneyin!

açıklama

Bir tamsayıya (listeyi tersine çevirir; vektörleştirmez) bir tamsayıya uygulandığında otomatik olarak aldığı gerçeğini kullanırD (basamak) .

Giriş 8 ile:

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

Bir baytlık "ilk truthy element" olduğunu sanmıyorum (böyle ȯ/davranır) ancak eğer varsa, bu toplam üç bayta kadar kısaltılabilir.


2

Java (OpenJDK 8) , 62 bayt

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

Çevrimiçi deneyin!

@Kevin Cruijssen'e benzer, ancak döngüleri birleştirerek 5 byte tasarruf eder.


PPCG'ye Hoşgeldiniz! Güzel ilk mesaj! Umarım takılırsın!
Rɪᴋᴇʀ

PPCG'ye Hoşgeldiniz! @Riker'la aynı fikirdeyim, ilk mesajın harika. Kodları golf döngüler birleştirerek golf aferin. Sen golf 1 daha değiştirerek şimdiki yanıtında bayt can ||ile |ve değiştirerek ek bayt ==0ile <1. Kaldınız!
Kevin Cruijssen

2

C, 150 140 135 bayt

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));}

ASCII sistemleri için olan versiyon budur; dizesini değiştirmek 33436ile 11214bir EBCDIC sistem için, ya da \1\1\2\1\4taşınabilir bir program için.

C çözümleri, tam bir program sağlama zorunluluğu tarafından biraz engellenmiştir; ancak, bu soruyu tam olarak cevaplıyor.

Çevrimiçi deneyin (Javascript gerektirir):

açıklama

N En Az Önemli Sıfır Basamağında belirtilen algoritmaya dayanmaktadır ! , döndü, böylece beşin en yüksek gücünü bulmak için tekrar girip tekrar hesaplamayı yaptık. Sabit tabloları çok büyüktü, bu yüzden önceki kalıntı r, mevcut basamak dve özyineleme derinliği arasında bir ilişki bularak onları azalttım 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

Çünkü r>0bu, sabit bir zaman rsürelerine 2^dk(mod 5) düzelir ; sabitler a[]aşağıdadır (golf kodunda belirtilmiştir). Bunun (2^4)%51 olduğunu da gözlemliyoruz , bu nedenle menzili taşmasını önlemek için üssü azaltabiliriz 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 */
}

Testler:

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

Performans da saygıdeğerdir. İşte 32 bitlik bir sistem için maksimum giriş int:

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

Aynı zamanlamaları maksimum 64 bit ile de aldım int.


1
2147483647!19 milyar haneden (2^63-1)!fazla ve 170.000.000.000.000.000.000 haneden fazla olduğuna dikkat etmek ilginç olabilir , bu yüzden bu faktörlerin hesaplanmasında büyük bir kazançtır. 1000000!soruda belirtildiği gibi mevcut donanım üzerinde hesaplamak mümkündür; bu sadece 5½ milyon rakam. :-)
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";}

Verilen test çantası ile 10 saniyenin altında çalışır.


1

Python3

239 Karakter

~ 3.2 saniyede 10000 yapabilir (Ideone beni 8 saniyede keser, 10 saniyeden daha uzun süreceğinden eminim :()

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 Chars (biraz daha hızlı)

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 karakter

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

(Muhtemelen 10 saniyede 1.000.000! 'İ hesaplamak için derlenmeye ihtiyaç duyacaktır).


İki karakter kaydet, Yenisini foldl1ile product(cf codegolf.stackexchange.com/questions/607/find-the-factorial/... ). Ama aslında 1000000 ile denediniz mi? ?
JB,

Not: tam bir program değil.
JB,

Üzgünüm, daha önce yorumlarda açıklığa kavuşturuldu. Güncelleyeceğim.
stusmith

1

J - 42 40 karakter

Bütün bir program. Bu programı bir dosyaya kaydedin ve ile çalıştırın jconsole script.ijs 1234. Bir sonuç yazdırdıktan sonra bu programın tercümandan çıkmadığına dikkat edin. Yazın ^Dveya exit]0tercüman çıkmak için.

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

İşte bir açıklama:

  • x #. ytamsayı vektörünü ytemel xsayı olarak yorumlar; örneğin, 10 #. 1 2 3 4verimler 1234.
  • u invfiilin tersini verir u. Özellikle, bir temel sayı olarak x #. inv ytemsil eder ; örneğin, verimler . Uyarı olarak tanımlanır olup, uygulanan -1 zaman.yx10 #. 12341 2 3 4inv^:_1u
  • x * yolan ürün bir xve yböylece x 10&#.inv@* yürünü bir baz-10 temsilini verir xve y.
  • x # ykopyalar n ait ıncı madde ygenellikle olduğunca n ait ıncı öğe x; ne zaman xbir boolean vektörü, xhangi nesnelerin alınacağını seçer y. Örneğin, 1 0 1 0 # 1 2 3 4verim 1 3.
  • * yverir sinyalnum arasında y.
  • x u~ ybir yansıtıcı arasında uolduğu, aynıy u x .
  • Böylece, pozitif y #~ * yolan tüm öğelerin bir vektörünü verir y. Taciz yazımında bu, bir kanca ile olduğu gibi yazılabilir .(#~ *) .
  • {: y içindeki son öğeyi verir y .
  • bir araya toplanıp anlaşılır bir cümle elde ediyoruz ([:{:@(#~*)10&#.inv@*) .
  • u/ ybir indirgeme bölgesinin ydiyadik fiildir, uelemanları arasına yerleştirilir y. Mesela, +/1 2 3 4benzer 1 + 2 + 3 + 4ve verim10 .
  • Böylece, cümle ([:{:@(#~*)10&#.inv@*)/ y, öğelerin ürününün son basamağını verir y.
  • ARGV komut satırı argümanlarının kutulu bir vektörüdür.
  • ".>{:ARGV kutusundaki ve bir sayı olarak yorumlanan son argümandır.
  • i. y doğal sayıları hesaplar 0 için y - 1.
  • Böylece, 1+i. ydoğal sayıları-dan 1verir y. Ayrıca >: artışı kullanabilirdim Burada , ancak 1+aynı karakter maliyetiyle daha açık.
  • Programın tamamı 1+i.".>{:ARGV( 1son komut satırı argümanındaki sayıya vektör ) fiile uygulanır ([:{:@(#~*)10&#.inv@*)/ve sonucu yazdırır echo.

1

Pyt , 5 bayt

!₫ą0⦋

Açıklama:

         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

Çevrimiçi deneyin!


1

R , 63 55 51 46 bayt

Faktör hesaplar, son sıfır olmayan basamağı çıkarır. Temel yapıyı sağladığı için Giuseppe'ye teşekkür ederiz.

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

Çevrimiçi deneyin!

Alternatif olarak, eski 51 baytlık cevabım:

Faktoringi hesaplar, karaktere dönüştürür, hepsini 0s ve ardından son karakteri alır. Giuseppe sayesinde 2 bayt kaydedildi.

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

Çevrimiçi deneyin!


1
gamma(x+1)daha kısadırfactorial(x)
Giuseppe

string dönüşümü olmadan elde edebileceğim en iyi (y=(x<-gamma(scan()+1))%/%10^(0:nchar(x))%%10)[!!y][1]54 byte idi.
Giuseppe

Biz yerini alabilir @Giuseppe nchar(x)ile 1e5bir 46 bayt çözümü için! İyi gidiyor.
rturnbull



1

C (gcc) , 72 bayt (işlev)

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

Çevrimiçi deneyin!

C (gcc) , 101 99 bayt (bütün program)

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);}

Çevrimiçi deneyin!

Bu soru sadece 8 yaşındayken utangaç, bu yüzden "makul makine" geçmiş zamankiyle aynı değil, ancak tüm test vakalarını birlikte yaparken bilgisayarımda hız artışı olmadıkça bilgisayarımda ~ .01 saniye zaman alıyorum Bu son on yılda 1000 faktörü ile iyi olmalı.


Moore'un yasası hala devam ediyor, bu yüzden yaklaşık x16 kat daha hızlı olmalı
ASCII-sadece

Ayrıca, bir işlev iyidir
sadece ASCII-


0

Ataşesi , 26 bayt

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

Çevrimiçi deneyin!

açıklama

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

Bu 4 fonksiyonun bir bileşimidir:

  • `! - bu faktoring operatörünün işlevsel bir versiyonudur
  • Digits - bu faktoringin rakamlarını alır
  • \&:(All@V)- Bu bir seçim işlevidir. Bu sol-yapıştırma (çalışır &:) işlevi All@Viçin \seçmektir. Buna karşılık, All@Vbir sayı 0 değilse, test etmenin kısa bir yoludur. Girdiyi bir vektöre dökerek çalışır, 0 -> [0]sonra tüm bu üyelerin kaba olup olmadığını sorgulayarak çalışır (yani 0 değil). Bu sayının 0s olmadan rakamını verir.
  • Last - bu sadece bu dizinin son üyesini alır.

Bu inanılmaz derecede yavaş görünüyor - TIO 100000 test davasında zaman aşımına uğradı (1 dakika) - 1000000 sonucunu 10 saniye içinde nasıl aldınız?
Toby Speight

@TobySpeight Bu zorluğa cevap verdiğimde, söz konusu gereksinim yoktu (revizyon geçmişini kontrol edin).
Conor O'Brien,

Ah, tarihe bakmalıydım! Yine de, sorudaki tüm sınamaları doğruladınız mı?
Toby Speight

Görünüşe göre, zaman diliminin sorudan çıkarıldığı dönem boyunca bir cevaplar telaşı yaşanıyor - bu talihsiz bir durum.
Toby Speight

@TobySpeight Evet, yaptım. Talihsiz bir durum ve bununla ilgili politikadan emin değilim.
Conor O'Brien,

0

APL (Dyalog Unicode) , 18 15 bayt

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

Çevrimiçi deneyin!

Tam önek işlevi. Tek bir test durumu için doğru rakam veya birden çok test durumu için bir rakam dizesi döndürür.

Her biri 3 baytlık @ Adám ve @ErikTheOutgolfer'a teşekkürler.

Nasıl?

{⊢/⍵/⍨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 bayt, 14 karakter

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

Nedenini bilmiyorum ama bu testi geçiyor:

  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 bayt

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

Çevrimiçi deneyin!

Orijinal çözüm "büyük" giriş değerlerini çok iyi işlememiş. -MÇalışmaya zorlamak için ekleyebilir , ancak bu çok daha fazla işlem süresi gerektirir.


Evet, @TobySpeight, pek iyi infdeğil %. :(
Robert Benson

Ah ... sorduğum sorunun versiyonuna bakarak, çok sayıda numara gerekli değildi.
Robert Benson,

-2

Japt , 6 bayt

Birkaç farklı 6-by-get geldi ama bunu en çok sevdim. Yine de, 5 yapmanın bir yolu olması gerektiğine ikna oldum.

Êsw ìv

Dene


açıklama

Êgirişin faktörünü hesaplar, sonu bir dizgeye dönüştürür ve wtersine çevirdikten sonra tamsayıya geri döndürür, ìsonucu bir basamak dizisine dönüştürür vve ilk öğeyi döndürür.


Alternatifler

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

Tüm test durumlarının yürütülmesi ne kadar sürer?
Toby Speight

@TobySpeight; denemek için bağlantıyı izleyerek test etmek çok kolaydır. Son 4 test senaryosunun, kendi yüzleri JavaScript'in maksimum tamsayısından büyük olduğu için başarısız olacağını unutmayın.
Shaggy

Demek problemi çözmüyor o zaman? Soru, 1 ≤ N ≤ 1,000,000 değerinde başarılı olması gerektiğini söylüyor . Diğer cevaplar, cevabı hesaplamak için faktoringi saklayabilmek zorunda olmadığınızı göstermektedir.
Toby Speight

Çevrimiçi testi denedim, ancak denediğim ilk testte (1000) zaman aşımına uğradı.
Toby Speight

-2

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

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

Çevrimiçi deneyin!


TIO sürümü denediğim ilk iki test senaryosunda başarısız oldu: 1000000 ⇒ f( 4 olmalı ) ve 100 ⇒ 7( 4 olmalı )
Toby Speight

Bir int büyüklüğünden taşıyor. Yeni sürüm bigint kullanarak çalışır. Performans hala kaba bir kuvvet hesabı olduğu için arzulanan bir şey bırakır. Bu daha büyük sayılar için TIO'da zaman aşımına uğradığı anlamına gelir.
Xcali
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.