My Solution to Project Euler in Ruby
2009-03-20 21:35
405 查看
Problem 11
求横、竖、对角方向上连续四个数乘积的最大值。
暴力解,没什么技术含量。
Problem 18
简单的动态规划。同样的题还有Problem 67。
Problem 22
先排序,再算score。
Problem 26
找循环节。本来是我最得意的一题,看了别人的解答以后,狂汗!
由于是模d,所以1/d 的循环节最多不超过d 位(鸽笼原理)。
看高手是怎么做的!
稍稍解释一下/1 的意思,这是一个回溯引用,引用前面划分出来的那个子表达式(/w+?)。/1 表示引用模式里的第一个子表达式,/2 代表第二个,/3 代表第三个 ……。
Problem 29
算不同的幂的个数。
Problem 40
见这里。
Problem 42
Problem 43
先写了一个ugly 版本:
后来实在看不下去了,写了一个递归版本,但不知道怎么把结果累加起来,只好用了全局变量-_-!!
Problem 44
这个程序的最大问题就是你必须先蒙一个范围,比如2000。
一个叫dfg59 的哥们这样写道:
Problem 46
Problem 47
记得mathn 库有个叫prime_division() 的函数,可以把自然是分解成素因子的幂的积的形式(当然,是用数组表示的)。
会不会太简单了!自己写一个prime_division():
嗯,速度还行,花了31.75秒。
看后面的论坛,看到了一位老兄四行搞定:
Problem 49
为什么又是3330呢?巧合??
Problem 50
第50题想了好久,一开始随手写了一个遍历所有可能的算法,跑了一晚也没算出来。后来重读了一遍题目,一想,既然是找最大的,何不从最长的区间开始搜呢。结果只花了不到4秒就算出来了,997651。算法的威力啊!!!
筛法是抄Bob大叔的。
固定区间长度,先找到最靠右、其和又没超过1,000,000的区间,不断左移。只要找到,它一定是最长最大的。
Problem 67
和Problem 18 一个味。
求横、竖、对角方向上连续四个数乘积的最大值。
暴力解,没什么技术含量。
ary2d = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48" ary2d = ary2d.split("/n").collect { |line| line.split(' ').collect { |n| n.to_i } } max_prod = 0 (0 ... ary2d.size).each do |r| (0 ... ary2d[r].size).each do |c| prod_h, prod_v, prod_d, prod_d_r = 0, 0, 0, 0 prod_h = (0 ... 4).inject(1) {|prod, idx| prod * ary2d[r][c+idx]} if c + 4 <= ary2d[r].size prod_v = (0 ... 4).inject(1) {|prod, idx| prod * ary2d[r+idx][c]} if r + 4 <= ary2d.size prod_d = (0 ... 4).inject(1) {|prod, idx| prod * ary2d[r+idx][c+idx]} if c + 4 <= ary2d[r].size and r + 4 <= ary2d.size prod_d = (0 ... 4).inject(1) {|prod, idx| prod * ary2d[r-idx][c+idx]} if r >= 3 and c + 4 <= ary2d[r].size max_prod = [max_prod, prod_h, prod_v, prod_d, prod_d_r].max end end p max_prod # => 70600674
Problem 18
简单的动态规划。同样的题还有Problem 67。
triangle = "75 95 64 17 47 82 18 35 87 10 20 04 82 47 65 19 01 23 75 03 34 88 02 77 73 07 63 67 99 65 04 28 06 16 70 92 41 41 26 56 83 40 80 70 33 41 48 72 33 47 32 37 16 94 29 53 71 44 65 25 43 91 52 97 51 14 70 11 33 28 77 73 17 78 39 68 17 57 91 71 52 38 17 14 91 43 58 50 27 29 48 63 66 04 68 89 53 67 30 73 16 69 87 40 31 04 62 98 27 23 09 70 98 73 93 38 53 60 04 23" triangle = triangle.split("/n").collect { |line| line.split(' ').collect { |n| n.to_i } } # [[3], [7, 5], [2, 4, 6], [8, 5, 9, 3]] tri = [] tri[0] = triangle[0] (1 ... triangle.size).each do |h| tri[h] = [] tri[h][0] = triangle[h][0] + tri[h-1][0] (1 ... triangle[h].size-1).each do |i| tri[h][i] = triangle[h][i] + [tri[h-1][i-1], tri[h-1][i]].max end tri[h] << triangle[h][-1] + tri[h-1][-1] end max = 0 (0 ... tri[-1].size).each do |x| max = [max, tri[-1][x]].max end p max # => 1074
Problem 22
先排序,再算score。
s = [] f = File.open("f:/names.txt").each do |line| line.scan(//"(/w*)/"/) {s << $1} end s.sort! letters = {} ("a".."z").zip(1..26) { |a, b| letters[a] = b } sum = 0 (0 ... s.size).each do |x| score = 0 s[x].each_byte do |c| score += letters[c.chr.downcase] end sum += score*(x+1) end p sum # => 871198282
Problem 26
找循环节。本来是我最得意的一题,看了别人的解答以后,狂汗!
由于是模d,所以1/d 的循环节最多不超过d 位(鸽笼原理)。
def cycle(d) divisor, remainder = [], [] r, n = 1, 0 while true old_r = r q, r = 10*r/d, 10*r%d #puts "#{old_r}*10/#{d}=#{q}, #{r}" if remainder.include? r divisor << q remainder << r break; end divisor << q remainder << r n += 1 end #p divisor, remainder if remainder[-1] == 0 #puts "0.#{divisor[0 .. -2]}" return 0 else idx = remainder.index(r) a, b = "", "" if divisor[-1] == divisor[idx] #puts "0.#{divisor[0 ... idx]}(#{divisor[idx .. -2]})" a = divisor[0 ... idx].to_s b = divisor[idx .. -2].to_s else #puts "0.#{divisor[0 .. idx]}(#{divisor[idx+1 .. -1]})" a = divisor[0 .. idx].to_s b = divisor[idx+1 .. -1].to_s end puts d if b.to_i != (10**a.size - d*a.to_i)*(10**b.size - 1)/d return b.size end end =begin 1/1 = 1.0 1/2 = 0.5 1/3 = 0.(3) 1/4 = 0.25 1/5 = 0.2 1/6 = 0.1(6) 1/7 = 0.(142857) 1/8 = 0.125 1/9 = 0.(1) 1/10 = 0.1 1/11 = 0.(09) 1/12 = 0.08(3) 1/13 = 0.(076923) 1/14 = 0.0(714285) 1/15 = 0.0(6) 1/16 = 0.0625 1/17 = 0.(0588235294117647) 1/18 = 0.0(5) 1/19 = 0.(052631578947368421) 1/20 = 0.05 =end len = [0, 0] 2.upto(1000) do |d| #puts d.to_s.center 40, "-" len << cycle(d) #p len[-1] end p len.index(len.max) # => 983
看高手是怎么做的!
ary = [0] 1.upto(999) do |i| ary << /(/w+?)/1/.match(((10**2000)/i).to_s)[1].length end puts ary.index(ary.max)
稍稍解释一下/1 的意思,这是一个回溯引用,引用前面划分出来的那个子表达式(/w+?)。/1 表示引用模式里的第一个子表达式,/2 代表第二个,/3 代表第三个 ……。
Problem 29
算不同的幂的个数。
terms = [] (2 .. 100).each do |a| (2 .. 100).each do |b| terms << a**b end end p terms.uniq.size # => 9183
Problem 40
见这里。
Problem 42
class Integer def triangle? delta = Math.sqrt(1 + 8*self) delta % 1 == 0 and delta % 2 == 1 end end File.open("f://words.txt") do |file| words = file.gets.split(",").inject([]) {|w, s| w << s[1...-1]} count = 0 words.each do |w| sum = 0 w.each_byte {|b| sum += (b - ?A + 1)} count += 1 if sum.triangle? end p count # 162 end
Problem 43
先写了一个ugly 版本:
def genarate_mult(n) rtn = rtn << (rtn[-1] + n) while rtn[-1] <= 1_000 rtn end def get_digits(n) d2, d1, d0 = n/100, (n/10)%10, n%10 end def problem_43 sum = 0 genarate_mult(17).each do |x| d = [] d[8], d[9], d[10] = get_digits(x) if (d[8] != d[9]) and (d[9] != d[10]) and (d[10] != d[8]) (0..9).each do |d7| if not d[8..10].include?(d7) and ("#{d7}#{d[8]}#{d[9]}".to_i % 13 == 0) d[7] = d7 (0..9).each do |d6| if not d[7..10].include?(d6) and ("#{d6}#{d[7]}#{d[8]}".to_i % 11 == 0) d[6] = d6 (0..9).each do |d5| if not d[6..10].include?(d5) and ("#{d5}#{d[6]}#{d[7]}".to_i % 7 == 0) d[5] = d5 (0..9).each do |d4| if not d[5..10].include?(d4) and ("#{d4}#{d[5]}#{d[6]}".to_i % 5 == 0) d[4] = d4 (0..9).each do |d3| if not d[4..10].include?(d3) and ("#{d3}#{d[4]}#{d[5]}".to_i % 3 == 0) d[3] = d3 (0..9).each do |d2| if not d[3..10].include?(d2) and ("#{d2}#{d[3]}#{d[4]}".to_i % 2 == 0) d[2] = d2 (0..9).each do |d1| if not d[2..10].include?(d1) d[1] = d1 num = "" (1..10).each { |i| num += d[i].to_s } puts num sum += num.to_i break end end end end end end end end end end end end end end end end sum end p problem_43 # 16695334890
后来实在看不下去了,写了一个递归版本,但不知道怎么把结果累加起来,只好用了全局变量-_-!!
def genarate_mult(n) rtn = rtn << (rtn[-1] + n) while rtn[-1] <= 1_000 rtn end def get_digits(n) d2, d1, d0 = n/100, (n/10)%10, n%10 end $sum = 0 def find_num(k, d, primes) if k == 1 (0..9).each do |d1| if not d[2..10].include?(d1) d[1] = d1 p n = (1..10).inject("") { |num, i| num += d[i].to_s } $sum += n.to_i end end else (0..9).each do |dk| if not d[(k+1)..10].include?(dk) and ("#{dk}#{d[k+1]}#{d[k+2]}".to_i % primes[k] == 0) d[k] = dk find_num(k-1, d, primes) end end end end def problem_43 genarate_mult(17).each do |x| d = [] d[8], d[9], d[10] = get_digits(x) if (d[8] != d[9]) and (d[9] != d[10]) and (d[10] != d[8]) primes = [nil, nil, 2, 3, 5, 7, 11, 13] find_num(7, d, primes) end end $sum end p problem_43
Problem 44
require 'benchmark' class Integer def pentagonal? r = Math.sqrt(1 + 24*self) (r % 1 == 0) and ((1 + r) % 6 == 0) end end def problem_44(n) p = [1] (2..n).each do |d| p << (p[-1] + 3*d - 2) end p.each do |d| p.each do |x| #idx = (1 + Math.sqrt(1 + 24*x)) / 6 #break if d < 3*idx - 2 if (x + d).pentagonal? and (2*x + d).pentagonal? p "yeah, #{x}, #{x + d}" return d end end end end p Benchmark.realtime { p problem_44(2_000) }
这个程序的最大问题就是你必须先蒙一个范围,比如2000。
一个叫dfg59 的哥们这样写道:
class Integer def pent? ((1+Math.sqrt(1+24*self))/6)%1 == 0 end end a = 1 while true pa = a*(3*a-1)/2 (1..a).each do |b| pb = b*(3*b-1)/2 if (pa+pb).pent? && (pa-pb).abs.pent? puts (pa-pb).abs exit end end a += 1 end
Problem 46
require 'mathn' class Prime @@primes = [] @@gen = Prime.new def prime(n) while n >= @@primes.size do @@primes << @@gen.next end @@primes end def prime?(n) loop do @@primes << @@gen.next break if n <= @@primes[-1] end @@primes.include?(n) end end require 'benchmark' p Benchmark.realtime { gen = Prime.new 3.step(1.0/0, 2) do |n| n = n.to_i if not gen.prime?(n) find_it = false 0.upto(1.0/0) do |i| p = gen.prime(i) break if p > n x = ((n - p)/2).to_i if Math.sqrt(x).floor ** 2 == x find_it = true # puts "#{n} = #{p} + 2*#{Math.sqrt(x)}**2" break end end if not find_it puts "yeah! #{n}" break end end end }
Problem 47
记得mathn 库有个叫prime_division() 的函数,可以把自然是分解成素因子的幂的积的形式(当然,是用数组表示的)。
require 'mathn' require 'benchmark' p Benchmark.realtime { factors_c = [0, 0, 1] (3..1000000).each do |x| factors_c << x.prime_division.size if factors_c[x] == factors_c[x-1] and factors_c[x-1] == factors_c[x-2] and factors_c[x-2] == factors_c[x-3] and factors_c[x] == 4 p "#{x-3}, #{x-2}, #{x-1}, #{x}" break end end } # 195.125 s
会不会太简单了!自己写一个prime_division():
class Integer @@factors = {2=>{2=>1}} def prime_division return @@factors[self] if @@factors[self] 2.upto(Math.sqrt(self)) do |x| if self % x == 0 lh, rh = x.prime_division, (self/x).prime_division keys = lh.keys + rh.keys hash = {} keys.each do |k| hash[k] = (lh[k] || 0) + (rh[k] || 0) end return @@factors[self] = hash end end @@factors[self] = {self=>1} end end
嗯,速度还行,花了31.75秒。
看后面的论坛,看到了一位老兄四行搞定:
# slow but compact and readable ruby require "mathn" require "enumerator" p (1..1.0/0.0).each_cons(4) { |g| break g if g.all? { |nbr| nbr.prime_division.length == 4 } }
Problem 49
为什么又是3330呢?巧合??
def sieve(n) sieve = Array.new(n, true) sieve[0..1] = [false, false] 2.upto(Integer(Math.sqrt(n))) do |i| if sieve[i] (2*i).step(n, i) do |j| sieve[j] = false end end end primes = [] sieve.each_with_index {|x, i| primes << i if x} primes end def permutation(ary) return ary if ary.size == 1 res = [] ary.each do |e| permutation(ary - [e]).each do |x| res << (e.to_s + x.to_s).to_i end end res end def permute(str) ary = [] (1..str.length).each {|x| ary << x} res = [] permutation(ary).each do |x| s = "" x.to_s.each_byte do |b| s << str[b - 49] # 1's ASCII code is 49. end res << s end res end def in_a_line(ary) n = ary.size (0..(n-3)).each do |i| ((i+1)..(n-2)).each do |j| ((j+1)..(n-1)).each do |k| return [ary[i], ary[j], ary[k]] if (ary[j] - ary[i]) == (ary[k] - ary[j]) end end end [] end require 'set' def solve_problem_49(d) n = 10**d primes = sieve(n) four_digit = primes.find_all { |x| x > 10**(d-1) } four_digit.each do |x| perm = permute(x.to_s).map {|e| e.to_i}.find_all {|e| e if four_digit.include? e} set = Set.new(perm) if set.size >= 3 ary = [] set.each {|x| ary << x} ary.sort! res = in_a_line(ary) p res if res != [] end end # [2969, 6299, 9629] end require 'benchmark' puts Benchmark.realtime { solve_problem_49(4) }
Problem 50
第50题想了好久,一开始随手写了一个遍历所有可能的算法,跑了一晚也没算出来。后来重读了一遍题目,一想,既然是找最大的,何不从最长的区间开始搜呢。结果只花了不到4秒就算出来了,997651。算法的威力啊!!!
筛法是抄Bob大叔的。
固定区间长度,先找到最靠右、其和又没超过1,000,000的区间,不断左移。只要找到,它一定是最长最大的。
def sieve(n) sieve = Array.new(n, true) sieve[0..1] = [false, false] 2.upto(Integer(Math.sqrt(n))) do |i| if sieve[i] (2*i).step(n, i) do |j| sieve[j] = false end end end primes = [] sieve.each_with_index {|x, i| primes << i if x} primes end def find_such_a_prime(primes, n) sum = 0 a, b = 0, n primes.each_with_index do |x, i| sum += x if sum > n a , b = 0, i - 1 sum -= x break end end # hints: 2 + ... + 3931 = 997661; 3931 is the 547th prime number. # 2 + ... + 3931 + 3943 = 1001604. (b - a + 1).downto 1 do |len| l, r, s = 0, len - 1, sum loop do new_s = s + primes[r + 1] - primes[l] break if new_s > n # shift right s = new_s l += 1 r += 1 end l.downto(0) do |u| v = u + len - 1 if primes.index(s) != nil puts "#{primes[u]} + ... + #{primes[v]} = #{s} (#{len} items)" return s end # shift left s = s - primes[v] + primes[u - 1] end sum -= primes[len - 1] end end require 'benchmark' puts Benchmark.realtime { n = 1_000_000 primes = sieve(n) p find_such_a_prime(primes, n) }
Problem 67
和Problem 18 一个味。
triangle = "" f = File.open("f:/triangle.txt").each do |line| triangle << line end triangle = triangle.split("/n").collect { |line| line.split(' ').collect { |n| n.to_i } } # [[3], [7, 5], [2, 4, 6], [8, 5, 9, 3]] tri = [] tri[0] = triangle[0] (1 ... triangle.size).each do |h| tri[h] = [] tri[h][0] = triangle[h][0] + tri[h-1][0] (1 ... triangle[h].size-1).each do |i| tri[h][i] = triangle[h][i] + [tri[h-1][i-1], tri[h-1][i]].max end tri[h] << triangle[h][-1] + tri[h-1][-1] end max = 0 (0 ... tri[-1].size).each do |x| max = [max, tri[-1][x]].max end p max # => 7273
相关文章推荐
- My Solution to Project Euler in JavaScript
- My Solution to Project Euler in Perl
- Plan to use track+ in my project
- [Solution]How to create Project Web App in SharePoint
- How to import Patio Library in my Project
- (VS TFS) Adding existing project to solution in TFS.
- SharePoint Project Deployment Fails With Error "Failed to extract the cab file in the solution"
- VSPackage Extension ----How to get Active project Name in Solution Explorer
- How to skip other publishable projects during publish a clickonce project in a solution?
- How to solve "one or more projects in the solution were not loaded correctly" problem?
- The goal you specified requires a project to execute but there is no POM in this directory...
- 解决Tomcat部署Maven异常:Deployment is out of date due to changes in the underlying project contents
- Project Dependency in solution
- How do I add multiple arguments to my custom template filter in a django template? - Stack Overflow
- (Redirect)How to create my own Corporate intranet(Site Definition In MOSS 2007)?(http://hermansberghem.blogspot.com/2008/04/crea
- How to use Atlas in our Web Projects
- Error:Failed to resolve: junit:junit:4.12 <a href="open.dependency.in.project.structure">Show in Pro
- Source folder ''{0}'' in project ''{2}'' cannot output to distinct source folder
- How to Enable Project Server License in SharePoint?
- first step in order to optimization of my C program