divvy_up 0.1.0 → 0.1.1
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 +4 -4
- data/CHANGELOG.md +5 -2
- data/lib/divvy_up/list.rb +48 -53
- data/lib/divvy_up/version.rb +1 -1
- data/spec/divvy_up/list_spec.rb +11 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7428ae33e30e958f738f5af7e4ae41fdd667774c
|
4
|
+
data.tar.gz: 7b499f0c387fc0f36dbc6b6119d0e7ec0f624986
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d6402894878432babb2ed1c555fd042b1aeed327a7c11b7f7cc4fd579e7daaa7b531cdd9ed30759c39e73f94c0fddf04fce8cbfe72d3f9f41d04e113dfecac8
|
7
|
+
data.tar.gz: 31025cac7d76fbe7294fbb0fcb41f25b56d04fd33a274703e6e604977b84efecb9d84ecacea46ba445a534982a4d293ec041f9cf7c93214cde5b49394c81ed13
|
data/CHANGELOG.md
CHANGED
@@ -4,7 +4,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
4
4
|
|
5
5
|
## [Unreleased]
|
6
6
|
|
7
|
-
|
7
|
+
## [0.1.1] - 2015-07-05
|
8
|
+
### Fixed
|
9
|
+
- Resolve error occurring in `#split` method for certain list and group number combinations
|
8
10
|
|
9
11
|
## [0.1.0] - 2015-07-04
|
10
12
|
### Changed
|
@@ -13,5 +15,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
13
15
|
## 0.0.1 - 2015-03-09
|
14
16
|
- Initial release
|
15
17
|
|
16
|
-
[unreleased]: https://github.com/djpowers/divvy_up/compare/v0.1.
|
18
|
+
[unreleased]: https://github.com/djpowers/divvy_up/compare/v0.1.1...HEAD
|
19
|
+
[0.1.1]: https://github.com/djpowers/divvy_up/compare/v0.0.1...v0.1.1
|
17
20
|
[0.1.0]: https://github.com/djpowers/divvy_up/compare/v0.0.1...v0.1.0
|
data/lib/divvy_up/list.rb
CHANGED
@@ -7,27 +7,27 @@ module DivvyUp
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def split(groups)
|
10
|
-
|
11
|
-
|
10
|
+
@groups = groups
|
11
|
+
return [self.items] if @groups == 1
|
12
|
+
determine_best_result
|
12
13
|
end
|
13
14
|
|
14
15
|
private
|
15
16
|
|
16
|
-
def permute
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
calculate_list_totals(list_possibilities, groups)
|
17
|
+
def permute
|
18
|
+
sublists = sublist_permutations
|
19
|
+
price_differences = sublist_price_differences(sublists)
|
20
|
+
sublist_options_sorted = sort_sublist_options(price_differences)
|
21
|
+
output_final_sublists(sublist_options_sorted)
|
22
22
|
end
|
23
23
|
|
24
|
-
def snake
|
24
|
+
def snake
|
25
25
|
unassigned_items = self.items.sort_by { |item, price| price }.to_a
|
26
26
|
permutations = []
|
27
|
-
groups.times { permutations << {} }
|
27
|
+
@groups.times { permutations << {} }
|
28
28
|
until unassigned_items.empty? do
|
29
29
|
permutations.each do |permutation|
|
30
|
-
permutation[unassigned_items.last.first] = unassigned_items.last.last
|
30
|
+
permutation[unassigned_items.last.first] = unassigned_items.last.last unless unassigned_items.empty?
|
31
31
|
unassigned_items.pop
|
32
32
|
end
|
33
33
|
permutations.reverse_each do |permutation|
|
@@ -35,66 +35,62 @@ module DivvyUp
|
|
35
35
|
unassigned_items.pop
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
output_final_sublists(permutations)
|
39
39
|
end
|
40
40
|
|
41
|
-
def price_is_right
|
41
|
+
def price_is_right
|
42
42
|
unassigned_items = self.items.sort_by { |item, price| price }.to_a
|
43
43
|
permutations = []
|
44
|
-
groups.times { permutations << {} }
|
44
|
+
@groups.times { permutations << {} }
|
45
45
|
permutations.each do |permutation|
|
46
46
|
total = 0
|
47
|
-
until total > target_amount
|
47
|
+
until total > target_amount || unassigned_items.empty? do
|
48
48
|
next_item = unassigned_items.pop
|
49
49
|
permutation[next_item.first] = next_item.last
|
50
50
|
total = permutation.values.reduce(:+).nil? ? 0 : permutation.values.reduce(:+)
|
51
|
-
if total > target_amount
|
51
|
+
if total > target_amount
|
52
52
|
permutation.delete(next_item.first)
|
53
53
|
unassigned_items << next_item
|
54
54
|
end unless permutation == permutations.last || permutation.count == 1
|
55
55
|
end
|
56
56
|
end
|
57
|
-
|
57
|
+
output_final_sublists(permutations)
|
58
58
|
end
|
59
59
|
|
60
|
-
def target_amount
|
61
|
-
(self.items.values.reduce(:+) /
|
60
|
+
def target_amount
|
61
|
+
(self.items.values.reduce(:+) / @groups).round(2)
|
62
62
|
end
|
63
63
|
|
64
|
-
def
|
65
|
-
|
64
|
+
def sublist_permutations
|
65
|
+
sublists = []
|
66
66
|
self.items.keys.size.times do |n|
|
67
|
-
|
68
|
-
sets.each do |set|
|
69
|
-
permutations << set
|
70
|
-
end
|
67
|
+
self.items.keys.combination(n+1).collect {|x| sublists << x}
|
71
68
|
end
|
72
|
-
|
69
|
+
sublists
|
73
70
|
end
|
74
71
|
|
75
|
-
def
|
76
|
-
|
72
|
+
def sublist_price_differences(permutations)
|
73
|
+
price_differences = {}
|
77
74
|
permutations.each do |permutation|
|
78
75
|
total = 0.0
|
79
76
|
permutation.each_with_index do |item, n|
|
80
77
|
total += self.items[item]
|
81
78
|
end
|
82
|
-
|
79
|
+
price_differences[permutation] = (target_amount - total).abs
|
83
80
|
end
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
def generate_list_combinations(permutation_price_differences)
|
88
|
-
permutation_price_differences.values.sort
|
81
|
+
price_differences
|
89
82
|
end
|
90
83
|
|
91
|
-
def
|
84
|
+
def sort_sublist_options(price_differences)
|
92
85
|
list = []
|
86
|
+
sorted_price_differences = price_differences.values.sort
|
93
87
|
sorted_price_differences.each do |difference|
|
94
88
|
if sorted_price_differences.count(difference) == 1
|
95
|
-
list <<
|
89
|
+
list << price_differences.key(difference)
|
96
90
|
else
|
97
|
-
|
91
|
+
price_differences.find_all do |k,v|
|
92
|
+
v == difference
|
93
|
+
end.map(&:first).each do |permutation|
|
98
94
|
list << permutation
|
99
95
|
end
|
100
96
|
sorted_price_differences.delete(difference)
|
@@ -102,47 +98,46 @@ module DivvyUp
|
|
102
98
|
end
|
103
99
|
flattened_list = list.flatten
|
104
100
|
if self.items.keys.sort == flattened_list.uniq.sort
|
105
|
-
|
101
|
+
sublist_options_sorted = []
|
106
102
|
list.each do |sublist|
|
107
103
|
item_price = {}
|
108
104
|
sublist.each do |item|
|
109
105
|
item_price[item] = self.items[item]
|
110
106
|
end
|
111
|
-
|
107
|
+
sublist_options_sorted << item_price
|
112
108
|
end
|
113
109
|
end
|
114
|
-
|
110
|
+
sublist_options_sorted
|
115
111
|
end
|
116
112
|
|
117
|
-
def
|
118
|
-
|
113
|
+
def output_final_sublists(sublist_options_sorted)
|
114
|
+
sublists = []
|
119
115
|
accounted_items = []
|
120
|
-
until
|
121
|
-
|
116
|
+
until sublists.size == @groups
|
117
|
+
sublist_options_sorted.each do |list|
|
122
118
|
if (accounted_items & list.keys).empty?
|
123
|
-
|
119
|
+
sublists << [list, (list.values.reduce(:+)).round(2)]
|
124
120
|
accounted_items << list.keys
|
125
121
|
accounted_items.flatten!
|
126
122
|
end
|
127
123
|
end
|
128
124
|
end
|
129
|
-
|
125
|
+
sublists
|
130
126
|
end
|
131
127
|
|
132
|
-
def determine_best_result
|
133
|
-
permute_result = permute
|
134
|
-
snake_result = snake
|
135
|
-
price_is_right_result = price_is_right
|
128
|
+
def determine_best_result
|
129
|
+
permute_result = permute
|
130
|
+
snake_result = snake
|
131
|
+
price_is_right_result = price_is_right
|
136
132
|
results = [permute_result, snake_result, price_is_right_result]
|
137
|
-
target = target_amount(groups)
|
138
133
|
result_differences = []
|
139
134
|
results.each do |result|
|
140
135
|
result_totals = []
|
141
136
|
result.each do |list|
|
142
137
|
result_totals << list.last
|
143
138
|
end
|
144
|
-
min_difference = (result_totals.min -
|
145
|
-
max_difference = (result_totals.max -
|
139
|
+
min_difference = (result_totals.min - target_amount).abs
|
140
|
+
max_difference = (result_totals.max - target_amount).abs
|
146
141
|
result_differences << (min_difference > max_difference ? min_difference : max_difference)
|
147
142
|
end
|
148
143
|
results[result_differences.index(result_differences.min)]
|
data/lib/divvy_up/version.rb
CHANGED
data/spec/divvy_up/list_spec.rb
CHANGED
@@ -76,5 +76,16 @@ module DivvyUp
|
|
76
76
|
]
|
77
77
|
)
|
78
78
|
end
|
79
|
+
|
80
|
+
it "splits a large list into three groups" do
|
81
|
+
shopping_list = { orange_juice: 3, eggs_dozen_1: 2.99, eggs_dozen_2: 2.99, frozen_strawberries: 2.99, spring_mix: 4.99, bacon: 4.99, onion: 1.25, rasberries: 3.99, paper_towels: 1.59 }
|
82
|
+
list = DivvyUp::List.new(shopping_list)
|
83
|
+
expect(list.split(2)).to eql(
|
84
|
+
[
|
85
|
+
[{orange_juice: 3, spring_mix: 4.99, bacon: 4.99, onion: 1.25}, 14.23],
|
86
|
+
[{eggs_dozen_1: 2.99, eggs_dozen_2: 2.99, frozen_strawberries: 2.99, rasberries: 3.99, paper_towels: 1.59}, 14.55]
|
87
|
+
]
|
88
|
+
)
|
89
|
+
end
|
79
90
|
end
|
80
91
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: divvy_up
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dave Powers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|