项目Euler 8 in Ruby

时间:2015-12-01 17:26:42

标签: ruby

我知道我的代码可以获得4个相邻整数的正确答案。但它与13无关。

我唯一能想到的是它可能是unsigned int的一个问题,但在Ruby中我不认为我会遇到这个问题,因为它会自动更改为Bignum类。

这意味着在我计算的某个地方我错了吗?

请给我一个提示。

# Euler 8
# http://projecteuler.net/index.php?section=problems&id=8
# Find the thirteen adjacent digits in the 1000-digit number 
# that have the greatest product. 
# What is the value of this product? 


number = []

#split the integer as a string into an array
long_digit = "73167176531330624919225119674426574742355349194934
            96983520312774506326239578318016984801869478851843
            85861560789112949495459501737958331952853208805511
            12540698747158523863050715693290963295227443043557
            66896648950445244523161731856403098711121722383113
            62229893423380308135336276614282806444486645238749
            30358907296290491560440772390713810515859307960866
            70172427121883998797908792274921901699720888093776
            65727333001053367881220235421809751254540594752243
            52584907711670556013604839586446706324415722155397
            53697817977846174064955149290862569321978468622482
            83972241375657056057490261407972968652414535100474
            82166370484403199890008895243450658541227588666881
            16427171479924442928230863465674813919123162824586
            17866458359124566529476545682848912883142607690042
            24219022671055626321111109370544217506941658960408
            07198403850962455444362981230987879927244284909188
            84580156166097919133875499200524063689912560717606
            05886116467109405077541002256983155200055935729725
            71636269561882670428252483600823257530420752963450"

long_digit.split("").map { |s| number << s.to_i }

#iterate through the array to find the 13 ajacent digits that have the largest product
largest_product = 0
a = 0
#stay within the bounds of the array
while number[a+12]
    current_product = number[a] * number[a+1] * number[a+2] * number[a+3] * number[a+4] * number[a+5] * number[a+6] * number[a+7] * number[a+8] * number[a+9] * number[a+10] * number[a+11] * number[a+12] 
        if current_product > largest_product
            largest_product = current_product
        end 
    a = a + 1
end

puts largest_product

3 个答案:

答案 0 :(得分:4)

我认为这个解决方案非常简洁明了:

console.log(/\b\w{1,7}\b/i.test('bc4rg6'))

#!/usr/bin/env ruby input = " 73167176531330624919225119674426574742355349194934 96983520312774506326239578318016984801869478851843 85861560789112949495459501737958331952853208805511 12540698747158523863050715693290963295227443043557 66896648950445244523161731856403098711121722383113 62229893423380308135336276614282806444486645238749 30358907296290491560440772390713810515859307960866 70172427121883998797908792274921901699720888093776 65727333001053367881220235421809751254540594752243 52584907711670556013604839586446706324415722155397 53697817977846174064955149290862569321978468622482 83972241375657056057490261407972968652414535100474 82166370484403199890008895243450658541227588666881 16427171479924442928230863465674813919123162824586 17866458359124566529476545682848912883142607690042 24219022671055626321111109370544217506941658960408 07198403850962455444362981230987879927244284909188 84580156166097919133875499200524063689912560717606 05886116467109405077541002256983155200055935729725 71636269561882670428252483600823257530420752963450" .gsub(/\s+/, '') puts input.chars .map(&:to_i) .each_cons(13) .map { |seq| seq.reduce(:*) } .max 执行修剪。

gsub获取角色。

chars将所有字​​符映射到整数。

map(&:to_i)获取连续数字的块(https://ruby-doc.org/core-2.4.1/Enumerable.html#method-i-each_cons

each_cons(13)将获取每个连续的块并执行reduce(将每个切片/连续数字块的所有数字相乘)。

map { |seq| seq.reduce(:*) }获得最大值。

答案 1 :(得分:1)

问题似乎是由于字符串long_digit中的大量空格字符在数组0中变为number,因此会产生错误的结果。

这是经过更正和简化的版本。使用gsub删除换行符和空格后,我们现在有一个1000位的数字,我们得到了正确答案。

number = long_digit.gsub!(/\s/, '').split("").map{ |s| s.to_i }
n = 13
p number.each_cons(n).map{|a| a.reduce {|a, i| a = a * i }}.max
#=> 23514624000

答案 2 :(得分:1)

首先,让我们修复字符串:

long_digit.gsub!(/\s|\n/,'')
long_digit.size #=> 1000

我们可以通过消除包含零的13个字符的子串来加快速度:

shorter_digit_arr = long_digit.split('0').reject { |s| s.size < 13 }
  #=> ["7316717653133",
  #    "6249192251196744265747423553491949349698352",
  #    "6326239578318",
  #    "18694788518438586156",
  #    "7891129494954595",
  #    "17379583319528532",
  #    "698747158523863",
  #    "435576689664895",
  #    "4452445231617318564",
  #    "987111217223831136222989342338",
  #    "81353362766142828",
  #    "64444866452387493",
  #    "1724271218839987979",
  #    "9377665727333",
  #    "594752243525849",
  #    "632441572215539753697817977846174",
  #    "86256932197846862248283972241375657",
  #    "79729686524145351",
  #    "6585412275886668811642717147992444292823",
  #    "863465674813919123162824586178664583591245665294765456828489128831426",
  #    "96245544436298123",
  #    "9878799272442849",
  #    "979191338754992",
  #    "559357297257163626956188267"] 

现在,对于shorter_digit_arr的每个元素,找到其数字乘积最大的13个字符的子字符串,然后找到其中最大的(shorter_digit_arr.size #=> 24)个产品。以这种方式将字符串拆分为子字符串的主要好处是,缺少零允许我们以更有效的方式执行产品计算,而不是简单地为每个子字符串研磨12次乘法:

res = shorter_digit_arr.map do |s|
      cand = s[0,13].each_char.reduce(1) { |prod,t| prod * t.o_i }
      best = { val: cand, offset: 0 }
      (13...s.size).each do |i|
        cand = cand*(s[i].to_i)/(s[i-13].to_i)
        best = { val: cand, offset: i-12 } if cand > best[:val]
      end
      [best[:val], s[best[:offset],13]]
    end.max_by(&:first)
      #=> [23514624000, "5576689664895"]

puts "max_product: %d for: '%s'" % res
  #=> max_product: 23514624000 for: '5576689664895'

解决方案是:

的最后13个字符
s = shorter_digit_arr[7]
  #=> "435576689664895"

这里的关键是:

cand = cand*(s[i].to_i)/(s[i-13].to_i)

通过乘以&#34;之前的&#34;来计算13位数的产品。 13位数的乘积加上数字除以数字下降。

在查找此元素的最大乘积时,计算如下:

s = "435576689664895"
cand  = s[0,13].each_char.reduce(1) { |prod,t| prod * t.to_i }
  #=> = "4355766896648".each_char.reduce(1) { |prod,t| prod * t.to_i }
  #   = 6270566400 
best_val = { val: 6270566400, offset: 0 } 

enum = (13...s.size).each
  #=> #<Enumerator: 13...15:each> 

此枚举器的元素将由Enumerator#each传递给块。我们可以通过将enum转换为数组来查看它们是什么:

enum.to_a
  #=> [13, 14]

我们可以使用Enumerator#next来模拟enum元素到块的传递及其对块变量i的赋值。

将枚举器的第一个元素(13)传递给块:

i = enum.next
  #=> 13 
cand = cand*(s[i].to_i)/(s[i-13].to_i)
  #  = 6270566400*(s[13].to_i)/(s[0].to_i)
  #  = 6270566400*(9)/(4)
  #  = 14108774400 
cand > best[:val]
  #=> 14108774400 > 6270566400 => true
best = { val: cand, offset: i-12 }
  #=> { val: 14108774400, offset: 1 }

将第二个元素(14)传递给块:

i = enum.next
  #=> 14 
cand  = cand*(s[i].to_i)/(s[i-13].to_i)
  #=> = 14108774400*(s[14].to_i)/(s[1].to_i)
  #   = 14108774400*(5)/(3)   
  #   = 23514624000 
cand > best[:val]
  #=> 23514624000 > 14108774400 => true
best = { val: 23514624000, offset: 2 }

现在,枚举器的所有元素都已传递给块。我们可以确认:

i = enum.next
  #=> StopIteration: iteration reached an end

结果(shorter_digit_arr[7])是:

[best[:val], s[best[:offset],13]]
  #=> [23514624000, "435576689664895"[2,13]]
  #   [23514624000, "5576689664895"]