nの最後のゼロ以外の数字!


22

入力として1≤N≤1,000,000の整数を指定すると、N!の最後のゼロ以外の数字が出力されます、どこ階乗(1からNまでのすべての数値の積)です。これは、OEISシーケンスA008904です。

プログラムは、有効な入力のために妥当なマシンで10秒以内に終了する必要があります。

テストケース

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

これはので、バイト単位の最短コードが勝ちです!


単一機能または完全なプログラム?
ジョーイ

@joeyいいえ、これらは単なるテストケースです。シングル入力、シングル出力。
fR0DDY

@joey完全なプログラム。
fR0DDY

1
完全なプログラムの要件は推奨されません...
エリックアウトゴルファー

2
私は時に決定されたことはないと思うので、7年前〜からである。この@EriktheOutgolfer
NoOneIsHere

回答:


8

ルビー-63文字

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}

ソース-http://oeis.org/A008904

fを1秒未満で1000桁まで処理します。

テスト

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バイト

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

勝利の答えのために非常に読みやすい。:)(再度、GolfScript&Co.の提出はまだありません。)

これは私のマシンで約5秒で1,000,000の入力を処理します。


1
Mathematicaはこの質問にぴったりの言語です。
マイケルスターン

4

パイソン-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バイト

これは速度とサイズのトレードオフです-テストケースには長い時間がかかります(最大6秒)

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

このバージョンははるかに高速(〜15マイクロ秒)ですが、81バイトかかります。

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)

この(ゴルフではない)コードを使用して、次のいずれかをテストできます。

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

ノート:

  • 100,000に近い数の場合、1分以上かかります。ただし、最後のゼロを削除するには文字列に変換する必要があり、計算を行うには数値が必要であるため、いずれにしても変換は避けられません。

歴史:

  • 2011-02-08 10:31(90)–最初の試行。
  • 2011-02-08 10:33(73)–モジュラスはスライスと結合よりも短いです。
  • 2011-02-08 10:34(63)–不要なトリム。
  • 2011-02-08 10:37(60)–数値への不必要なキャスト。モジュラスはすでにそれをうまくやっています。
  • 2011-02-08 10:40(59)–いくつかのインライン化。
  • 2011-02-08 11:00(56)–モジュラスが短くなることについて、私は以前何と言いましたか?出力にも適用されます。
  • 2011-02-08 11:01(53)– $input文字列へのキャストで十分です。キャストintは暗黙的に適用されます。

2

Perl、53 58 61 キャラクター

すべての空白は削除できますが、「読みやすさ」のために残しておきます。注:Sloaneの愚かな明示的な式を使用しないでください。

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

私のマシンで8.7秒でf(10 ^ 6)を計算します。

更新:OPは、プログラム全体にすることを望んでいました。

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

これで55文字になります。


2

CJam-28

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

最大10000程度の値については、http://cjam.aditsu.net/で試すことができます。数値が大きい場合は、Javaインタープリターを使用する必要があります。私のラップトップでは約3秒で1000000が実行されます。

説明:

残念ながら、簡単な解決策は遅すぎるため、各乗算後に最後の7桁(末尾のゼロの前)のみを保持しています。

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

注:この言語は質問よりもずっと新しいです。




2

ゼリー、4バイト

!Ṛȯ/

オンラインでお試しください!

説明

(リストを逆にする;ベクトル化しない)が整数に適用されると、自動的にD(数字)がとられるという事実を使用します。

入力8の場合:

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

1バイトの「最初の真実の要素」(ȯ/として機能する)は存在しないと思いますが、存在する場合、これを合計3バイトに短縮できます。


2

Java(OpenJDK 8)、62バイト

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

オンラインでお試しください!

@Kevin Cruijssenに似ていますが、ループを組み合わせることで5バイトを節約します。


PPCGへようこそ!素敵な最初の投稿!頑張ってね!
Rɪᴋᴇʀ

PPCGへようこそ!素晴らしい最初の投稿である@Rikerに同意します。ループを組み合わせて、コードをゴルフでよくやった。あなたはゴルフ1以上置換することにより、あなたの現在の答えでバイトすることができ|||、そして交換することにより、追加のバイト==0<1。滞在を楽しんで!
ケビンクルーッセン

2

C、150の 140 135バイト

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システムのバージョンです。EBCDICシステムの場合、またはポータブルプログラムの場合は、文字列33436を置き換えます。11214\1\1\2\1\4

Cソリューションは、完全なプログラムを提供するための要件によって少し妨げられています。ただし、これは質問に完全に答えます。

オンラインで試す(Javascriptが必要):

説明

これは、nの最下位の非ゼロ数字で概説されているアルゴリズムに基づいています、5のべき乗の最大値を見つけるために再帰し、途中で計算を行うように向きを変えました。定数のテーブルが大きすぎたため、前の剰余r、現在の桁d、再帰の深さの関係を見つけることでそれらを減らしました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

の場合r>0、これは定数r2^dk(mod 5)に解決されます。定数はa[]以下にあります(ゴルフのコードでインライン化されています)。また、それ(2^4)%5は1であるため、指数を減らしての範囲をオーバーフローさせないようにすることができ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 */
}

テスト:

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

パフォーマンスも立派です。32ビットのシステムの最大入力はint次のとおりです。

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

最大64ビットintでも同じタイミングを取得しました。


1
2147483647!190億桁(2^63-1)!以上、170,000,000,000,000,000,000桁以上あることに注目するのは興味深いかもしれません。したがって、これは階乗の計算よりも大きな勝利です。 1000000!質問で指定されているように、現在のハードウェアで計算することが可能です。それはたったの550万桁です。:-)
トビースパイト

1

PHP-105

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

指定されたテストケースで10秒未満で実行します。


1

Python3

239文字

〜3.2秒で10000を実行できます(Ideoneは8秒で切断しますが、10秒より長くかかると確信しています:()

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文字(少し高速)

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文字

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

(10秒で1,000,000!を計算するには、おそらくコンパイルする必要があります)。


2つの文字を保存してfoldl1productcodegolf.stackexchange.com/questions/607/find-the-factorial/…を参照)に置き換えます。しかし、実際に1000000で試してみましたか!?
JB

PS:完全なプログラムではありません。
JB

申し訳ありませんが、コメントで明らかにされる前にそれをしました。更新します。
stusmith

1

J – 42 40文字

プログラム全体。このプログラムをファイルに保存し、で実行しjconsole script.ijs 1234ます。このプログラムは、結果を出力した後、インタープリターを終了しないことに注意してください。^Dまたはexit]0を入力して、インタープリターを終了します。

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

説明は次のとおりです。

  • x #. y 整数ベクトルを解釈します yを基数としてxます。たとえば、10 #. 1 2 3 4yields 1234
  • u inv動詞のを返しuます。特に、ベース番号としてx #. inv y表します。例えば、yx10 #. 1234 yields 1 2 3 4invとして定義されていることに注意してください。つまり^:_1u -1回適用されます。
  • x * yある製品xy、従ってx 10&#.inv@* y生成物のベース10の表現を生成xし、y
  • x # yコピーN番目の項目yしばしばとしてのn番目の項目x。when xがブール値のベクトルの場合、取得xするアイテムを選択yします。たとえば、 1 0 1 0 # 1 2 3 4yields 1 3
  • * y符号を生成しyます。
  • x u~ yある再帰uと同じです、y u x
  • したがって、正のy #~ * yすべてのアイテムのベクトルを生成しyます。暗黙表記で、この缶を用いて書かれたフック として(#~ *)
  • {: yの最後のアイテムを生成しyます。
  • 一緒に組み立てると、暗黙のフレーズが得られ([:{:@(#~*)10&#.inv@*)ます。
  • u/ yは、の簡約ですy。つまり、のu要素間に挿入される二項動詞ですy。例えば、+/1 2 3 4のようなものです1 + 2 + 3 + 4と利回り10です。
  • したがって、フレーズ ([:{:@(#~*)10&#.inv@*)/ yは、次の項目の積の最後の桁を生成しますy
  • ARGV コマンドライン引数のボックス化されたベクトルです。
  • ".>{:ARGV ボックス化されていない数値として解釈される最後の引数です。
  • i. yから自然数を計算0しますy - 1ます。
  • したがって、1+i. yからの自然数が得1られyます。 ここでも>: インクリメントを使用できますが1+、同じコストのキャラクターでより明確になります。
  • プログラム全体が動詞に適用され1+i.".>{:ARGV1最後のコマンドライン引数の数値のベクトル)([:{:@(#~*)10&#.inv@*)/、結果がで出力されechoます。


1

R63 55 51 46バイト

階乗を計算し、最後のゼロ以外の数字を抽出します。基本構造を提供してくれたGiuseppeに感謝します。

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

オンラインでお試しください!

あるいは、私の古い51バイトの答え:

階乗を計算し、文字に変換し、すべて0のsを削除してから、最終文字を取得します。Giuseppeのおかげで2バイト節約されました。

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

オンラインでお試しください!


1
gamma(x+1)より短いfactorial(x)
ジュゼッペ

文字列変換なしでは(y=(x<-gamma(scan()+1))%/%10^(0:nchar(x))%%10)[!!y][1]、54バイトでした。
ジュゼッペ

私たちは、置き換えることができます@Giuseppe nchar(x)1e546バイトのソリューションのために!いいね
rturnbull



1

C(gcc)、72バイト(関数)

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

オンラインでお試しください!

C(gcc)101 99バイト(プログラム全体)

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

オンラインでお試しください!

この質問は8歳の恥ずかしがり屋なので、「合理的なマシン」は当時と同じではありませんが、すべてのテストケースを一緒に実行すると、コンピューターで〜.01秒の時間が発生します。この10年間で1000倍になります。


ムーアの法則はまだ(ちょっと)維持されているので、約16倍高速になるはずです
ASCIIのみ

また、この関数は結構です
ASCIIのみを


0

アタッシュ、26バイト

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

オンラインでお試しください!

説明

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

これは4つの機能の構成です。

  • `! -これは階乗演算子の機能バージョンです
  • Digits -これは階乗の桁を取得します
  • \&:(All@V)-これは選択機能です。selectの&:関数All@Vを左結合()することで機能し\ます。次に、All@V数値が0でないかどうかをテストする簡単な方法です。入力をベクトルにキャストすることで機能します0 -> [0]、すべてのメンバーが真実(つまり0ではない)かどうかを照会ます。これにより、0のない数字の数字が得られます。
  • Last -これは単にこの配列の最後のメンバーを取得します。

これは信じられないほど遅いようです-100000テストケースでTIOがタイムアウト(1分)しました-10秒以内に1000000の結果を取得する方法は?
トビー・スペイト

@TobySpeightこの課題に答えたとき、その特定の要件はありませんでした(改訂履歴を確認してください)。
コナーオブライエン

ああ、私は歴史を見るべきでした!ただし、質問内のすべてのテストケースを検証しましたか?
トビー・スペイト

質問から時間制限が削除された期間中に回答が急増したようです-それは本当に残念です。
トビースパイト

@TobySpeightはい、できました。それは残念なことであり、私はこれに関する方針がわかりません。
コナーオブライエン

0

APL(Dyalog Unicode)18 15バイト

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

オンラインでお試しください!

暗黙のプレフィックス機能。単一のテストケースの正しい数字、または複数のテストケースの数字の文字列を返します。

それぞれ3バイトの@Adámと@ErikTheOutgolferに感謝します。

どうやって?

{⊢/⍵/⍨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バイト、14文字

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

理由はわかりませんが、これはテストに合格します。

  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

AWK47 57バイト

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

オンラインでお試しください!

元のソリューションでは、「大きな」入力値をうまく処理できませんでした。追加することができます-M仕事にそれを強制するために、それはまた、より多くの処理時間を要します。


ええ、@ TobySpeight inf%あまりうまくいきません。:(
ロバートベンソン

ああ...私が答えた質問のバージョンを見て、大きな数字は必要ありませんでした。
ロバートベンソン

-2

Japt、6バイト

いくつかの異なる6バイトに出会ったが、私はこれが一番好きだった。しかし、私は5でそれをする方法があるに違いないと確信しています。

Êsw ìv

それを試してみてください


説明

Ê入力の階乗を計算し、sそれを文字列wì変換し、逆にした後に整数に戻し、結果を数字の配列に変換しv、最初の要素を返します。


代替案

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

すべてのテストケースを実行するのにどれくらい時間がかかりますか?
トビースパイト

@TobySpeight; リンクをクリックして試してみると、非常に簡単にテストできます。階乗がJavaScriptの最大整数よりも大きいため、最後の4つのテストケースが失敗することに注意してください。
シャギー

それでは実際に問題を解決しませんか?問題は、それがために成功しなければならないと言う1≤N≤1,000,000。他の回答は、回答を計算するために階乗を保存する必要がないことを示しています。
トビースパイト

オンラインテストを試しましたが、最初に試したテストケース(1000)でタイムアウトになりました。
トビースパイト

-2

Perl 5、36 + 10(-p -Mbigint)= 46バイト

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

オンラインでお試しください!


TIOバージョンは、私が試した最初の2つのテストケースに失敗します。1000000⇒ f4でなければなりません)および100⇒ 74でなければなりません)
Toby Speight

intのサイズがオーバーフローしています。新しいバージョンは、bigintを使用して機能します。総当たり計算であるため、パフォーマンスにはまだ何かが望まれます。これは、TIOの数が多いとタイムアウトになることを意味します。
Xcali
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.