Dave Thomas of the Pragmatic Programmers has started publishing programming problems, calling them Kata. He’s just published Kata 8 this morning and I’ve had a go at a solution. The problem is to take a supplied list of words and go through it finding all the six letter words that are constructed from shorter words in the file. The full problem is to write the program in three different ways: one optimized for human consumption, one optimized for speed, and one that is highly extensible.
Presented below is my first cut at this kata. I think it is fairly readable, at 79 lines, so this probably will count as my “fit for human consumption” version. It’s relatively fast, completing in 11 seconds.
Comments? Critiques?
#!/usr/local/bin/ruby start = Time.now # Arrays for each class of word fourLetters = Array.new threeLetters = Array.new twoLetters = Array.new sixLetters = Array.new # Loop over the word list, segregating the words # to their respective array IO.foreach("wordlist.txt") do |line| line.chomp!.downcase! case line.length when 2 twoLetters << line when 3 threeLetters << line when 4 fourLetters << line when 6 sixLetters << line end end candidates = Array.new # Build up all combinations of four letters + two letters # and store in them as candidates fourLetters.each do |four| twoLetters.each do |two| wc = four + two candidates << wc end end # Build up all combinations of three letters + three # letters and store them as candidates threeLetters.each do |three| threeLetters.each do |otherThree| wc = three + otherThree candidates << wc end end # Finally, all combinations of two letters + two letters # + two letters and store those as candidates twoLetters.each do |firstTwo| twoLetters.each do |secondTwo| twoLetters.each do |thirdTwo| wc = firstTwo + secondTwo + thirdTwo candidates << wc end end end # Now get rid of dups and sort in place candidates.uniq!.sort! puts "Candidates = #{candidates.length}" # # And the two arrays together leaving only those words # that appear in both lists matches = sixLetters & candidates # Now write the matches to a file File.open("matches.txt", "w") do |file| matches.each do |word| file.puts(word) end end finish = Time.now puts "Started at #{start}" puts "Finished at #{finish}" puts "Total time #{finish.to_i - start.to_i}"