lib/minimizes_partition/minimizes_partition.rb |
104 |
82 |
|
|
1 module MinimizesPartition |
2 class MinimizesPartition |
3 attr_accessor :original_list, :word_list , :already_tried_letters |
4 |
5 def word_list=(list) |
6 @original_list = list.dup |
7 end |
8 |
9 def new_game(guesses_left) |
10 @already_tried_letters = [] |
11 @last_guess_correct = true |
12 @word_list = @original_list |
13 end |
14 |
15 def guess(word, guesses_left) |
16 filter_word_list_by_word_pattern(word) if @last_guess_correct |
17 letter_with_least_worst_case #letter that reveals most information by guessing it |
18 end |
19 |
20 def incorrect_guess(guess) |
21 @last_guess_correct = false |
22 @already_tried_letters << guess |
23 filter_word_list_by_incorrect_letter guess |
24 end |
25 |
26 def correct_guess(guess) |
27 @last_guess_correct = true |
28 @already_tried_letters << guess |
29 end |
30 |
31 def fail(reason) |
32 end |
33 |
34 def game_result(result, word) |
35 end |
36 |
37 def letter_with_least_worst_case |
38 least_worst_case_so_far = @word_list.size + 1 |
39 |
40 potential_remaining_letters.each do |letter| |
41 |
42 number_of_non_matches = number_of_words_that_do_not_match(letter) |
43 if number_of_non_matches >= half_the_word_list_size |
44 new_potential_worst_case_for_this_letter = number_of_non_matches |
45 else |
46 new_potential_worst_case_for_this_letter = minimum_of_worse_case_found_for_this_letter_and_least_worse_case_so_far(letter,least_worst_case_so_far) |
47 end |
48 |
49 if new_potential_worst_case_for_this_letter < least_worst_case_so_far |
50 least_worst_case_so_far = new_potential_worst_case_for_this_letter |
51 @least_worse_case_letter = letter |
52 end |
53 |
54 end |
55 @least_worse_case_letter |
56 end |
57 |
58 def potential_remaining_letters |
59 @word_list.join.split(//).uniq - already_tried_letters |
60 end |
61 |
62 def minimum_of_worse_case_found_for_this_letter_and_least_worse_case_so_far(letter,best_size_so_far) |
63 parts = Hash.new{|hash, key| hash[key] = 0} |
64 @word_list.each do |word| |
65 parts[word.tr('^'+letter,'*')] += 1 |
66 if parts[word.tr('^'+letter,'*')] > best_size_so_far |
67 return best_size_so_far #ie this letter is no better |
68 end |
69 end |
70 return parts.values.sort[-1] |
71 end |
72 |
73 def regex_from_word_pattern(word_pattern) |
74 Regexp.new('^' + word_pattern.gsub(/_/, '\w') + '$', true) |
75 end |
76 |
77 def number_of_words_that_do_not_match(letter) |
78 words_that_do_not_match(letter).size |
79 end |
80 |
81 private |
82 |
83 def words_that_do_not_match(letter) |
84 @word_list.reject do |word| |
85 word.include?(letter) |
86 end |
87 end |
88 |
89 def filter_word_list_by_word_pattern(word_pattern) |
90 @word_list = @word_list.select do |word| |
91 regex_from_word_pattern(word_pattern).match word |
92 end |
93 end |
94 |
95 def filter_word_list_by_incorrect_letter(guess) |
96 @word_list = words_that_do_not_match guess |
97 end |
98 |
99 def half_the_word_list_size |
100 @word_list.size / 2 |
101 end |
102 |
103 end |
104 end |