Created
August 20, 2009 21:04
-
-
Save jawspeak/171375 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| #!/usr/bin/env ruby | |
| require 'pp' | |
| require 'set' | |
| require 'test/unit' | |
| $heights = %w(T S) | |
| $colors = %w(D F) | |
| $looks = %w(H U) | |
| $people = %w(Adam Bond Cruz Dumbo) | |
| class DatingSolver | |
| def initialize | |
| @one_persons_attribute_combos = combinations_for_a_persons_attributes | |
| end | |
| def solve | |
| possibilities = all_possible_date_arrangements | |
| puts "Combinations: #{possibilities.length}" | |
| possibilities.reject!{|row| Set.new([score_person(row['Adam']), score_person(row['Bond']), score_person(row['Cruz']), score_person(row['Dumbo']) ]).length != 4} #rule1 | |
| puts "Combinations, after filtering rule 1: #{possibilities.length}" | |
| possibilities.reject!{|row| row['Bond'].match(/TF/) || row['Cruz'].match(/TF/)} #rule2, demorgan's | |
| puts "Combinations, after filtering rule 2: #{possibilities.length}" | |
| possibilities.reject!{|row| row['Dumbo'].match(/S.H/) || row['Adam'].match(/S.H/)} #rule3, demorgan's | |
| puts "Combinations, after filtering rule 3: #{possibilities.length}" | |
| possibilities.reject!{|row| (row['Adam'].match(/T/) && row['Cruz'].match(/S/)) || (row['Adam'].match(/S/) && row['Cruz'].match(/T/))} # rule4 | |
| puts "Combinations, after filtering rule 4: #{possibilities.length}" | |
| possibilities.reject!{|row| (row['Dumbo'].match(/D/) && row['Bond'].match(/F/)) || (row['Dumbo'].match(/F/) && row['Bond'].match(/D/))} #rule5 | |
| puts "Combinations, after filtering rule 5: #{possibilities.length}" | |
| i = 0 | |
| dates = {} | |
| possibilities.each do |row| | |
| row.each do |name, attributes| | |
| if attributes.match(/TDH/) | |
| dates[name] = 1 unless dates[name] | |
| dates[name] = dates[name]+1 if dates[name] | |
| end | |
| end | |
| end | |
| # every one of the remaining possibilities must have a TDH person in there, because they have 1, 2, 3, adn 4 matching attributes in rule1 | |
| pp possibilities | |
| # but these are the number of times each person came up as a TDH person. | |
| puts "Frequencies per dater: " | |
| pp dates | |
| end | |
| def score_person(person_attributes) | |
| score = 0 | |
| score += 1 if person_attributes.match(/T/) | |
| score += 1 if person_attributes.match(/D/) | |
| score += 1 if person_attributes.match(/H/) | |
| score | |
| end | |
| def combinations_for_a_persons_attributes() | |
| attribute_combos = [] | |
| $heights.each do |height| | |
| $colors.each do |color| | |
| $looks.each do |look| | |
| attribute_combos << height + color + look | |
| end | |
| end | |
| end | |
| attribute_combos | |
| end | |
| def combinations_for_all_peoples | |
| peoples_attributes = {} | |
| $people.each do |person| | |
| peoples_attributes[person] = combinations_for_a_persons_attributes() | |
| end | |
| peoples_attributes | |
| end | |
| # all possible arrangements, including invalid ones that don't meet rules | |
| def all_possible_date_arrangements | |
| combos = [] | |
| $people.each do |person1| | |
| @one_persons_attribute_combos.each do |person1_attribute_option| | |
| $people.reject{|p| Set.new([person1]).member?(p)}.each do |person2| | |
| @one_persons_attribute_combos.each do |person2_attribute_option| | |
| $people.reject{|p| Set.new([person1, person2]).member?(p)}.each do |person3| | |
| @one_persons_attribute_combos.each do |person3_attribute_option| | |
| $people.reject{|p| Set.new([person1, person2, person3]).member?(p)}.each do |person4| | |
| @one_persons_attribute_combos.each do |person4_attribute_option| | |
| row = {} | |
| row[person1] = person1_attribute_option | |
| row[person2] = person2_attribute_option | |
| row[person3] = person3_attribute_option | |
| row[person4] = person4_attribute_option | |
| # # reject these, could do it this way too | |
| # next if row['Bond'].match(/TF/) || row['Cruz'].match(/TF/) #rule2, demorgan's | |
| # next if row['Dumbo'].match(/S.H/) || row['Adam'].match(/S.H/) #rule3, demorgan's | |
| # next if (row['Adam'].match(/T/) && row['Cruz'].match(/S/)) || (row['Adam'].match(/S/) && row['Cruz'].match(/T/)) # rule4 | |
| # next if (row['Dumbo'].match(/D/) && row['Bond'].match(/F/)) || (row['Dumbo'].match(/F/) && row['Bond'].match(/D/)) #rule5 | |
| combos << row | |
| puts "Calculating combinations #{combos.length} ..." if combos.length % 10000 == 0 | |
| end | |
| end | |
| end | |
| end | |
| end | |
| end | |
| end | |
| end | |
| combos | |
| end | |
| end | |
| class DatingSolverTest < Test::Unit::TestCase | |
| def test_2_exp_8_attribute_combos | |
| attribute_combos = DatingSolver.new.combinations_for_a_persons_attributes | |
| assert attribute_combos.length == 2**3 | |
| end | |
| def test_score_for_row | |
| solver = DatingSolver.new | |
| assert_equal 0, solver.score_person("SFU") | |
| assert_equal 1, solver.score_person("TFU") | |
| assert_equal 2, solver.score_person("TDU") | |
| assert_equal 3, solver.score_person("TDH") | |
| assert_equal 1, solver.score_person("SDU") | |
| assert_equal 2, solver.score_person("SDH") | |
| assert_equal 1, solver.score_person("SFH") | |
| end | |
| end | |
| # THIS RUNS THE SOLVER | |
| DatingSolver.new.solve |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment