Just a minor nit-pick on the comments
).map{|b| # foreach character b that you get\n "A"..b # make an array "A"..bShould be "make a range from "A" to b. A range object doesn't store every element of the range, but only the first and last elements, so ("A".."B") takes the same amount of storage as ("A".."Z").
Which makes the call to inject interesting. The first time inject invokes its block, a range object is passed as parameter a. The remaining times the flattened array from the previous invocation is passed. Since map works on both arrays and ranges, we don't care.