pairs 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: {}