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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a1f81d17ce9ba4eafe46a66f3aa25828e44499cc
4
- data.tar.gz: 009551861b5cfd507505eba3496164a1a17890d9
3
+ metadata.gz: 7428ae33e30e958f738f5af7e4ae41fdd667774c
4
+ data.tar.gz: 7b499f0c387fc0f36dbc6b6119d0e7ec0f624986
5
5
  SHA512:
6
- metadata.gz: 91fa9383f65ae1ebb2aff88ab916ea7c08e9a17c10d5d8bb7baaf25ff77ea0dd21d1194a5ba4ba36b101b8103c2f273ae1a8661aa43515fa65144ffd5ad42d5f
7
- data.tar.gz: c5a48f2b4c21ce19510a7f00f2421f794c4e293e8aaa97a93ccfb5625760e77cb979a928d57ef0d9cb9526048faf7a1b07ef4bc281b57263c121df314b2c3e63
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
- - Your contribution here!
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.0...HEAD
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
- return [self.items] if groups == 1
11
- determine_best_result(groups)
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(groups)
17
- permutations = generate_list_permutations
18
- permutation_price_differences = calculate_permutation_price_differences(permutations, groups)
19
- sorted_price_differences = generate_list_combinations(permutation_price_differences)
20
- list_possibilities = find_full_list(permutation_price_differences, sorted_price_differences)
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(groups)
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
- calculate_list_totals(permutations, groups)
38
+ output_final_sublists(permutations)
39
39
  end
40
40
 
41
- def price_is_right(groups)
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(groups) || unassigned_items.empty? do
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(groups)
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
- calculate_list_totals(permutations, groups)
57
+ output_final_sublists(permutations)
58
58
  end
59
59
 
60
- def target_amount(divisor)
61
- (self.items.values.reduce(:+) / divisor).round(2)
60
+ def target_amount
61
+ (self.items.values.reduce(:+) / @groups).round(2)
62
62
  end
63
63
 
64
- def generate_list_permutations
65
- permutations = []
64
+ def sublist_permutations
65
+ sublists = []
66
66
  self.items.keys.size.times do |n|
67
- sets = self.items.keys.combination(n+1)
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
- permutations
69
+ sublists
73
70
  end
74
71
 
75
- def calculate_permutation_price_differences(permutations, divisor)
76
- permutation_price_differences = {}
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
- permutation_price_differences[permutation] = (target_amount(divisor) - total).abs
79
+ price_differences[permutation] = (target_amount - total).abs
83
80
  end
84
- permutation_price_differences
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 find_full_list(permutation_price_differences, sorted_price_differences)
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 << permutation_price_differences.key(difference)
89
+ list << price_differences.key(difference)
96
90
  else
97
- permutation_price_differences.find_all{|k,v| v == difference}.map(&:first).each do |permutation|
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
- output = []
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
- output << item_price
107
+ sublist_options_sorted << item_price
112
108
  end
113
109
  end
114
- output
110
+ sublist_options_sorted
115
111
  end
116
112
 
117
- def calculate_list_totals(lists, groups)
118
- output = []
113
+ def output_final_sublists(sublist_options_sorted)
114
+ sublists = []
119
115
  accounted_items = []
120
- until output.size == groups
121
- lists.each do |list|
116
+ until sublists.size == @groups
117
+ sublist_options_sorted.each do |list|
122
118
  if (accounted_items & list.keys).empty?
123
- output << [list, (list.values.reduce(:+)).round(2)]
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
- output
125
+ sublists
130
126
  end
131
127
 
132
- def determine_best_result(groups)
133
- permute_result = permute(groups)
134
- snake_result = snake(groups)
135
- price_is_right_result = price_is_right(groups)
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 - target).abs
145
- max_difference = (result_totals.max - target).abs
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)]
@@ -1,3 +1,3 @@
1
1
  module DivvyUp
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -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.0
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-04 00:00:00.000000000 Z
11
+ date: 2015-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler