底の階乗の最後の非ゼロ桁


22

n b k入力の出力として3つの正の整数を指定するか、またはkの基本b表現の末尾のゼロの前の最後の桁を返すプログラムまたは関数を作成する必要がありn!ます。

n=7 b=5 k=4
factorial(n) is 5040
5040 is 130130 in base 5
the last 4 digits of 130130 before the trailing zeros are 3013
the output is 3013

入力

  • n b kここで、3つの正の整数2 <= b <= 10
  • 入力整数の順序は任意に選択できます。

出力

  • 整数または整数リストとして返されるか出力される数字のリスト。
  • 先行ゼロはオプションです。
  • あなたの解決策は、私のコンピューターで1分以内すべてのサンプルテストケースを解決する必要があります(私は、近いケースのみをテストします。

提出物の正確性を確認するための新しいテストが追加されました。(これらは1分未満のランタイムルールの一部ではありません。)

入力=>出力(先行ゼロの省略を選択可能)

3 10 1  =>  6

7 5 4  =>  3013

3 2 3  =>  11

6 2 10  =>  101101

9 9 6  =>  6127

7 10 4  =>  504

758 9 19  =>  6645002302217537863

158596 8 20  =>  37212476700442254614

359221 2 40  =>  1101111111001100010101100000110001110001

New tests:
----------

9 6 3  =>  144

10 6 3  =>  544

これはコードゴルフであるため、最短のエントリが優先されます。


1
私のコンピューターで1分もかからないのは、詳細がわからない場合、狙うのが少し難しいです。
デニス

1
うの7 5 3出力「013」または「13」?
クラウディ

1
7 10 4私が言うテストケースに基づいて@Claudiu13
Maltysen

2
@Claudiu「先行ゼロはオプションです。」したがって、両方のバージョンが正しいです。
-randomra

1
またはに対して正の整数を受け入れなければなりませんnk?または、言語の整数型の範囲に制限できますか?
トビー

回答:


1

Dyalog APL、23バイト

⌽k↑⌽{⍵↓⍨-⊥⍨0=⍵}b⊥⍣¯1⊢!n

このプログラムは、階乗が内部表現の制限を超えない限り機能します。Dyalog APLでは、制限はによって引き上げられ⎕FR←1287ます。

変数nは、B、及びkはセットされている(例えばを想定しているn b k←7 5 4)が、あなたは、むしろを要求したい場合は、NB、及びK(この順序で)、その後に3つの文字を置き換えます


私が投げたすべてのテストケースは、マシン(M540)で約11マイクロ秒で計算されました。
アダム

7

Mathematica、57 48バイト

@ 2012rcampionのおかげで9バイト節約されました。

IntegerString[#!/#2^#!~IntegerExponent~#2,##2]&

数学を実際に使ったことはありませんが、引数の順序を入れ替えてb最初に2バイトを節約できませんでしたか?
-FryAmTheEggman

@FryAmTheEggman私はゴルフ界では初めてですが、引数の順序を「コーシャ」と入れ替えていますか?
2012rcampion

1
あなたは実際に47に到達することができIntegerString[#!#2^-#!~IntegerExponent~#2,##2]&ます:(これとあなたのオリジナルの両方が非常に高速です)
-2012rcampion

質問者は、「入力整数の順序は任意に選択できます」と書きました。入力中なので、この場合は間違いなく問題あり
ません-FryAmTheEggman

@Fry Wow、よく読んでいないようです。ただし、SlotSequenceコメントで使用したトリックは現在の順序でのみ機能するため、これ以上保存できませんでした。
2012rcampion

7

Pythonの、198の 192 181文字

def F(n,b,k):
 p=5820556928/8**b%8;z=0;e=f=x=1
 while n/p**e:z+=n/p**e;e+=1
 z/=1791568/4**b%4;B=b**(z+k)
 while x<=n:f=f*x%B;x+=1
 s='';f/=b**z
 while f:s=str(f%b)+s;f/=b
 return s

これは十分に高速で、最大の例では約23秒です。階乗の組み込み関数はありません(Mathematicaをご覧ください!)。


[2,3,2,5,3,7,2,3,5][b-2]int('232537235'[b-2])3バイトを節約することができます。[1,1,2,1,1,1,3,2,1][b-2]同様に。
randomra

後者の場合、ルックアップテーブル111973>>2*(b-2)&3はさらに短くなります。ただし、前者と同じバイト数です(90946202>>3*(b-2)&7)。
Sp3000

あなたのようなNVMルックスは、右の上位桁事をした
SP3000

これをプログラムではなく関数にすることで、数バイト節約できると思います。
FryAmTheEggman

6

Pyth、26 35バイト

M?G%GHg/GHH.N>ju%g*GhHT^T+YslNN1T_Y

これは、3つの引数、数、基数、桁数の関数です。

デモンストレーション。

最も遅いテストケースである最後のテストケースでは、マシン上で15秒かかります。


@ Sp3000私は十分だと思う修正を追加しました。
isaacg

2

PARI / GP、43バイト

スペースの取引速度により、この簡単なアルゴリズムが得られます。

(n,b,k)->digits(n!/b^valuation(n!,b)%b^k,b)

私のマシンでは、各テストケースが1秒未満で実行されます。


2

Mathematica-48バイト

#!~IntegerDigits~#2/.{l__,0...}:>{l}~PadLeft~#3&

ゴルフをしていない:

Function[{n, b, k},
  IntegerDigits[n!, b] (* list of the base-b digits in n! *)
  /. {l__, 0...} (* match a sequence of elements l and some number of zeros*)
                 (* lucky for me, __ defaults to match the shortest number *)
     :> PadLeft[List[l], k] (* pad l to be k elements long with zeros on the left *)
                            (* this truncates the list if it is too long*)
]

例:

#!~IntegerDigits~#2/.{l__,0...}:>{l}~PadLeft~#3 &
%[758, 9, 19] // Timing

(* {0.031250, {6, 6, 4, 5, 0, 0, 2, 3, 0, 2, 2, 1, 7, 5, 3, 7, 8, 6, 3}} *)

最大の場合、制限要因は数字を生成しません:

Length@IntegerDigits[359221!, 2] // Timing
(* {0.109375, 6111013} 6.1M digits in 100 ms *)

パターンマッチングはのようでO(n^2)、最後の2つのテストケースは1分をはるかに超えています。


2

Bash / coreutils / dc、60バイト

dc<<<"1 `seq -f%g* $1`$2op"|sed -r s/0+$//|tail -c$(($3+1))

私の答えdcスクリプトを使用して、Find the Factorialを使用してbase $2に出力し、sed末尾のゼロをトリムtailし、最後の$3数字を選択します。


40ビットのベース2テストケースでは非常に遅いことを認めざるを得ません。私が使用してのsedの仕事を緩和しようとしたrevバックトラックを減らすために、それはだdcCPUを食べているの...
トビースパイツ

2

Haskell、111 109バイト

import Data.Digits
f n b k=digits b$foldl(((unDigits b.reverse.take k.snd.span(<1).digitsRev b).).(*))1[1..n]

使用法:f 158596 8 20->[3,7,2,1,2,4,7,6,7,0,0,4,4,2,2,5,4,6,1,4]

f 359221 2 40私の4歳のラップトップでは約8秒かかります。

仕組み:乗算(*)をリストに折り込みます[1..n]。すべての中間結果をb数字のリストとして(最下位が最初に)k基数に変換し、先行ゼロを取り除き、最初の数字を取得して再び基数10に変換します。最後にb再びベースに変換しますが、最上位桁が最初になります。


あなたは私の心の中に、私はMATLABを使用してそれを解釈していたという考えを持っていました、何と偶然でしょう:D
Abr001am

1

Python 3、146バイト

import math
i,f=input(),int
n=i.split()
e=math.factorial(f(n[0]))
d=''
while e>0:
 d=str((e%f(n[1])))+d;e=e//f(n[1])
print(d.strip('0')[-f(n[2]):])

テストケースがすべて十分に高速で実行されるかどうかはわかりません-大きなテストケースは非常に低速です(数値をループしているため)。

ここでオンライン試してください(ただし注意してください)。


1

Java、303 299 296バイト

import java.math.*;interface R{static void main(String[]a){BigInteger c=new BigInteger(a[1]),b=c.valueOf(1);for(int i=new Integer(a[0]);i>0;i--){b=b.multiply(b.valueOf(i));while(b.mod(c).equals(b.ZERO))b=b.divide(c);b=b.mod(c.pow(new Integer(a[2])));}System.out.print(b.toString(c.intValue()));}}

私のコンピューターでは、これは359221 2 40テストケースで平均して3分の1秒未満です。コマンドライン引数を介して入力を受け取ります。


1

bc、75バイト

define void f(n,b,k){
obase=b
for(x=1;n;x%=b^k){
x*=n--
while(!x%b)x/=b}
x}

これは、コードサイズを削減するためにいくつかのGNU拡張機能を使用します。POSIX準拠の同等物は80バイトの重さです:

define f(n,b,k){
obase=b
for(x=1;n;x%=b^k){
x*=n--
while(x%b==0)x/=b}
return(x)}

実行時間を適切に保つために、階乗()を計算するときに、末尾のゼロ(while(!x%b)x/=b)を切り捨てて最終k桁(x%=b^k)に切り捨てfor(x=1;n;)x*=n--ます。

テストプログラム:

f(3, 10, 1)
f(7, 5, 4)
f(3, 2, 3)
f(6, 2, 10)
f(9, 9, 6)
f(7, 10, 4)
f(758, 9, 19)
f(158596, 8, 20)
f(359221, 2, 40)
f(9, 6, 3)
f(10, 6, 3)
quit

完全なテストスイートの実行時間は、2006年のビンテージワークステーションで約4¼秒です。


これは私の初めてのあるbc任意のヒントを特に歓迎されているので...、プログラム(ゴルフかどうかを)
トビースパイツ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.