Suma cyfr czynnikowych

25

Wyzwanie polega na obliczeniu sumy cyfr silni liczby.


Przykład

Input: 10
Output: 27

10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, a suma cyfr w liczbie 10! wynosi 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27

Można oczekiwać, że wartość wejściowa będzie liczbą całkowitą powyżej 0. Dane wyjściowe mogą być dowolnego typu, ale odpowiedź powinna znajdować się w standardowej bazie języka kodowania.


Przypadki testowe:

10    27
19    45
469   4140
985   10053

Uwaga: Niektóre języki nie obsługują dużych liczb powyżej 32-bitowych liczb całkowitych; dla tych języków nie będzie wymagane obliczanie dużych silni.

Link OEIS tutaj dzięki Martinowi Enderowi


To jest , więc wygrywa najkrótszy kod w postaci!

Jerzy
źródło
Jakiej maksymalnej liczby wejściowej można się spodziewać? Przy 32-bitowych liczbach całkowitych w R to wyzwanie nie może zostać dokładnie rozwiązanen>21
Billywob,
1
@Billywob W przypadku R musisz tylko przejść do 20. Będę edytować pytanie, aby to odzwierciedlić
George

Odpowiedzi:

11

Galaretka , 3 bajty

!DS

Wypróbuj online!

Czy to, czego oczekujesz:

!    Factorial.
 D   Decimal digits.
  S  Sum.
Martin Ender
źródło
8

Mathematica, 21 bajtów

Tr@IntegerDigits[#!]&
Martin Ender
źródło
4
przyszedł tutaj, aby wpisać dokładne znaki.
Michael Stern
Dlaczego [#!]nie @#!? (Mathematica noob)
Cyoce
1
@Cyoce, ponieważ @ma wyższy priorytet niż !.
Martin Ender
7

C ++ 11, 58 bajtów

Jako nienazwana lambda modyfikująca dane wejściowe:

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

Jeden z nielicznych przypadków, kiedy mój kodu C ++ jest krótszy niż kod C .

Jeśli chcesz obsługiwać większe przypadki, przełącz się na C ++ 14 i użyj:

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

i podaj argument wywołujący z ullprzyrostkiem.

Stosowanie:

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);
}
Karl Napf
źródło
7

Rubinowy, 63 61 53 38 bajtów

Nowe podejście dzięki manatwork:

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

Stary:

->n{(1..n).reduce(:*).to_s.chars.map(&:hex).reduce:+}
  • -3 bajty dzięki Martinowi Enderowi
  • -5 bajtów dzięki GB
TuxCrafting
źródło
1
Stary nudny evalsposób: ->n{eval"#{(1..n).reduce:*}".chars*?+}.
manatwork
6

Pyth, 7 6 bajtów

Dzięki @Kade za uratowanie mi bajtu

sj.!QT

Wypróbuj online!

Po raz pierwszy używam Pytha, więc jestem pewien, że moja odpowiedź mogłaby być dość golfowa.

Wyjaśnienie:

s Sum
  j the digits of
    .! the factorial of
      Q the input
    T in base 10
BookOwl
źródło
1
10jest przypisany do zmiennej T, więc możesz to zrobić sj.!QT:)
Kade
Ok dzięki! Dodam to
BookOwl
Miły! ssM`.!wykonuje też zadanie, również w 6 bajtach.
hakr14
5

Haskell, 41 40 bajtów

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

Przykład użycia: f 985-> 10053.

Stwórz listę od 1do x, oblicz iloczyn elementów listy, przekształć go w reprezentację ciągu, zamień każdy znak na liczbę i zsumuj je.

Edycja: @Angs zapisał bajt. Dzięki!

nimi
źródło
f x=sum$read.pure<$>(show$product[1..x])zapisuje bajt
Angs
5

Python, 54 bajty

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

repl.it

Jonathan Allan
źródło
Właśnie wyszedł z nieco gorszą wersją tego, który wygląda sposób zbyt podobne, aby była ona odrębną odpowiedź. Brawo
osuka_
5

R, 58 53 bajtów

Edycja: Zapisano jeden bajt dzięki @Jonathan Carroll i kilka dzięki @Micky T.

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

Niestety przy 32-bitowych liczbach całkowitych działa to tylko dla n < 22. Pobiera dane wejściowe ze standardowego wejścia i wyjścia na standardowe wyjście.

Jeśli chciałbyś większej precyzji, musiałbyś użyć biblioteki zewnętrznej, takiej jak Rmpfr:

sum(as.numeric(el(strsplit(paste(factorial(Rmpfr::mpfr(scan()))),""))))
Billywob
źródło
1
Dotarłem dokładnie taką samą odpowiedź jak ty, a następnie znaleźć zysk na 1-bajtowy c(x,"")vs paste(x): sum(as.integer(el(strsplit(c(factorial(scan()),""),"")))). Zmusza wynik silni do znaku i strsplitzwraca go jako drugą listę, więc elnadal działa i wyodrębnia pierwsze elementy listy.
Jonathan Carroll
2
jak o prod(1:scan())?
MickyT,
1
też as.double powinno wystarczyć
MickyT
@MickyT Thanks! Zaktualizowano
Billywob
strtoidziała jak krótszy zamiennik as.double, tak myślę.
Giuseppe,
4

Pip , 8 bajtów

$+$*++,a

Wypróbuj online!

Wyjaśnienie

      ,a    # range
    ++      # increment
  $*        # fold multiplication
$+          # fold sum
Emigna
źródło
Niestety, udało mi się opublikować odpowiedź 05AB1E przed tobą;).
Magic Octopus Urn
2
@carusocomputing: Hehe. Mam okazję spojrzeć na nowy język :)
Emigna,
1
Myślę, że jako pierwszy oprócz mnie użyłem Pip do odpowiedzi na golfa bez kodu poliglota. : D
DLosc
4

CJam , 8 bajtów

rim!Ab:+

Wypróbuj online!

Wyjaśnienie

r   e# Read input.
i   e# Convert to integer.
m!  e# Take factorial.
Ab  e# Get decimal digits.
:+  e# Sum.
Martin Ender
źródło
3

Brachylog , 5 bajtów

$!@e+

Wypróbuj online!

Wyjaśnienie

Zasadniczo opisany algorytm:

$!       Take the factorial of the Input
  @e     Take the elements of this factorial (i.e. its digits)
    +    Output is the sum of those elements
Fatalizować
źródło
3

Java 7, 148 bajtów

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;
jacksonecac
źródło
@EyalLev W pytaniu nie określono limitu. Jak długo oczekujesz, aby obsłużyć silnię, która jest większa niż 9 223 372 036 854 775 807?
jacksonecac
3

Rubinowy, 63 60 53 51 bajtów

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

Podziękowania dla Martina za pomoc w grze w golfa.

GB
źródło
3

Pushy , 4 bajty

fsS#

Swój wkład w wierszu poleceń: $ pushy facsum.pshy 5. Oto podział:

f      % Factorial of input
 s     % Split into digits
  S    % Push sum of stack
   #   % Output
FlipTack
źródło
3

Oktawa, 30 bajtów

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

Oblicza silnię, biorąc iloczyn listy [1 2 ... n]. Konwertuje go na ciąg znaków i odejmuje 48od wszystkich elementów (dla kodu ASCII 0). Wreszcie podsumowuje :)

Stewie Griffin
źródło
3

bash (seq, bc, fold, jq), 34 33 bajty

Na pewno nie najbardziej elegancki, ale do wyzwania

seq -s\* $1|bc|fold -1|jq -s add
Adam
źródło
fold -1zapisuje bajt.
Cyfrowa trauma
@DigitalTrauma poprawiony! dzięki
Adam,
3

C, 58 bajtów

To nie jest idealne. Działa tylko, ponieważ na początku musi być -1. Chodzi o to, aby użyć dwóch funkcji rekurencyjnych w jednej funkcji. To nie było tak proste, jak myślałem na początku.

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

Zastosowanie i zrozumiały format:

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

Edycja: Znalazłem metodę, która pozwala używać tej funkcji wiele razy, ale długość wynosi 62 bajty.

a,b;k(i){a=b?a:i+(--b);return a?k(i*a--):i?i%10+k(i/10):++b;}
teksturi
źródło
Fajny pomysł, ale nie do końca rozumiem, dlaczego nie byłoby krótsze użycie jednej funkcji do zwrócenia silni, a innej do obliczenia sumy cyfr, na przykład a (b (10)). Czy słowo „powrót” jest zbyt długie, aby zadziałało?
JollyJoker,
Return je dużo. Próbuję tego oczywiście. Może ktoś może to zrobić, przynajmniej nie mogłem dostać tej pracy
teksturi
1
możesz zaakceptować dwa argumenty, aby zaoszczędzić kilka bajtów: codegolf.stackexchange.com/a/153132/77415
user84207
3

Perl 6 , 21 bajtów

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

Rozszerzony:

{  # 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
}
Brad Gilbert b2gills
źródło
Gratulacje, masz odpowiedź nie. 101010!
RudolfJelin
@ RudolfL.Jelínek To nic, na StackOverflow i Meta.StackExchange Jestem numerem użytkownika 1337
Brad Gilbert b2gills
3

Cubix, 33 32 bajty

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

Formularz netto:

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

Wypróbuj online!

Notatki

  • Działa z danymi wejściowymi do 170 włącznie, co powoduje powstanie nieskończonej pętli, ponieważ ich silnia daje Infinityliczbę (technicznie rzecz biorąc, jest to nie do zapisania, nie do wyliczenia i nie do skonfigurowania właściwość obiektu okna).
  • Dokładność jest tracona dla danych wejściowych 19 i wyższych, ponieważ liczb wyższych niż 2 53 (= 9 007 199 254 740 992) nie można dokładnie zapisać w JavaScript.

Wyjaśnienie

Ten program składa się z dwóch pętli. Pierwszy oblicza silnię danych wejściowych, drugi dzieli wynik na cyfry i dodaje je do siebie. Następnie suma jest drukowana i program kończy się.

Początek

Najpierw musimy przygotować stos. W tej części wykorzystujemy pierwsze trzy instrukcje. IP zaczyna się na czwartej linii, wskazując na wschód. Stos jest pusty.

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

Będziemy trzymać sumę na samym dole stosu, więc musimy zacząć od 0bycia sumą, przechowując ją na dole stosu. Następnie musimy nacisnąć a 1, ponieważ dane wejściowe zostaną początkowo pomnożone przez liczbę przed nim. Gdyby było to zero, silnia również zawsze dawałaby zero. Na koniec odczytujemy dane wejściowe jako liczbę całkowitą.

Teraz stos jest, [0, 1, input]a adres IP znajduje się w czwartej linii, czwartej kolumnie, skierowanej na wschód.

Pętla czynnikowa

Jest to prosta pętla, która zwielokrotnia dwa górne elementy stosu (wynik poprzedniej pętli i danych wejściowych - n, a następnie zmniejsza dane wejściowe. Łamie się, gdy dane wejściowe osiągną 0. $Instrukcja powoduje, że IP pomija u- turn Pętla jest następującą częścią sześcianu: IP zaczyna się od czwartej linii, czwartej kolumny.

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

Z powodu tej ^postaci IP natychmiast zaczyna się poruszać na północ. Następnie uodwraca adres IP i przesuwa go jeden w prawo. Na dole znajduje się kolejna strzałka: <wskazuje adres IP z powrotem na ^. Stos zaczyna się od [previousresult, input-n], gdzie, gdzie njest liczba iteracji. W pętli wykonywane są następujące znaki:

*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]

Następnie górna część stosu (zmniejszone wejście) jest sprawdzana 0przez !instrukcję, a jeśli tak 0, uznak jest pomijany.

Zsumuj cyfry

IP otacza sześcian, kończąc na ostatnim znaku w czwartej linii, początkowo wskazując na zachód. Następująca pętla składa się z prawie wszystkich pozostałych znaków:

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

Pętla najpierw usuwa element górny ze stosu (który jest albo 10albo 0), a następnie sprawdza, co jest na lewo od wyniku silni. Jeśli to zostało zmniejszone 0, drukowane jest dno stosu (suma) i program zatrzymuje się. W przeciwnym razie zostaną wykonane następujące instrukcje (stos zaczyna się jako [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]

Pętla zaczyna się od nowa, aż do factorial/10zera.

Luke
źródło
3

C, 47 bajtów

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

stosowanie:

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));
}
użytkownik84207
źródło
2

Python, 57 bajtów

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

Wypróbuj online

mbomb007
źródło
Czy możesz użyć tykających znaków zamiast str?
nedla2004
2
@ nedla2004 To by Lsię stało, gdy silnia jest wystarczająco duża, aby stać się długim.
Kade
2

Partia, 112 bajtów

@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%

Dogodnie set/adziała na bieżącej wartości zmiennej, więc działa normalnie w pętli. Działa tylko do 12 ze względu na ograniczenia typu liczb całkowitych Batcha, więc teoretycznie mogę zapisać bajt, zakładając 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%

Ale w ten sposób leży szaleństwo ... Równie dobrze mogę w tym przypadku zakodować listę (97 bajtów):

@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
Neil
źródło
2

JavaScript (ES6), 50 bajtów

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

Działa tylko n=22ze względu na ograniczenia dokładności zmiennoprzecinkowej.

Neil
źródło
2

Befunge 93 , 56 54 bajtów

Zaoszczędzono 2 bajty, aby użyć get zamiast cudzysłowów. To pozwoliło mi przesunąć górne 2 linie o 1, zmniejszając niepotrzebne białe miejsca.

Wypróbuj online!

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

Wyjaśnienie:

&#:<                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.
Łagodnie Milquetoast
źródło
Masz rację. Pracuję nad nową wersją. Do Twojej wiadomości używam quickster.com, ponieważ inni, których znalazłem, nie traktowali poprawnie `` gdy na stosie był tylko jeden #.
MildlyMilquetoast
Dzięki! Wygląda na to, że ten kod działa poprawnie tylko w wersji Befunge-98 , prawdopodobnie z powodu metody put.
MildlyMilquetoast
48 bajtów, które również poprawnie obsługują 0
Jo King
2

JavaScript ES6 - 61 54 bajtów

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

EDYCJA: Dziękuję Hedi i ETHproductions za odcięcie 7 bajtów. Muszę pamiętać, że sztuczka t - = - j.

Marcus Dirr
źródło
1
Niezła odpowiedź! Możesz zapisać kilka bajtów na różne sposoby:n=>{a=_=>!_||_*a(~-_);t=0;for(j of''+a(n))t-=-j;return t}
ETHprodukcje
@ETHproductions Niektóre bajty można zapisać za pomocą eval:n=>eval(`for(j of''+(a=_=>!_||_*a(~-_))(n,t=0))t-=-j`)
Hedi,
@Hedi Wiem, robiłem to krok po kroku :-)
ETHproductions
2

AHK , 60 bajtów

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

AutoHotkey nie ma wbudowanej funkcji silni, a funkcje pętli mają długie nazwy dla wbudowanych zmiennych. Pierwsza pętla jest silnia, a druga dodaje cyfry razem.

Inżynier Toast
źródło
2

J, 12 11 bajtów

Oszczędność 1 bajtu dzięki Cole!

1#.10#.inv!

To po prostu stosuje sumę ( 1#.) do cyfr (przy użyciu odwrotnościinv konwersji podstawy #.z podstawą 10) silni ( !) argumentu.

Przypadki testowe

Uwaga: dwa ostatnie przypadki testowe to biginty, oznaczone znakiem końcowym x.

   f=:10#.inv!
   (,. f"0) 10 19 469x 985x
 10    27
 19    45
469  4140
985 10053
Conor O'Brien
źródło
Możesz użyć, "."0":aby uzyskać cyfry
Bolce Bussiere
11 bajtów: 1#.,.&.":@!co wymaga większej precyzji także w przypadku mniejszych przypadków (nie wiadomo dlaczego). Również 11 bajtów: 1#.10#.inv!.
cole
1

C, 63 60 bajtów

-3 bajt na do...whilepętlę.

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

Niegolfowane i użycie:

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

main() {
 printf("%d\n",f(10));
}
Karl Napf
źródło
Czy intdomyślnie definiujemy f (n) ?
Mukul Kumar
@MukulKumar jest to standard w C, jeśli nie ma typu, intzakłada się.
Karl Napf,