Факторна цифра


25

Завдання полягає в тому, щоб обчислити розрядну суму факторіалу числа.


Приклад

Input: 10
Output: 27

10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, а сума цифр у числі 10! дорівнює 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27

Ви можете очікувати, що вхід буде цілим числом більше 0. Вихід може бути будь-якого типу, але відповідь має бути в стандартній базі мови кодування.


Тестові приклади:

10    27
19    45
469   4140
985   10053

Примітка: Деякі мови не можуть підтримувати велику кількість вище 32-бітних цілих чисел; для цих мов від вас не очікується обчислення великих фабрик.

Тут посилання на OEIS завдяки Мартіну Ендеру


Це , тому найкоротший код у символах виграє!


Яке максимальне число входу очікувати? З 32-бітовими цілими числами в R цей виклик неможливо точно вирішитиn>21
Billywob

1
@Billywob Для R тоді вам потрібно буде лише перейти до 20. Я відредагую питання, щоб це відобразити
Джордж

Відповіді:





7

C ++ 11, 58 байт

Як безіменна лямбда змінює свій вхід:

[](int&n){int i=n;while(--n)i*=n;do n+=i%10;while(i/=10);}

Один з рідкісних випадків , коли мій C ++ код коротше , ніж код C .

Якщо ви хочете підтримати більші регістри, перейдіть на C ++ 14 і скористайтеся:

[](auto&n){auto i=n;while(--n)i*=n;do n+=i%10;while(i/=10);}

і надайте аргумент виклику ullсуфіксом.

Використання:

auto f=
[](int&n){int i=n;while(--n)i*=n;do n+=i%10;while(i/=10);}
;

main() {
  int n=10;
  f(n);
  printf("%d\n",n);
}

7

Рубі, 63 61 53 38 байт

Новий підхід завдяки манатурності:

->n{eval"#{(1..n).reduce:*}".chars*?+}

Старий:

->n{(1..n).reduce(:*).to_s.chars.map(&:hex).reduce:+}
  • -3 байти завдяки Мартіну Ендеру
  • -5 байт завдяки ГБ

1
Старий нудний evalспосіб: ->n{eval"#{(1..n).reduce:*}".chars*?+}.
манатурка

6

Pyth, 7 6 байт

Дякую @Kade, що врятував мені байт

sj.!QT

Спробуйте в Інтернеті!

Це мій перший раз, коли я використовую Pyth, тож я впевнений, що моя відповідь могла би бути зовсім небагатою.

Пояснення:

s Sum
  j the digits of
    .! the factorial of
      Q the input
    T in base 10

1
10присвоюється змінній T, тому ви можете зробити це sj.!QT:)
Kade

Добре, дякую! Додам
BookOwl

Приємно! ssM`.!виконує завдання також у 6 байт.
hakr14

5

Haskell, 41 40 байт

f x=sum$read.pure<$>(show$product[1..x])

Приклад використання: f 985-> 10053.

Складіть список від 1до x, обчисліть добуток елементів списку, перетворіть його на його рядкове подання, перетворіть кожен символ у число і підсумуйте їх.

Редагувати: @Angs зберегло байт. Спасибі!


f x=sum$read.pure<$>(show$product[1..x])рятує байт
ангс

5

Пітон, 54 байти

f=lambda n,r=1:n and f(n-1,r*n)or sum(map(int,str(r)))

repl.it


Я тільки що прийшов з кілька гіршою версією цього , який виглядає шлях надто схожий на те , щоб бути окремим відповіддю. Bravo
osuka_

5

R, 58 53 байти

Редагувати: Збережено один байт завдяки @Jonathan Carroll та пару завдяки @Micky T

sum(as.double(el(strsplit(c(prod(1:scan()),""),""))))

На жаль, з 32-бітовими цілими числами це працює лише для цього n < 22. Приймає введення з stdin та виводить у stdout.

Якщо ви хочете отримати більш високий рівень точності, доведеться використовувати зовнішню бібліотеку, таку як Rmpfr:

sum(as.numeric(el(strsplit(paste(factorial(Rmpfr::mpfr(scan()))),""))))

1
Я дійшов до такої самої відповіді, що і ви, а потім знайшов посилення в 1 байті на c(x,"")vs paste(x): sum(as.integer(el(strsplit(c(factorial(scan()),""),"")))). Примушує факторний результат до символу і strsplitповертає його як другий список, тому elвсе ще працює і витягує елементи першого списку.
Джонатан Керролл

2
як щодо prod(1:scan())?
MickyT

1
теж as.double повинно вистачити
MickyT

@MickyT Дякую! Оновлено.
Billywob

strtoiпрацює як коротша заміна as.double, я думаю.
Джузеппе

4

Піп , 8 байт

$+$*++,a

Спробуйте в Інтернеті!

Пояснення

      ,a    # range
    ++      # increment
  $*        # fold multiplication
$+          # fold sum

На жаль, мені вдалося опублікувати відповідь 05AB1E перед вами;).
Чарівний восьминіг Урна

2
@carusocomputing: Hehe. Отримав мені можливість заглянути нову мову :)
Emigna

1
Я думаю, що ти перший, окрім мене, застосував Піп для відповіді на гольф на поліглот. : D
DLosc



3

Java 7, 148 байт

int s=1,ret=0;while(i>1){s=s*i; i--;}String y=String.valueOf(s);for(int j=0;j<y.length();j++){ret+=Integer.parseInt(y.substring(j,j+1));}return ret;

@EyalLev У питанні немає обмежень. Як ви очікуєте довго працювати з фабрикою, яка дорівнює більшій, ніж 9,223,372,036,854,775,807?
jacksonecac

3

Рубі, 63 60 53 51 байт

->n{a=0;f=(1..n).reduce:*;f.times{a+=f%10;f/=10};a}

Дякую Мартіну за допомогу в гольфі.


3

Пушистий , 4 байти

fsS#

Дайте введення в командному рядку: $ pushy facsum.pshy 5. Ось поділка:

f      % Factorial of input
 s     % Split into digits
  S    % Push sum of stack
   #   % Output

3

Октава, 30 байт

@(n)sum(num2str(prod(1:n))-48)

Обчислює факторіал, беручи добуток списку [1 2 ... n]. Перетворює його в рядок і віднімає 48з усіх елементів (ASCII код для 0). Нарешті це підсумовує :)


3

bash (seq, bc, fold, jq), 34 33 байт

Безумовно, не найелегантніше, але для виклику

seq -s\* $1|bc|fold -1|jq -s add

fold -1зберігає байт.
Цифрова травма

@DigitalTrauma виправлено! дякую
Адам

3

C, 58 байт

Це не ідеально. Працює лише тим, що на початку має бути -1. Ідея полягає у використанні двох рекурсивних функцій в одній функції. Це було не так просто, як я спершу подумав.

a=-1;k(i){a=a<0?i-1:a;return a?k(i*a--):i?i%10+k(i/10):0;}

Використання та зрозумілий формат:

a = -1;
k(i){
   a = a<0 ? i-1 : a;
   return a ? k(i*a--) : i? i%10+k(i/10) :0;
}

main() {
   printf("%d\n",k(10));
}

Редагувати: Я знайшов методи, які дозволяють використовувати цю функцію кілька разів, але тоді довжина становить 62 байти.

a,b;k(i){a=b?a:i+(--b);return a?k(i*a--):i?i%10+k(i/10):++b;}

Хороша ідея, але я не зовсім розумію, чому не було б коротше використовувати одну функцію для повернення факторіалу, а іншу для обчислення цифрної суми, як (b (10)). Чи занадто довго слово "повернутись", щоб воно працювало?
JollyJoker

Повернення їсть багато. Я це намагаюся, звичайно. Можливо, хтось може це зробити, принаймні я не міг би отримати цю роботу
текстурі

1
ви можете прийняти два аргументи, щоб зберегти кілька байтів: codegolf.stackexchange.com/a/153132/77415
користувач84207

3

Perl 6 , 21 байт

{[+] [*](2..$_).comb}

Розширено:

{  # bare block lambda with implicit parameter 「$_」

  [+]           # reduce the following with 「&infix:<+>」

    [*](        # reduce with 「&infix:<*>」
      2 .. $_   # a Range that include the numbers from 2 to the input (inclusive)
    ).comb      # split the product into digits
}

З повагою, ви отримали відповідь "ні". 101010!
РудольфДжелін

@ RudolfL.Jelínek Це нічого, на StackOverflow та Meta.StackExchange Я номер користувача 1337
Бред Гілберт b2gills

3

Cubix, 33 32 байти

u*.$s.!(.01I^<W%NW!;<,;;q+p@Opus

Чиста форма:

      u * .
      $ s .
      ! ( .
0 1 I ^ < W % N W ! ; <
, ; ; q + p @ O p u s .
. . . . . . . . . . . .
      . . .
      . . .
      . . .

Спробуйте в Інтернеті!

Примітки

  • Робота з входами до і включаючи 170, більш високі входи призводять до нескінченного циклу, тому що їх фабрика дає Infinityкількість (технічно кажучи, це незаписувана, не перелічувана і не конфігурувана властивість віконного об'єкта).
  • Точність для входів 19 і вище втрачається, тому що числа, які перевищують 2 53 (= 9 007 199 254 740 992), не можуть бути точно збережені в JavaScript.

Пояснення

Ця програма складається з двох циклів. Перший обчислює коефіцієнт введення, другий розбиває результат на його цифри і додає їх разом. Потім сума друкується, і програма закінчується.

Старт

Спочатку нам потрібно підготувати стек. Для цієї частини ми використовуємо перші три вказівки. ІС починається з четвертої лінії, вказуючи на схід. Стек порожній.

      . . .
      . . .
      . . .
0 1 I . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
      . . .
      . . .
      . . .

Ми збережемо суму в самому нижній частині стека, тому нам потрібно почати з 0суми, зберігаючи її в нижній частині стека. Тоді нам потрібно натиснути a 1, тому що вхід спочатку буде помножений на число перед ним. Якби це дорівнювало нулю, факториал завжди також давав би нуль. Нарешті ми читаємо введення як ціле число.

Тепер стек є, [0, 1, input]і IP знаходиться на четвертому рядку, четвертому стовпчику, вказує на схід.

Факторна петля

Це простий цикл, який примножує два верхні елементи елемента стека (результат попереднього циклу та введення - n, а потім зменшує вхід. Він руйнується, коли вхід досягне 0. $Інструкція змушує IP пропустити u- петля - це наступна частина куба. IP починається з четвертого рядка, четвертого стовпця.

      u * .
      $ s .
      ! ( .
. . . ^ < . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
      . . .
      . . .
      . . .

Через ^характер, IP починає рухатися на північ негайно. Потім uобертає IP навколо і переміщує його вправо. Внизу є ще одна стрілка: <вказує IP назад у ^. Стек починається як [previousresult, input-n], де nкількість ітерацій. У циклі виконуються наступні символи:

*s(
*   # Multiply the top two items
    #   Stack: [previousresult, input-n, newresult]
 s  # Swap the top two items
    #   Stack: [previousresult, newresult, input-n]
  ( # Decrement the top item
    #   Stack: [previousresult, newresult, input-n-1]

Потім у верхній частині стеки (зменшився введення) звіряються 0з !інструкції, і якщо вона 0, то uперсонаж буде пропущений.

Підсумуйте цифри

IP обертається навколо куба, закінчуючи останнім символом на четвертому рядку, спочатку вказуючи на захід. Наступний цикл складається майже з усіх символів, що залишилися:

      . . .
      . . .
      . . .
. . . . . W % N W ! ; <
, ; ; q + p @ O p u s .
. . . . . . . . . . . .
      . . .
      . . .
      . . .

Цикл спочатку видаляє верхній елемент із стека (який є 10або 0), а потім перевіряє, що залишилося від результату факториуму. Якщо це було зменшено до 0, друкується нижня частина стека (сума) і програма зупиняється. В іншому випадку виконуються такі інструкції (стек починається як [oldsum, ..., factorial]):

N%p+q;;,s;
N          # Push 10
           #   Stack: [oldsum, ..., factorial, 10]
 %         # Push factorial % 10
           #   Stack: [oldsum, ..., factorial, 10, factorial % 10]
  p        # Take the sum to the top
           #   Stack: [..., factorial, 10, factorial % 10, oldsum]
   +       # Add top items together
           #   Stack: [..., factorial, 10, factorial % 10, oldsum, newsum]
    q      # Send that to the bottom
           #   Stack: [newsum, ..., factorial, 10, factorial % 10, oldsum]
     ;;    # Delete top two items
           #   Stack: [newsum, ..., factorial, 10]
       ,   # Integer divide top two items
           #   Stack: [newsum, ..., factorial, 10, factorial/10]
        s; # Delete the second item
           #   Stack: [newsum, ..., factorial, factorial/10]

І цикл починається знову, factorial/10дорівнює 0.


3

C, 47 байт

f(n,a){return n?f(n-1,a*n):a?a%10+f(0,a/10):0;}

використання:

f(n,a){return n?f(n-1,a*n):a?a%10+f(0,a/10):0;}
main() {
  printf("answer: %d\n",f(10,1));
}


2

Пакетна, 112 байт

@set/af=1,t=0
@for /l %%i in (1,1,%1)do @set/af*=%%i
:g
@set/at+=f%%10,f/=10
@if %f% gtr 0 goto g
@echo %t%

Зручно set/aпрацює на поточному значенні змінної, тому вона працює нормально всередині циклу. Працює лише до 12 через обмеження цілого типу Batch, тому теоретично я міг би зберегти байт, вважаючи f<1e9:

@set/af=1,t=0
@for /l %%i in (1,1,%1)do @set/af*=%%i
@for /l %%i in (1,1,9)do @set/at+=f%%10,f/=10
@echo %t%

Але таким чином лежить божевілля ... Я можу так само важко зашифрувати список у цьому випадку (97 байт):

@call:l %1 1 1 2 6 6 3 9 9 9 27 27 36 27
@exit/b
:l
@for /l %%i in (1,1,%1)do @shift
@echo %2

2

JavaScript (ES6), 50 байт

f=(n,m=1,t=0)=>n?f(n-1,n*m):m?f(n,m/10|0,t+m%10):t

Працює лише n=22через обмеження точності з плаваючою комою.


2

Befunge 93 , 56 54 байт

Збережені 2 байти робити з використанням get замість лапок. Це дозволить мені перенести перші два рядки на 1, зменшуючи зайвий пробіл.

Спробуйте в Інтернеті!

&#:<_v#:-1
: \*$<:_^#
g::v>91+%+00
_v#<^p00</+19
@>$$.

Пояснення:

&#:<                Gets an integer input (n), and reverses flow direction
&#:< _v#:-1         Pushes n through 0 onto the stack (descending order)

:  \*$<:_^#         Throws the 0 away and multiplies all the remaining numbers together

(reorganized to better show program flow):
vp00< /+19 _v#<    Stores the factorial at cell (0, 0). Pushes 3 of whatever's in
> 91+%+ 00g ::^    cell (0, 0). Pops a, and stores a / 10 at (0, 0),
                   and adds a % 10 to the sum.

@>$$.              Simply discards 2 unneeded 0s and prints the sum.

Ви праві. Я працюю над новою версією. FYI, я використовую quickster.com, тому що інші, яких я знайшов, не поводились `` правильно, коли в стеку був лише один #.
MildlyMilquetoast

Спасибі! Схоже, цей код працює належним чином лише у версії Befunge-98 , ймовірно, через метод put.
MildlyMilquetoast

48 байт, які також обробляють 0 правильно
Jo King

2

Javascript ES6 - 61 54 байт

n=>eval(`for(j of''+(a=_=>!_||_*a(~-_))(n,t=0))t-=-j`)

EDIT: Дякую Hedi та ETHproductions за бриття 7 байт. Мені доведеться пам'ятати, що т - = - j трюк.


1
Гарна відповідь! Ви можете зберегти пару байтів різними способами:n=>{a=_=>!_||_*a(~-_);t=0;for(j of''+a(n))t-=-j;return t}
ETHproductions

@ETHproductions Ще кілька байтів можна зберегти за допомогою eval:n=>eval(`for(j of''+(a=_=>!_||_*a(~-_))(n,t=0))t-=-j`)
Hedi,

@Hedi Я знаю, я робив це крок за часом :-)
ETHproductions

2

AHK , 60 байт

a=1
Loop,%1%
a*=A_Index
Loop,Parse,a
b+=A_LoopField
Send,%b%

AutoHotkey не має вбудованої факториальної функції, а функції циклу мають довгі назви вбудованих змінних. Перший цикл є факторіальним, а другий - додаванням цифр разом.


2

J, 12 11 байт

Збережено 1 байт завдяки Cole!

1#.10#.inv!

Це просто застосовується sum ( 1#.) до цифр (використовуючи обернене invбазове перетворення#. бази на базу 10) факторіального ( !) аргументу.

Тестові справи

Примітка. Останні два тестових випадки - це бігтінги, як вони позначені проривом x.

   f=:10#.inv!
   (,. f"0) 10 19 469x 985x
 10    27
 19    45
469  4140
985 10053

Ви можете використовувати "."0":цифри
Bolce Bussiere

11 байт: 1#.,.&.":@!що вимагає розширеної точності і для менших випадків (не знаю чому). Також 11 байт: 1#.10#.inv!.
Коул


1

C, 63 60 байт

-3 байт для do...whileциклу.

i;f(n){i=n;while(--n)i*=n;do n+=i%10;while(i/=10);return n;}

Безголівки та використання:

i;
f(n){
 i=n;
 while(--n)
  i*=n;
 do
  n+=i%10;
 while(i/=10);
 return n;
}

main() {
 printf("%d\n",f(10));
}

Чи визначимо f (n) intза замовчуванням?
Мукул Кумар

@MukulKumar це стандарт у C, якщо немає типу, тоді intпередбачається.
Карл Напф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.