2
$\begingroup$

Yup, im a newbie, you guessed it. But I have been having fun solving Project Euler problems with Mathematica. I am on problem #8:

The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832.

The 1000 digit number is:

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

Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?

I know its elementary but here's what ive tried so far: ATTEMPT #1:

string1 =
 IntegerString[
  73167176531330624919225119674426574742355349194934969835203127745063\
2623957831801698480186947885184385861560789112949495459501737958331952\
8532088055111254069874715852386305071569329096329522744304355766896648\
9504452445231617318564030987111217223831136222989342338030813533627661\
4282806444486645238749303589072962904915604407723907138105158593079608\
6670172427121883998797908792274921901699720888093776657273330010533678\
8122023542180975125454059475224352584907711670556013604839586446706324\
4157221553975369781797784617406495514929086256932197846862248283972241\
3756570560574902614079729686524145351004748216637048440319989000889524\
3450658541227588666881164271714799244429282308634656748139191231628245\
8617866458359124566529476545682848912883142607690042242190226710556263\
2111110937054421750694165896040807198403850962455444362981230987879927\
2442849091888458015616609791913387549920052406368991256071760605886116\
4671094050775410022569831552000559357297257163626956188267042825248360\
0823257530420752963450]

ToExpression[StringPart[string1, Range[13]]]

Times[7, 3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3]
5000940

Then I knew I would have to do it again and again, just moving one digit over with another 13 adjacent digits like so....

ToExpression[StringPart[string1, Range[2, 14]]]

Times[3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3, 0]

0

And Again,,,

ToExpression[StringPart[string1, Range[3, 15]]]

Times[1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3, 0, 6]

0

So I know that I could solve it this way but it would take me a long time....i know there has to be another way....a loop maybe? I am really new to mathematica so be patient with me.

But leading me down a path of righteousness for his namesake would be great. For thou art surely walking through the valley and shadows of death but thou fearest no evil for Stack Exchange art with thee!

$\endgroup$
4
  • 3
    $\begingroup$ Times @@MaximalBy[Partition[IntegerDigits[nbr], 13, 1], Times @@ # &][[1]] $\endgroup$
    – Bob Hanlon
    Commented Sep 4, 2022 at 4:59
  • 2
    $\begingroup$ You can take an integer and get the digits as a list with IntegerDigits. Once you have a list you can use Partition to get sublists. In your case you'll want to use the offset form of Partition: Partition[list, length, offset] where length is 13 and offset is 1. At that point you'll have a list of 13-element lists. You can then apply Times to each list (look at MapApply). At that point you'll have a list of integers, and you can select the Max. $\endgroup$
    – lericr
    Commented Sep 4, 2022 at 5:03
  • 4
    $\begingroup$ Lericr's comment will set you on your way. Whenever you want to implement a loop, first consider whether you need one. Mathematica is a functional language in which other operations replace loops. Map (or MapApply) is a key operation. Note that it is used by lericr. Check out Leonid Shifrin's, Mathematica Programming: Advanced Introduction, page 216 section 5.2.2.2, Map is a replacement for loop, and the basic example implemented with loop and with Map instead. Leonid spells out the advantages. Best of luck, Michel. $\endgroup$ Commented Sep 4, 2022 at 10:07
  • $\begingroup$ Thank you @lericr and michel,both of you guided me to an answer that I could understand and easily enough implement. Mapping in lieu of looping. Will remember this going forward! Thank you. I take notes on your comments and I save my notebook for reference. Its always nice to have a referenced note with an example :-) $\endgroup$
    – SugarFoot
    Commented Sep 5, 2022 at 5:28

1 Answer 1

2
$\begingroup$

Since you want the value of the maximal product, and not the sequence of digits from which it is obtained, I recommend:

Max[Times @@@ Partition[IntegerDigits[n], 13, 1]]

where n is your number.

This is how it works:

  • IntegerDigits[n] gives you a list of each digit in the number ({7, 3, 1, ..., 5, 0}).
  • Partition[<list>, 13, 1] gives you a list of overlapping chunks of from that list of digits, each 13 digits long, overlapped by one digit.
  • Times @@@ applies Times (i.e., multiplication) to each of the chunks obtained from partition. @@@ is infix notation for Apply[f, input, 1]. MapApply is a newly introduced built-in function that does the same thing and provides "syntactic sugar" for the same operation. See Apply and, for comparison, Map and MapApply as well.
  • The result is a list of the products of the digits in each 13-digit chunk. You want the largest of those products, so you can use Max to pick it out.

Generally speaking, whenever you find yourself in need of repeating the same operation on a list of inputs, a looping construct would be the answer in imperative languages. In a functional or declarative programming language like Mathematica, you would typically use a Map operation instead. In other words, you would "map" your operation over the list, and obtain a new list of results, one for each element of the original list. The operation itself would often be presented as a pure function. See also Applying Functions to Lists.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.