Последние ненулевые цифры факториала в базе


22

Вы должны написать программу или функцию, которая дает три положительных целых числа в n b kкачестве входных данных или возвращает последние 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

вход

  • 3 натуральных числа n b kгде 2 <= b <= 10.
  • Порядок ввода целых чисел может быть выбран произвольно.

Выход

  • Список цифр, возвращаемых или выводимых в виде целочисленного или целочисленного списка.
  • Ведущие нули необязательны.
  • Ваше решение должно разрешить любой пример теста менее чем за минуту на моем компьютере (я буду тестировать только закрытые случаи. У меня компьютер ниже среднего.).

Примеры

Добавлены новые тесты для проверки правильности представлений. (Они не являются частью правила выполнения менее 1 минуты.)

Input => Output (с возможностью опускания ведущих нулей)

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
Будет ли 7 5 3выводить «013» или «13»?
Клавдиу

1
@Claudiu на основе 7 10 4тестового примера, я бы сказал13
Maltysen

2
@Claudiu "Ведущие нули необязательны." поэтому обе версии верны.
Рандомра

1
Должны ли мы принять любое положительное целое число для nили k? Или мы можем ограничить их диапазоном целочисленного типа языка?
Тоби Спейт

Ответы:


1

Дьялог АПЛ , 23 байта

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

Эта программа работает до тех пор, пока факториал не превышает внутренний предел представления. В Dyalog APL предел может быть увеличен на ⎕FR←1287.

Предполагается, что переменные n, b и k были установлены (например n b k←7 5 4), но если вы предпочитаете запрашивать n , b и k (в этом порядке), то замените три символа на .


Каждый тестовый пример, который я набрасывал, вычислялся на моей машине примерно за 11 микросекунд (M540).
Адам

7

Mathematica, 57 48 байтов

Сохранено 9 байт благодаря @ 2012rcampion.

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

Я никогда не использовал mathematica, но не могли бы вы поменять местами порядок аргументов, bчтобы сэкономить 2 байта?
FryAmTheEggman

@FryAmTheEggman Я новичок в гольф-сообществе, меняет ли порядок аргументов "кошерный"?
2012rcampion

1
Вы можете на самом деле добраться до 47: IntegerString[#!#2^-#!~IntegerExponent~#2,##2]&(и это, и ваш оригинал довольно быстро)
2012rcampion

Аскер писал: «Порядок ввода целых чисел можно выбрать произвольно». под вводом, так что в этом случае это определенно нормально
FryAmTheEggman

@ Фрай Вау, похоже, я не читал достаточно внимательно. Однако SlotSequenceтрюк, который я использовал в своем комментарии, работает только с текущим порядком, поэтому вы больше не можете сохранить.
2012rcampion

7

Питон, 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]по аналогии.
Рандомра

Для последнего справочная таблица 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 Я добавил исправление, которое, по моему мнению, должно быть достаточным.
Исаак

2

PARI / GP, 43 байта

Скорость торговли для космоса дает этот простой алгоритм:

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

Каждый из тестовых случаев выполняется на моей машине менее чем за секунду.


2

Mathematica - 48 байтов

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

Ungolfed:

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

Bash / coreutils / dc, 60 байт

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

Использует dcскрипт из моего ответа для поиска факториала , выводя в базу $2, sedчтобы обрезать конечные нули и tailвыбрать последние $3цифры.


Я должен признать, что это очень медленно с 40-битным тестом base-2. Я попытался ослабить работу sed, используя revдля уменьшения обратного отслеживания, но это то, dcчто съедает процессор ...
Тоби Спейт

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]

Занимает около 4 секунд f 359221 2 40на моем 4-летнем ноутбуке.

Как это работает: сложите умножение ( *) в список [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тестовом примере. Принимает ввод через аргументы командной строки.


1

до н.э., 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

Время выполнения полного набора тестов составляет примерно 4¼ секунды на моей рабочей станции 2006 года выпуска.


Это моя первая в истории bcпрограмма (гольф или нет), поэтому любые советы особенно приветствуются ...
Тоби Спайт

0

PHP, 80 байт

function f($a,$b,$c){echo substr(rtrim(gmp_strval(gmp_fact($a),$b),"0"),-1*$c);}

Используется как f(359221,2,40)для последнего контрольного примера. Работает довольно гладко для всех тестовых случаев.

Попробуй здесь!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.