Last active
August 10, 2019 01:14
-
-
Save petertseng/731e11f82b83846439220bdb0cd48aad to your computer and use it in GitHub Desktop.
letter jam help
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
files, hints = ARGV.partition { |x| File.file?(x) } | |
hint = hints.join | |
dict_words = {} | |
hints = (files.empty? ? File.open('words_alpha.txt', ?r) : ARGF).each_line.map { |word| | |
dict_words[word.chomp.downcase] = true | |
} | |
non_letters = hint.chars.reject { |c| (?a..?z).cover?(c) }.uniq | |
non_star_non_letters = non_letters - [?*] | |
star_present = non_letters.include?(?*) | |
raise "invalid non-letters #{non_letters}" unless non_star_non_letters.size == 1 | |
my_letter = non_star_non_letters[0] | |
alphabet = (?a..?z).to_a | |
missing_letters = 'JQVXZ' | |
alphabet.each { |letter| | |
next if missing_letters.include?(letter) | |
possible_star = star_present ? alphabet : [''] | |
possible_words = possible_star.map { |star| | |
candidate = hint.tr(my_letter + ?*, letter + star) | |
candidate if dict_words[candidate] | |
}.compact | |
next if possible_words.empty? | |
puts "#{letter}: #{possible_words}" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'optparse' | |
options = { | |
dummy: [], | |
free_human: [], | |
bonus: [], | |
} | |
OptionParser.new do |opts| | |
opts.banner = "Usage: #{$PROGRAM_NAME} [options]" | |
opts.on("-d", "--dummy=LETTERS", "dummy player letters - give extra clue if entire stack gone, second priority") do |v| | |
options[:dummy] = v.chars | |
end | |
opts.on("-f", "--finished=LETTERS", "finished human letters - become bonus card if used, third priority") do |v| | |
options[:free_human] = v.chars | |
end | |
opts.on("-b", "--bonus=LETTERS", "bonus letters already on table - will be used up, so will try not to use") do |v| | |
options[:bonus] = v.chars | |
end | |
# there may be a finished dummy, but maybe I'll just treat it as finished human and manually correct the designations. | |
end.parse! | |
def freq(letters) | |
letters.group_by(&:itself).transform_values(&:size) | |
end | |
files, letters = ARGV.partition { |x| File.file?(x) } | |
letter_freq = freq(letters.join.chars) | |
p letter_freq | |
hints = (files.empty? ? File.open('words_alpha.txt', ?r) : ARGF).each_line.map { |word| | |
word.chomp! | |
word.downcase! | |
word_letters = freq(word.chars) | |
extra_letters = word_letters.keys - (letter_freq.keys | options[:dummy] | options[:free_human] | options[:bonus]) | |
next if extra_letters.size > 1 | |
# matches of humans we want to help, used to calculate score but not official designation | |
helpful_human_matches = letter_freq.sum { |letter, freq| | |
[freq, (word_letters[letter] || 0)].min | |
} | |
dummy_used = ((word_letters.keys - letter_freq.keys) & options[:dummy]).size | |
free_human_used = ((word_letters.keys - (letter_freq.keys | options[:dummy])) & options[:free_human]).size | |
bonus_used = ((word_letters.keys - (letter_freq.keys | options[:dummy] | options[:free_human])) & options[:bonus]).size | |
{ | |
word: word, | |
designation: [ | |
"#{helpful_human_matches + free_human_used}h", | |
("#{bonus_used}b" if bonus_used > 0), | |
("#{dummy_used}d" if dummy_used > 0), | |
(?* unless extra_letters.empty?), | |
].compact.join(" "), | |
# we will NOT reverse, but we'll look at the bottom of the file, | |
# so give high scores a positive value. | |
score: [ | |
helpful_human_matches, | |
# TODO: for each human in helpful_human_matches, | |
# quantify how certain they could be about their letter? | |
word.size, | |
dummy_used, | |
free_human_used, | |
-bonus_used, | |
extra_letters.empty? ? '_' : '*', | |
], | |
} | |
}.compact | |
hints.sort_by { |h| h[:score] }.each { |h| p h } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
stub_letters = Hash.new { |h, k| h[k] = {} } | |
words_containing = Hash.new(0) | |
seven_or_more = ARGV.delete('-7') | |
specific_pair = if (parg = ARGV.find { |x| x.start_with?('-p') }) | |
ARGV.delete(parg) | |
parg[2..-1] | |
end | |
(ARGV.empty? ? File.open('words_alpha.txt', ?r) : ARGF).each_line { |word| | |
word.chomp! | |
word.downcase! | |
letters = word.chars.uniq | |
next if letters.size > 6 && !seven_or_more | |
letters.each { |letter| | |
words_containing[letter] += 1 | |
stub_letters[word.tr(letter, ?_)][letter] = true | |
} | |
} | |
stub_letters.transform_values! { |v| v.keys.sort } | |
if specific_pair | |
stub_letters.each { |stub, letters| | |
next unless specific_pair.each_char { |c| letters.include?(c) } | |
puts "#{stub}: #{specific_pair.each_char.map { |c| stub.tr(?_, c) }}" | |
} | |
Kernel.exit(0) | |
end | |
pair_freq = Hash.new(0) | |
ambiguous_containing = Hash.new(0) | |
stub_letters.each_value { |letters| | |
letters.combination(2) { |a, b| pair_freq[a + b] += 1 } | |
letters.each { |k| ambiguous_containing[k] += 1 } if letters.size > 1 | |
} | |
alphabet = (?a..?z).to_a | |
mixup_chance = alphabet.map { |letter| | |
n = ambiguous_containing[letter] | |
d = words_containing[letter] | |
[letter, n = ambiguous_containing[letter], d = words_containing[letter], n.fdiv(d)] | |
} | |
max_len = words_containing.values.max.to_s.size | |
fmtd = "%#{max_len}d" | |
mixup_chance.sort_by(&:last).reverse_each { |x| puts "%s: #{fmtd} / #{fmtd} = %8.6f" % x } | |
max_len = pair_freq.values.max.to_s.size | |
fmtd = "%#{max_len}d" | |
fmts = "%#{max_len}s" | |
header = ([' ' * max_len] + alphabet.map { |x| fmts % x }).join(' ') | |
puts header | |
alphabet.each { |a| | |
puts ([fmts % a] + alphabet.map { |b| fmtd % pair_freq[[a, b].sort.join] } + [a]).join(' ') | |
} | |
puts header | |
pair_freq.to_a.sort_by(&:last).reverse_each { |x| p x } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment