pairs 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 15663f641b3dd19d88544bcb8f2a76c5ba71a954
4
- data.tar.gz: 06245a8493128bc129b55163dbbfcd7014d43f4a
3
+ metadata.gz: 1c45b4690d8e587e6f573da694da1e9c2de38765
4
+ data.tar.gz: 8fb165db6f151c56d7f46cb02db8f7cfef578a74
5
5
  SHA512:
6
- metadata.gz: 7349ecdb60cb5518f634bf525c781fdbd7a968f4526e99ad3917c722055fdb0fb77bf33dda9f866703d8204e82be074a9ee5fdb2370827e5147385b4bb152e21
7
- data.tar.gz: e91e1664c55340d8e3cabcc92b8cfce40b987dc34945b3d3f63e8da1749df7cec7b3bb4ba08c44f83bd2e7e764e8b275d090d0db1b7779a57636dcaed0da8a48
6
+ metadata.gz: fe982314f97243308c4c5f5084e709c7a840ba66742a2a0450a3eca596e5599522f6954171edd4c591fdac8136c6a17a9292bee13203c489264ef276d4856659
7
+ data.tar.gz: e9b9181531de3bc6b8960b9f962a97eb093f224621fc9394c2e37de679f5fb7e366fbd583fe5f7d7a7b54e9b1803542c385cb84aceade2ad00551ecd9330e112
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0
4
+
5
+ * Add helper constraints `together`, `separate`, `alone`, and `accompanied`
6
+ * Change max_attempts to 10,000
7
+ * Raise an error if unsolvable
8
+ * Create predicate methods for use in constraints
9
+
3
10
  ## 0.1.0
4
11
 
5
12
  * Initial release, basic constraints
data/lib/pairs.rb CHANGED
@@ -1,7 +1,11 @@
1
1
  class Pairs
2
+ class NoSolutionError < StandardError; end
3
+
2
4
  attr_reader :max_attempts, :block
3
5
 
4
- def initialize(max_attempts: 1000, &block)
6
+ MAX_ATTEMPTS = 10_000
7
+
8
+ def initialize(max_attempts: MAX_ATTEMPTS, &block)
5
9
  @max_attempts = max_attempts
6
10
  @block = block
7
11
  end
@@ -16,10 +20,6 @@ class Pairs
16
20
  until all.empty?
17
21
  these = all.sample(2)
18
22
 
19
- next unless clean_room.__constraints__.all? { |constraint|
20
- constraint.call(these)
21
- }
22
-
23
23
  result << these
24
24
 
25
25
  these.each do |item|
@@ -27,8 +27,14 @@ class Pairs
27
27
  end
28
28
  end
29
29
 
30
- return result
30
+ return result if clean_room.__constraints__.all? { |constraint|
31
+ result.all? { |pair|
32
+ constraint.call(pair)
33
+ }
34
+ }
31
35
  end
36
+
37
+ raise NoSolutionError
32
38
  end
33
39
 
34
40
  def solution
@@ -54,9 +60,32 @@ class Pairs
54
60
  __constraints__ << block
55
61
  end
56
62
 
63
+ def together(a, b)
64
+ constraint { |both| both.include?(a) ? both.include?(b) : true }
65
+ end
66
+
67
+ def separate(a, b)
68
+ constraint { |both| both.include?(a) ? !both.include?(b) : true }
69
+ end
70
+
71
+ def alone(a)
72
+ constraint { |both| both.include?(a) ? both == [a] : true }
73
+ end
74
+
75
+ def accompanied(a)
76
+ constraint { |both| both.include?(a) ? both.count == 2 : true }
77
+ end
78
+
57
79
  def method_missing(method_name, *args, &block)
58
80
  return super unless args.count == 1
59
81
 
82
+ predicate_method_name = "#{method_name}?".intern
83
+ unless methods.include?(predicate_method_name)
84
+ define_singleton_method(predicate_method_name) do |item|
85
+ __items__[method_name].include?(item)
86
+ end
87
+ end
88
+
60
89
  __items__[method_name] ||= []
61
90
  __items__[method_name] << args.first
62
91
  end
data/pairs.gemspec CHANGED
@@ -4,12 +4,12 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "pairs"
7
- spec.version = "0.1.0"
7
+ spec.version = "0.2.0"
8
8
  spec.authors = ["Justin Campbell"]
9
9
  spec.email = ["justin@justincampbell.me"]
10
10
  spec.summary = "Constraint solver for pairs"
11
11
  spec.description = "Constraint solver for pairs"
12
- spec.homepage = ""
12
+ spec.homepage = "https://github.com/justincampbell/pairs"
13
13
  spec.license = "MIT"
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0")
@@ -1,7 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Pairs do
4
- let(:pairs) { Pairs.new(&block) }
4
+ let(:pairs) { Pairs.new(max_attempts: max_attempts, &block) }
5
+ let(:max_attempts) { Pairs::MAX_ATTEMPTS }
5
6
  let(:block) { -> { } }
6
7
  let(:solution) { pairs.solution }
7
8
 
@@ -60,4 +61,97 @@ describe Pairs do
60
61
  end
61
62
  end
62
63
  end
64
+
65
+ context "with an unsolvable constraint" do
66
+ let(:block) {
67
+ -> {
68
+ n 1; n 2; n 3
69
+ constraint { |both| both.reduce(:+) == 100 }
70
+ }
71
+ }
72
+ let(:max_attempts) { 1 }
73
+
74
+ generative do
75
+ it "raises a NoSolutionError" do
76
+ expect { solution }.to raise_error(Pairs::NoSolutionError)
77
+ end
78
+ end
79
+ end
80
+
81
+ context "with predicate constraints" do
82
+ let(:block) {
83
+ -> {
84
+ good "a"; good "b"; bad "c"; bad "d"
85
+ constraint { |a, b| !(bad?(a) && bad?(b)) }
86
+ }
87
+ }
88
+
89
+ generative do
90
+ it "returns a solution" do
91
+ expect(solution.size).to eq(2)
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "#together" do
97
+ let(:block) {
98
+ -> {
99
+ item "a"; item "b"; item "c"; item "d"
100
+ together "a", "b"
101
+ }
102
+ }
103
+
104
+ generative do
105
+ it "keeps those 2 items together" do
106
+ expect(solution.any? { |both| both.sort == %w[a b] }).to eq(true)
107
+ end
108
+ end
109
+ end
110
+
111
+ describe "#separate" do
112
+ let(:block) {
113
+ -> {
114
+ item "a"; item "b"; item "c"; item "d"
115
+ separate "a", "b"
116
+ }
117
+ }
118
+
119
+ generative do
120
+ it "keeps those 2 items separate" do
121
+ expect(solution.any? { |both| both.sort == %w[a b] }).to_not eq(true)
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "#alone" do
127
+ context "with an odd number" do
128
+ let(:block) {
129
+ -> {
130
+ item "a"; item "b"; item "c"
131
+ alone "c"
132
+ }
133
+ }
134
+
135
+ generative do
136
+ it "keeps that item alone" do
137
+ expect(solution.last).to eq(["c"])
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ describe "#accompanied" do
144
+ let(:block) {
145
+ -> {
146
+ item "a"; item "b"; item "c"
147
+ accompanied "c"
148
+ }
149
+ }
150
+
151
+ generative do
152
+ it "ensures that item is accompanied" do
153
+ expect(solution.first).to include("c")
154
+ end
155
+ end
156
+ end
63
157
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pairs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Campbell
@@ -84,7 +84,7 @@ files:
84
84
  - pairs.gemspec
85
85
  - spec/lib/pairs_spec.rb
86
86
  - spec/spec_helper.rb
87
- homepage: ''
87
+ homepage: https://github.com/justincampbell/pairs
88
88
  licenses:
89
89
  - MIT
90
90
  metadata: {}