Project Euler: Problem 8 in Ruby

Problem 8 is to Problem 7 as Problem 6 is to Problem. My original plan involved storing the current sum of 5 numbers and then simply dividing by $big_n[i – 1] and multiplying by $big_n[i + 5], but the zeros made it a bit messy so I thought I’d just give the straight-forward an approach a go to see what I was up against. And it ran correctly, and more importantly quickly so I let it be.

Problem #8

Find the greatest product of five consecutive digits in the 1000-digit number.

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

Note: Global variables ahead, proceed with caution.

$big_n ="731671765313306249192251196744265747423553
491949349698352031277450632623957831801698480186947
885184385861560789112949495459501737958331952853208
805511125406987471585238630507156932909632952274430
435576689664895044524452316173185640309871112172238
311362229893423380308135336276614282806444486645238
749303589072962904915604407723907138105158593079608
667017242712188399879790879227492190169972088809377
665727333001053367881220235421809751254540594752243
525849077116705560136048395864467063244157221553975
369781797784617406495514929086256932197846862248283
972241375657056057490261407972968652414535100474821
663704844031998900088952434506585412275886668811642
717147992444292823086346567481391912316282458617866
458359124566529476545682848912883142607690042242190
226710556263211111093705442175069416589604080719840
385096245544436298123098787992724428490918884580156
166097919133875499200524063689912560717606058861164
671094050775410022569831552000559357297257163626956
1882670428252483600823257530420752963450".split('')

$stack = []
$chars = 5
max    = 9

def find_product start
  total = 1
  $chars.times do |i|
    total *= $big_n[start + i].to_i
  end
  total
end

$chars.upto($big_n.length - $chars) do |i|
  current = find_product i
  max = [current,max].max
end

puts max

Blessed Olathe had a Ruby-er Solution:

class String
  def max_digit_product length
    # Get each string of 'length' or more nonzero digits.
    strings = scan(/((?:W*[1-9A-Z]){#{length},})/i).map { |string|
      string.first.scan(/([1-9A-Z])/i).map { |digit|
        digit.first.to_i 36
      }
    }
 
    # Find the maximum product of 'length' digits.
    max = 0
    strings.each { |string|
      product = string[0, length].inject(1) { |prod, digit|
        prod * digit
      }
      max = [max, product].max
      (0...(string.length - length)).each { |index|
        product = product / string[index] * string[index + length]
        max = [max, product].max
      }
    }
    max
  end
end