-
Notifications
You must be signed in to change notification settings - Fork 1
/
problem.rb
86 lines (70 loc) · 2.41 KB
/
problem.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# Author:: Max Craigie (@MaxCraigie)
# Copyright:: Copyright (c) 2017 Max Craigie
# License:: Attribution-NonCommercial 3.0 Australia (CC BY-NC 3.0 AU)
require './errors.rb'
require './rule.rb'
require 'set'
require 'digest'
module Bongard
class Problem
# TODO: add error checking
def initialize(rule, other_rules, verbose: false)
@rule = rule
puts "Finding diagrams for: #{@rule.description}" if verbose
find_demonstration_diagrams(other_rules, verbose: verbose)
find_answer_diagrams
end
def find_demonstration_diagrams(other_rules, verbose: false)
@followers = Set.new
@rogues = Set.new
loop do
grid = Bongard::Grid.random
grid_follows_rule = @rule.follower?(grid)
# TODO: refactor this using send
if grid_follows_rule
@followers = @followers.to_a.sample(5).to_set if @followers.length > 5
@followers.add(grid)
else
@rogues = @rogues.to_a.sample(5).to_set if @rogues.length > 5
@rogues.add(grid)
end
next unless @followers.length == 6 && @rogues.length == 6
non_covered_overlapping_rules = other_rules.find_all do |r|
@followers.all? { |g| r.follower?(g) } && @rogues.none? { |g| r.follower?(g) }
end.map(&:description)
break if non_covered_overlapping_rules.empty?
puts "Conflict found with #{non_covered_overlapping_rules}. Retrying." if verbose
end
end
def find_answer_diagrams
@correct_answer = nil
@incorrect_answers = Set.new
loop do
grid = Bongard::Grid.random
if @rule.follower?(grid)
@correct_answer = grid
else
@incorrect_answers.add(grid)
@incorrect_answers = @incorrect_answers.to_a.last(2).to_set
end
if !@correct_answer.nil? &&
@incorrect_answers.length == 2 &&
[email protected]?(@correct_answer) &&
[email protected]?(@incorrect_answers)
break
end
end
@answers = [@correct_answer, @incorrect_answers.to_a].flatten.shuffle
end
def to_h
{
id: Digest::MD5.hexdigest(@rule.description),
rule: @rule.description,
correctAnswerId: @correct_answer.hexdigest,
followers: @followers.map(&:to_h),
rogues: @rogues.map(&:to_h),
answers: @answers.map(&:to_h),
}
end
end
end