I recently wrote a name generator that uses a DTMC underneath (I asked about it here) and, since I'm not entirely confident I did it right, I wrote a script to check my code, or at least its output.
It works pretty well, but, being new to the language, I want to know how to make it more idiomatic. Performance boosts (in terms of speed and memory efficiency) would also be a plus, but since this is just a simple test script they're not as important.
# arguments: '-dDELIMITER'
if ARGV[0] == '-h'
[
'Should be used in the form:',
'<invocation of name_gen.rb> | <ruby> name_gen_test.rb -d<delimiter>',
'The delimiter MUST be specified in name_gen.rb and it MUST NOT be ``.'
].each { |line| puts line }
end
DELIMITER = ARGV[0] || abort('You must specify a delimiter as the sole command-line argument')
connections = Hash.new { |hash, key| hash[key] = Hash.new 0 }
start = Hash.new 0
until (cur_line = STDIN.gets).nil?
cur_line.chomp!
individual_syllables = cur_line.split DELIMITER
individual_syllables.each_with_index { |from, index|
start[from] += 1 if index == 0
connections[from][individual_syllables[index + 1] || !!false] += 1
}
end
# % of start per syllable
# % of connections to each syllable it connected to
puts 'Start:'
total_start_count = start.values.inject(:+).to_f
max_len = start.keys.inject (0) { |memo, cur|
(cur.length > memo) ? cur.length : memo
}
start.each { |text, percent|
puts " #{text.ljust max_len} : #{(percent * 100 / total_start_count).round.to_i}%"
# Get the percent -> Truncate -> convert to string -> justify
}
puts
END_MARKER = '[end]'
puts 'Connections:'
connections.each { |from, links|
total_connection_count = links.values.inject(:+).to_f
max_len = links.keys.inject(END_MARKER.length) { |memo, cur|
((cur ? cur : '').length > memo) ? cur.length : memo
}
puts " #{from}:"
links.each { |to, probability|
next unless to
puts " #{to.ljust max_len} : #{(probability * 100 / total_connection_count).round.to_i}%"
}
puts " #{END_MARKER} : #{(links[false] * 100 / total_connection_count).round.to_i}%"
}
This is the name generator; this script is meant to be used something like this (on Windows, at least):
ruby name_gen.rb dict.txt 10000 -d_ | ruby name_gen_test.rb _
if the dictionary of syllables is located at 'dict.txt'.
Here's an example dictionary file:
a|1|1|b,2;c,2 b|0|3|a,0;c,2 c|0|0|a,1;b,1
And an example output for the script:
Start: a : 100% Connections: a: c : 40% b : 40% [end] : 20% c: a : 50% b : 50% [end] : 0% b: c : 40% [end] : 60%
For anyone interested, the final code is available here.