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"

One Comment to “Project Euler 32: Ruby”

  1. Greg Charles says:

    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}
    

Leave a Reply

You can wrap your code with [ruby][/ruby] or [python][/python] blocks for syntax highlighting and you can use these traditional tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>