Aug
15
In my attempt to learn Ruby out in the open, here’s my solution for Project Euler Problem 42.
I don’t have much to say about this problem except for the fact that it holds strong ties to Euler 12 and Euler 22 so it doesn’t take long to piece this solution together. Minor note — you’ll notice I used reduce in the word_value method. I figured after my little rant about inject vs reduce the other day I should actually make the move to my preferred syntax.
As always, any feedback is welcome.
# Euler 42
# http://projecteuler.net/index.php?section=problems&id=42
# The nth term of the sequence of triangle numbers is
# given by, tn = ½n(n+1); so the first ten triangle numbers
# are:
#
# 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
#
# By converting each letter in a word to a number
# corresponding to its alphabetical position and adding
# these values we form a word value. For example, the word
# value for SKY is 19 + 11 + 25 = 55 = t10. If the word
# value is a triangle number then we shall call the word a
# triangle word.
#
# Using words.txt (right click and 'Save Link/Target As...'),
# a 16K text file containing nearly two-thousand common
# English words, how many are triangle words?
timer_start = Time.now
def word_value(word)
word.enum_for(:each_byte) \
.map { |c| c - 64 } \
.reduce(0, :+)
end
def triangle_numbers(n)
i,current_triangle = 0,0
triangles = []
n.times do
i += 1
current_triangle += i
triangles << current_triangle
end
triangles
end
# We could limit the array of triangles
# based on the max word value but simply
# grabbing the first 100 will do.
triangles = triangle_numbers(100)
text = File.open("words.txt", "r").gets
words = text.gsub!('"','').split(',').sort
puts words.each \
.map { |word | word_value(word) } \
.select { |value| triangles.include?(value) } \
.count
puts "Elapsed Time: #{(Time.now - timer_start)*1000} milliseconds"