Project Euler # 8, я не понимаю, где я ошибаюсь

Я работаю над проблемой эйлера проекта №8, в которой я получил это смехотворно большое число:

73167176531330624919225119674426574742355349194934 96983520312774506326239578318016984801869478851843 85861560789112949495459501737958331952853208805511 12540698747158523863050715693290963295227443043557 66896648950445244523161731856403098711121722383113 62229893423380308135336276614282806444486645238749 30358907296290491560440772390713810515859307960866 70172427121883998797908792274921901699720888093776 65727333001053367881220235421809751254540594752243 52584907711670556013604839586446706324415722155397 53697817977846174064955149290862569321978468622482 83972241375657056057490261407972968652414535100474 82166370484403199890008895243450658541227588666881 16427171479924442928230863465674813919123162824586 17866458359124566529476545682848912883142607690042 24219022671055626321111109370544217506941658960408 07198403850962455444362981230987879927244284909188 84580156166097919133875499200524063689912560717606 05886116467109405077541002256983155200055935729725 71636269561882670428252483600823257530420752963450

и я должен "найти тринадцать смежных цифр в 1000-значном числе, которые имеют наибольший продукт". EG произведение первых четырех смежных цифр 7 * 3 * 1 * 6. Мой код следующий:

int main()
{
    string num = /* ridiculously large number omitted */;
    int greatestProduct = 0;
    int product;
    for (int i=0; i < num.length() -12; i++)
    {
        product = ((int) num[i] - 48);
        for (int j=i+1; j<i+13; j++)
        {
            product = product * ((int) num[j] - 48);
            if (greatestProduct <= product)
            {
                greatestProduct = product;
            }
        }
    }
    cout << greatestProduct << endl;
}

Я продолжаю получать 2091059712 как ответ, который эйлер проекта сообщает мне, что это неправильно, и я подозреваю, что он слишком велик. Любая помощь будет оценена.

EDIT: изменено на unsigned long int, и оно сработало. Спасибо всем!

Ответы

Ответ 1

На самом деле ваше решение слишком мало, а не слишком велико. Ответ заключается в том, что было отмечено в комментариях, что существует целочисленное переполнение, и ключ заключается в том, что ваше решение близко к максимально возможному значению для подписанного int: 2147483647. Для хранения нужно использовать другой тип для хранения продукт.

Обратите внимание, что приведенный ниже ответ по-прежнему "правильный" в том, что ваш код делает это неправильно, но это не то, что вызывает неправильное значение. Попробуйте взять ваш (рабочий) код на http://codereview.stackexchange.com, если вы хотите, чтобы люди там рассказывали вам, что вы могли бы улучшить в своем подходе и в вашем стиле кодирования.

Предыдущий ответ

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

Это может иметь значение, если вы находите строку, которая имеет менее 13 цифр, которые имеют большой продукт, но 0 с обоих концов. Вы не должны считать это самым большим, но ваш код. (Я не проверял, действительно ли это происходит.)

for (int i=0; i < num.length() -12; i++)
{
    product = ((int) num[i] - 48);
    for (int j=i+1; j<i+13; j++)
    {
        product = product * ((int) num[j] - 48);
    }
    if (greatestProduct <= product)
    {
        greatestProduct = product;
    }
}

Ответ 2

9 ^ 13 ≈ 2.54e12 (максимальное возможное значение, требуется 42 бит, которое должно быть представлено точно), которое не вписывается в signed int. Вы должны использовать int64.

Ответ 3

Если вы не хотите общаться с библиотеками BigNum, вы можете просто взять логарифмы ваших цифр (отклонение 0) и добавить их. Это равноценное сравнение.

Ответ 4

У меня такая же проблема. int product и int mostproduct имеют максимальное значение, которое он может хранить, поскольку они имеют тип int. Они могут хранить значения только до 2147483647.

Используйте тип long long вместо int.

Ответ 5

Более быстрый способ без внутреннего цикла, но работает только там, где на входе нет 0:

long long greatest(string num)
{
    if (num.length() < 13)
        return 0;

    // Find a product of first 13 numbers.
    long long product = 1;
    unsigned int i;
    for (i=0; i<13; ++i) {
        product *= (num[i]-'0');
    }
    long long greatest_product = product;
    // move through the large number
    for (i=0; i+13<num.length(); ++i) {
        product = product/(num[i]-'0')*(num[i+13]-'0');
        if (greatest_product < product)
            greatest_product = product;
    }
    return greatest_product;
}

Чтобы сделать эту работу с входами, содержащими 0, разделите входную строку на подстроки:

int main()
{
    string num = /* input value*/;

    long long greatest_product = 0;
    size_t start = -1;
    // Iterate over substrings without zero
    do {
        ++start;
        size_t end = num.find('0', start);
        long long product = greatest(num.substr(start, end-start));
        if (greatest_product < product)
            greatest_product = product;
        start = end;
    } while (start != string::npos);

    cout << greatest_product << endl;
}

Ответ 6

Несмотря на то, что выше решения хороши, вот реализация python, которая отлично работает:

def main():
      num=7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
      prod,maxprod=1,0
      numtostr=str(num)
      length=len(numtostr)
      for i in range(1,length-13+1):
          prod=1
          for z in range(i,i+13):
              prod=prod*int(numtostr[z-1:z])
              if prod>maxprod:
                  maxprod=prod
      print "Largest 13 digit product is %d" %(maxprod)

 if __name__ == '__main__':
       main()

Ответ 7

static long q8(){
        long max_product = 1;
        long product = 1;
        String n = "LONG_INPUT";
        for(int i=0;i<13;i++){
            max_product *= Integer.parseInt(n.charAt(i)+"");
        }
        product = max_product;
        for(int i=1;i<n.length()-13;i++){
            int denom = Integer.parseInt(n.charAt(i-1)+"");
            if(denom!=0)
                product = product/denom * Integer.parseInt(n.charAt(i+12)+"");
            else
                product = product(i,n);
            max_product = (max_product>product)?max_product:product;
        }

        return max_product;
    }
    static long product(int index,String n){
        long pro = 1;
        for(int i=index;i<index+13;i++){
            pro *= Integer.parseInt(n.charAt(i)+"");
        }
        return pro;
    }

Ответ 8

Попробуйте следующее:

    {
        DateTime BeganAt = new DateTime();

        BeganAt = DateTime.Now;

        Int64 result = 0;

        string testNumber = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";

        StringBuilder StringBuilder = new StringBuilder(13);

        Int64 maxNumber = 0;

        try
        {
            char[] numbers = testNumber.ToCharArray();

            int tempCounter = 13;

            for (int i = 0;i < numbers.Length;i++)
            {
                if(i < tempCounter)
                {
                    StringBuilder.Append(numbers[i]);
                }
                else if (i == tempCounter)
                {
                    if (maxNumber < Convert.ToInt64(StringBuilder.ToString()))
                    {
                        maxNumber = Convert.ToInt64(StringBuilder.ToString());
                    }

                    StringBuilder.Clear();
                    StringBuilder.Append(numbers[i]);
                    tempCounter = tempCounter + n;
                }
            }

            result = maxNumber;
        }
        catch
        {
            throw;
        }

        DateTime EndedAt = new DateTime();

        EndedAt = DateTime.Now;

        TimeSpan TimeItTook = (EndedAt - BeganAt);

        return Convert.ToString(result) + " - Time took to execute: " + Convert.ToString(TimeItTook.TotalMilliseconds);
    }

Ответ 9

Мое функциональное программирующее решение

def product(number):
    product_result = 1
    for n in number:
        product_result *= int(n)
    return product_result

length = 13
indices = range(0, len(number) - 13 + 1)
values = indices
values = map(lambda index: {"index": index, "number": number}, values)
values = map(lambda value: value["number"][value["index"]:value["index"] + length], values)
values = map(product, values)
values = max(values)
print values

Ответ 10

public static void main(String[] args) {

    String val = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";

    int Sum = 0;
    String adjacent  = null;
    for (int i = 0; i < val.length()-13; i++) {

        int total = 1;
        for (int j = 0; j < 13; j++) {
            total = total * Character.getNumericValue(val.charAt(i+j));
        }

        if(total > Sum){
            Sum = total;
            adjacent  = val.substring(i, i+13);
        }

    }

    System.out.println("Sum = " + Sum);
    System.out.println("Adjsc = " + adjacent );

}

Ответ 11

long long int sum = 1,high=0;

for (int i = 0; i < 988; i++)
{
    sum = sum*(arr[i] - 48);
    for (int j = i + 1; j < i+13; j++)
    {
        sum = sum*(arr[j]-48);
    }
    if (sum >= high)
    {
        high = sum;
    }
    sum = 1;
}   

Ответ 12

Мое решение вышеуказанной проблемы, если кто-то все еще наблюдает за этим в 2018 году. Хотя здесь есть много вариантов решения этого вопроса, мое решение предварительно проверяет отдельные 13 цифр, в которых есть 0. Поскольку что-то умноженное на 0 всегда равно 0, поэтому мы можно удалить это бесполезное вычисление

int j = 0, k = 12;
long long int mult = 1;
long long int max = 0;
char *digits = /*Big number*/
while(k < 1000){
    for (int i = j; i <= k; ++i)
    {
        /* code */
        long long int val = digits[i] -'0';
        /* check if any number in series contains 0 */
        if(val == 0){
            break;
        }
        mult = mult * val;
    }
    printf("mult is %lld\n",mult );
     /* check for max value */
    if(max < mult){
        max = mult;
    }
    printf("the new max is %lld\n", max);
    j += 1;
    k += 1;
    mult = 1;
    printf("%d iteration finished\n", k);
}
printf("%lld\n", max);

Ответ 13

Вы должны использовать int64_t вместо int

Ответ 14

Я решил эту проблему с помощью модуля Python 'Re'

Найдя все возможные 13-значные числа без нулей (всего 988 с нулем и 283 без нуля), найдите произведение каждой из этих цифр и проверьте на макс.

здесь я использовал регулярное выражение с нетерпением

Примечание. Строка не должна содержать символы новой строки.

s = '731671765...'

import re


def product_13(d):
    pro = 1
    while d:
        pro *= d % 10
        d //= 10
    return pro


pat = re.compile(r'(?=([1-9]{13}))')

all = map(int, re.findall(pat, s))
pro = -1
for i in all:
    v = product_13(i)
    if pro < v:
        pro = v
print(pro)

Ответ 15

**This is JavaScript solution.**


greatestProductOfAdjacentDigit = (givenNumber, noOfDigit) => {
stringNumberToNumbers = givenNumber => givenNumber.split('').map(each => parseInt(each, 10))

            let numbers = mathematicalProblems.stringNumberToNumbers(givenNumber);
            return numbers.map(function (each, ind, arr) {
                return mathematicalProblems.productOfAll(arr.slice(ind, ind + noOfDigit));
            }).reduce(function (accumulator, currentValue) {
                return accumulator > currentValue ? accumulator : currentValue;
            });
        };

Тестирование

const givenNumber = '73167176531330624919225119674426574742355349' +
                '194934969835203127745063262395783180169848018694788518438586' +
                '156078911294949545950173795833195285320880551112540698747158' +
                '523863050715693290963295227443043557668966489504452445231617' +
                '318564030987111217223831136222989342338030813533627661428280' +
                '644448664523874930358907296290491560440772390713810515859307' +
                '960866701724271218839987979087922749219016997208880937766572' +
                '733300105336788122023542180975125454059475224352584907711670' +
                '556013604839586446706324415722155397536978179778461740649551' +
                '492908625693219784686224828397224137565705605749026140797296' +
                '865241453510047482166370484403199890008895243450658541227588' +
                '666881164271714799244429282308634656748139191231628245861786' +
                '645835912456652947654568284891288314260769004224219022671055' +
                '626321111109370544217506941658960408071984038509624554443629' +
                '812309878799272442849091888458015616609791913387549920052406' +
                '368991256071760605886116467109405077541002256983155200055935' +
                '72972571636269561882670428252483600823257530420752963450';

console.log(greatestProductOfAdjacentDigit(givenNumber, 4)); //5832
console.log(greatestProductOfAdjacentDigit(givenNumber, 13)); //23514624000

Ответ 16

const thousandDigit = 
'73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450';

const productsOfAdjacentNths = num =>
  [...thousandDigit].reduce((acc, _, idx) => {
    const nthDigitAdjX = [...thousandDigit.substr(idx, num)].reduce(
      (inAcc, inCur) => inCur * inAcc,
      1
    );

    return acc.concat(nthDigitAdjX);
  }, []);

console.log(Math.max(...productsOfAdjacentNths(13))); //5377010688

Ответ 17

Это найдет ответ в O (n) времени и обработает нуль. Написано в Дарт.

/**
 * Main function
 *
 * Find the thirteen adjacent digits in the 1000-digit number that have the greatest product.
 * What is the value of this product?
 *
 */
const String DIGITS = "73167176531330624919225119674426574742355349194934"
                      "96983520312774506326239578318016984801869478851843"
                      "85861560789112949495459501737958331952853208805511"
                      "12540698747158523863050715693290963295227443043557"
                      "66896648950445244523161731856403098711121722383113"
                      "62229893423380308135336276614282806444486645238749"
                      "30358907296290491560440772390713810515859307960866"
                      "70172427121883998797908792274921901699720888093776"
                      "65727333001053367881220235421809751254540594752243"
                      "52584907711670556013604839586446706324415722155397"
                      "53697817977846174064955149290862569321978468622482"
                      "83972241375657056057490261407972968652414535100474"
                      "82166370484403199890008895243450658541227588666881"
                      "16427171479924442928230863465674813919123162824586"
                      "17866458359124566529476545682848912883142607690042"
                      "24219022671055626321111109370544217506941658960408"
                      "07198403850962455444362981230987879927244284909188"
                      "84580156166097919133875499200524063689912560717606"
                      "05886116467109405077541002256983155200055935729725"
                      "71636269561882670428252483600823257530420752963450";

main(List<String> args) {

  const int MAX_DIGITS = 13;
  int len = DIGITS.length;

  int digits = 0;
  int largest = 0;
  int current = 0;

  int index = 0;
  while (index < len) {

    int value = int.parse(DIGITS[index]);

    // if we get a zero then rebuild the MAX_DIGITS consecutive digits
    if (value == 0) {
      current = 0;
      digits = 0;
    } else {
      // Multiply consecutive digits up to target set
      if (digits < MAX_DIGITS) {
        if (current == 0) {
          current = value;
        } else
          current *= value;
        digits++;
      } else {
        int divisor = int.parse(DIGITS[index - MAX_DIGITS]);

        if (current == 0) {
          current = value;
        } else {
          current = (current ~/ divisor);
          current *= value;
        }
      }

      if (current > largest) {
        largest = current;
      }
    }

    index++;
  }

  print('Num  $largest');
}