divvy_up 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|