Estava fazendo uma prova para um estagio como programador/desenvolvedor e aparece esta questão:
Create an algorithm, on your preferred language, that calculates the factorial digit sum. The factorial is represented by the ‘!’ operator. The ‘n’ represents a generic number. The ‘n!’ means n × (n − 1) × … × 3 × 2 × 1 For example, 10! = 10 × 9 × … × 3 × 2 × 1 = 3628800, and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.
Find the factorial in the number 100!
Para explicar a questão, você tem que calcular o fatorial de um numero e logo pegar o resultado e somar cada digito dela. E eles pedem você calcular para o numero 100!, a resposta ta no final caso você queira resolver você mesmo. Em teoria isso é bem fácil de resolver, más como tudo na vida, nada é fácil em pratica.
Agora, eu tinha feito a minha solução ou melhor dito algoritmo no papel. Algoritmo, porque não cheguei a testar o maldito código. Lembrando que todo algoritmo que funciona pra nós, não necessariamente pode funcionar para o computador, em breve explicarei porque.
Esta foi a minha solução para esta questão feito em c#:
class Program
{
static void Main()
{
ulong i,n,fatorial = 1,result = 0;
n = 100;
for(i = 1; i <= n ; i++){
fatorial *= i;
}
Console.WriteLine(fatorial);
do{
result += fatorial % 10;
fatorial = fatorial / 10;
}while(fatorial > 0);
Console.WriteLine(result);
}
}
Agora si você já é um mestre em programação, você vai falar que isso não vai funcionar, e você ta certo. Por que não funciona? A variável ulong (que tem um tamanho de 64 bits ou 8 bytes) não tem o tamanho suficiente para armazenar o fatorial de 100. E qual é o fatorial de 100? 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
É, não é um numero pequeno. Da pra ver porque não caberia em uma variável de 8 bytes, nem na tela do meu site.
E com as maravilhas do .Net, fiz uma solução bem simples.
using System;
using System.Numerics;
namespace FactorialDigitSum
{
class Program
{
static void Main(string[] args)
{
BigInteger factorial = new BigInteger(1);
BigInteger result = new BigInteger(0);
int n = 100;
for (int i = 1; i <= n; i++)
factorial *= i;
do
{
result += factorial % 10;
factorial /= 10;
} while (factorial > 0);
Console.WriteLine("Factorial Digit Sum of " + n + ": " + result.ToString());
}
}
}
Resultado da soma dos dígitos do fatorial de 100! = 648.
Yay, que fácil! É só usar a classe BigInteger que trabalha com números absurdamente grandes, que vai para facilitar a sua vida. E se a prova não quer o uso de qualquer classe e somente o uso de variáveis primitivas? Ai é problema seu, aqui só trabalho com .Net.
Não! Como cientista da computação, devo trazer todas as soluções. Porem viz a versão usando uma lista para armazenar cada digito do resultado fatorial. Assim podendo ser possível calcular números bem maiores.
A idea do método Multiply(int x, List
using System;
using System.Collections.Generic;
using System.Numerics;
namespace FactorialDigitSum
{
class Program
{
static void Main(string[] args)
{
int n = 100;
Console.WriteLine("Factorial Digit Sum of " + n + ": " + CalculateFactorialDigitSum(n));
}
//Metodo usado para multiplicar grandes numeros usando uma lista
public static void Multiply(int x, List<int> bigNum)
{
int remaining = 0, sol;
//Realiza uma multiplicão simples e guarda o sobrante da multiplicacão no remaining
for (int i = bigNum.Count - 1; i >= 0; i--)
{
sol = remaining + bigNum[i] * x;
bigNum[i] = sol % 10;
remaining = sol / 10;
}
//Caso existir sobrante da multiplicação e si o numero tiver o digito maior do que 1 ele vai colocar cada digito em uma posição da lista
while (remaining != 0)
{
bigNum.Insert(0, remaining % 10);
remaining /= 10;
}
}
//Metodo usado para calcular o fatorial de numeros grandes
public static List<int> Factorial(int n)
{
List<int> result = new List<int> { 1 };
if (n == 0)
return result;
//Multiplicação dos valores fatoriais
// 10! = 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x 1
// Cada digito vai ser guardado em uma posição da lista.
for (int i = 1; i <= n; i++)
Multiply(i, result);
return result;
}
//Metodo usado para calcular a soma dos digitos do fatorial de um numero
public static int CalculateFactorialDigitSum(int n)
{
List<int> factorial = Factorial(n);
int result = 0;
//Soma cada digito do resultado do fatorial
for (int i = 0; i < factorial.Count; i++)
result += factorial[i];
return result;
}
}
}