Aug
8
In my attempt to learn Ruby out in the open, here’s my solution for Project Euler Problem 32.
I should take some time and consider why iterating from 1 to 9999 is enough looping to obtain the correct result. I should but I won’t. It’s a beautiful Sunday afternoon and the grill is calling. I’ll also bet there are dozens of more optimized solutions to this problem (likely tied to the iteration count) but I’m happy with what I’ve provided below — and now those burgers and Anaheim peppers won’t have to cook themselves.
As always, any feedback is welcome.
# Euler 32
# http://projecteuler.net/index.php?section=problems&id=32
# We shall say that an n-digit number is pandigital if it
# makes use of all the digits 1 to n exactly once;
# for example, the 5-digit number, 15234, is 1 through 5
# pandigital.
#
# The product 7254 is unusual, as the identity,
# 39 x 186 = 7254, containing multiplicand, multiplier,
# and product is 1 through 9 pandigital.
#
# Find the sum of all products whose multiplicand/
# multiplier/product identity can be written as a 1 through
# 9 pandigital.
#
# HINT: Some products can be obtained in more than one way
# so be sure to only include it once in your sum.
timer_start = Time.now
require 'set'
distinct_products = Set.new
def ordered_value(a, b)
# Build and sort the
# multiplicand/multiplier/product
num = a.to_s + b.to_s + (a*b).to_s
num.split(//).sort.join
end
(1..9999).each do |a|
(a+1..9999).each do |b|
value = ordered_value(a, b)
if value.length == 9 && value == "123456789"
distinct_products << a*b
elsif value.length > 9
# Safely break out of the inner loop because the
# Product isn't going to get any smaller
break
end
end
end
puts distinct_products.inject {|agg, n| agg + n }
puts "Elapsed Time: #{(Time.now - timer_start)*1000} milliseconds"
I actually downloaded Ruby 1.9 for this one, just so I could use the nifty Array.permutation method it includes. I also used the idea that if x has m digits and y has n digits then z = x * y will have either m + n or m + n – 1. Since the total number of digits has to be nine, that means we just need to test one digit numbers times four digit numbers and two digit number times three digit numbers.
#!/usr/bin/ruby def testTwoThree(n) n[0..1].join.to_i * n[2..4].join.to_i == n[5..9].join.to_i end def testOneFour(n) n[0..0].join.to_i * n[1..4].join.to_i == n[5..9].join.to_i end products = [] (1..9).to_a.permutation(9) {|p| products << p[5..9].join.to_i if (testOneFour(p) || testTwoThree(p)) } puts products.uniq.inject {|sum, x| sum + x}