Факториальная сумма цифр


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

NB. Некоторые языки не могут поддерживать большие числа выше 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 байт

Новый подход благодаря manatwork:

->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*?+}.
manatwork

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])сохраняет байт
Angs

5

Python, 54 байта

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

repl.it


Я только что пришел с несколько худшей версией этого , который выглядит так слишком похож на то , чтобы быть отдельным ответом. Браво
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,"")сравнению 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: Хе-хе. У меня появилась возможность заглянуть на новый язык :)
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

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

Хорошая идея, но я не совсем понимаю, почему не было бы короче использовать одну функцию для возврата факториала и другую для вычисления суммы цифр, например, a (b (10)). Слово «возврат» слишком длинное, чтобы это сработало?
JollyJoker

Возвращение кушает много. Я пробую это конечно. Может быть, кто-то может сделать это, по крайней мере, я не мог получить эту работу
Текстури

1
Вы можете принять два аргумента для сохранения нескольких байтов: codegolf.stackexchange.com/a/153132/77415
user84207

3

Perl 6 , 21 байт

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

Expanded:

{  # 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.

объяснение

Эта программа состоит из двух циклов. Первый вычисляет факториал ввода, другой разбивает результат на его цифры и складывает их вместе. Затем сумма печатается, и программа заканчивается.

Начало

Сначала нам нужно подготовить стек. Для этой части мы используем первые три инструкции. IP начинается на четвертой строке, указывая на восток. Стек пуст.

      . . .
      . . .
      . . .
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

Python, 57 байт

import math
lambda n:sum(map(int,str(math.factorial(n))))

Попробуйте онлайн


Не могли бы вы использовать обратные галочки вместо str?
Недла2004

2
@ nedla2004 Это добавит, Lкогда факториал станет достаточно большим, чтобы стать длинным.
Каде

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 из-за ограничений целочисленного типа пакета, поэтому в теории я мог бы сохранить байт, предположив 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. Это позволило мне сдвинуть верхние 2 строки на 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.

Ты прав. Я работаю над новой версией. К вашему сведению, я использую quickster.com, потому что другие, которые я обнаружил, некорректно обрабатывали ``, когда в стеке был только один #.
MildlyMilquetoast

Благодарность! Похоже, этот код работает правильно только в версии Befunge-98 , возможно, из-за метода put.
MildlyMilquetoast

48 байтов, которые также обрабатывают 0 правильно
Джо Кинг

2

Javascript ES6 - 61 54 байта

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

РЕДАКТИРОВАТЬ: Спасибо Hedi и ETHproductions за сбрить 7 байтов. Я должен помнить этот трюк.


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`)
Хеди

@ Хеди, я знаю, я делал это по одному шагу за раз :-)
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 байт благодаря Коул!

1#.10#.inv!

Это просто применяет sum ( 1#.) к цифрам (используя обратное invпреобразование базы)#. с основанием 10) факториала ( !) аргумента.

Контрольные примеры

Примечание: последние два контрольных примера - это bigints, отмеченные трейлингом 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;}

Ungolfed и использование:

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.