box_packer 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NzdjZDhlOTBiNmZmYjI3Zjc2ZDA2MTE2YWVlNWJiYWE0NmIwMjExMg==
4
+ MmU3YzNiYTFmYzA1YTM5MzFiYTc0NDA4MzYzODQ4YWQwZGM1OTI5Yg==
5
5
  data.tar.gz: !binary |-
6
- N2E1MDhjOTY1ZmQ5YjQ4M2M0MjUzMmY4ZTE4NzI5ZTNlOWEyYTY0OA==
6
+ NjdhYzg2OGM1ZjRhZDBjNTBiOWVlYzkwNjE5NGFlMDRjZmIwNTIzYw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ODMxODdhNTE5OWQ4ZTNkNzFkZGJlYzY2ODJlYzU3OWMyNDQzNTBmNDAzYTlm
10
- MjJkMWZhOGVmMjkyM2MxNzc3ZDJhZGQzODJkNjFmMTVlMDc0ZTVkNjI2YjE1
11
- YzYwMjZhY2FkMGQ0YTZlZDU5Y2ZiYmU3MzVmOGYxNmU2OTRhZGQ=
9
+ ZTNkNmJmZWI4ODI5YzE0MjY2ZTcyZjI2OWJkZWE4NjhjY2VmNDg3MDBkOTI4
10
+ YjQ1MDEwY2UwZDhlYjA1NjI0OWJhODhkNGQ4YmQ4MjNkZDZiZTkzZmVhNmVk
11
+ NzE3MWM0MTA2M2VmYTg0YTk0NzQxYTc2NWFjNmYyNTMzNTkxNDY=
12
12
  data.tar.gz: !binary |-
13
- NmZkNTgzYzA3ZWYyZTI2YjdjMGJjZjhkM2Y0YTYyMmRmYmNkZjI4ZGUwNGE1
14
- YTFmMzhhYjcwZTZjNTBlZDVlMWZmNzliOThlNGM2OTlhN2ZiZjU5MjU4ZWE1
15
- NmMxNTM3NmVhNjIwYzQ4NzkyOWM5ZDczZTBmZWJlZmNmNTBiMjc=
13
+ OThjYjRlOWRhMDQ5OTMyNzNjNDI0M2QxNTRmYzE0NGM4ODYyMTM2YzA2MTVj
14
+ YTE0ZDdlMmM5MGI4MDU0MTRmYWI3Nzc5NjU0YTRiYjllNWRiNTM0NDFiMGFm
15
+ OGZmMTljZmJmZTFhYjA4YTgzMDU1MzQwNDkxODVhNDhlZTY1NzU=
data/README.md CHANGED
@@ -18,6 +18,8 @@ Usage
18
18
  -----
19
19
 
20
20
  ```Ruby
21
+ require "box_packer"
22
+
21
23
  container = BoxPacker::Container.new("MyContainer", [6, 3, 7], 50)
22
24
 
23
25
  container.items << BoxPacker::Item.new("MyItem01", [1, 5, 3], 10)
@@ -1,3 +1,3 @@
1
1
  module BoxPacker
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/box_packer.rb CHANGED
@@ -136,7 +136,7 @@ module BoxPacker
136
136
  end
137
137
 
138
138
  def items_all_light_enough?
139
- @items.all? { |item| item.weight < @weight_limit }
139
+ @items.all? { |item| item.weight <= @weight_limit }
140
140
  end
141
141
 
142
142
  def pack_box(current_items, box_to_pack)
@@ -0,0 +1,171 @@
1
+ require_relative "box_packer"
2
+ require "test/unit"
3
+ require 'benchmark'
4
+
5
+ class TestBoxPacker < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @containers = []
9
+ @containers[0] = BoxPacker::Container.new("A",[10, 1, 1],15)
10
+ @containers[1] = BoxPacker::Container.new("B",[1, 10, 5],50)
11
+ @containers[2] = BoxPacker::Container.new("C",[10, 15, 5],325)
12
+
13
+ @items = []
14
+ @items[0] = BoxPacker::Item.new("a",[1, 1, 1],1)
15
+ @items[1] = BoxPacker::Item.new("b",[3, 1, 1],6)
16
+ @items[2] = BoxPacker::Item.new("c",[5, 5, 1],15)
17
+ @items[3] = BoxPacker::Item.new("d",[5, 5, 5],20)
18
+
19
+ @skip_items_count = false
20
+ end
21
+
22
+ def teardown
23
+ @containers.delete_if{ |container| container.packings.empty? }
24
+ unless @containers.empty?
25
+ assert(@containers[0].packings.map(&:count).reduce(:+) == @containers[0].items.count, "Packed items less than container's list") unless @skip_items_count
26
+ assert(@containers[0].packings.map(&:remaining_weight).all? { |rw| rw >= 0 }, "Packing too heavy")
27
+ end
28
+ end
29
+
30
+ def test_no_items
31
+ assert_nil(@containers[0].pack)
32
+ end
33
+
34
+ def test_items_too_heavy
35
+ @items[0].weight = 16
36
+ @containers[0].items << @items[0]
37
+ assert_nil(@containers[0].pack)
38
+ end
39
+
40
+ def test_items_too_big
41
+ @containers[0].items << @items[2]
42
+ assert_nil(@containers[0].pack)
43
+ end
44
+
45
+ def test_too_many_packings
46
+ @containers[0].packings_limit = 1
47
+ 11.times { @containers[0].items << @items[0] }
48
+ assert_nil(@containers[0].pack)
49
+ @skip_items_count = true
50
+ end
51
+
52
+ def test_1d_one_full_packing
53
+ 7.times { @containers[0].items << @items[0] }
54
+ @containers[0].items << @items[1]
55
+ assert_equal(1, @containers[0].pack)
56
+ assert_equal(0, @containers[0].packings[0].remaining_volume)
57
+ end
58
+
59
+ def test_1d_two_packings_due_to_weight_limit
60
+ 3.times { @containers[0].items << @items[1] }
61
+ assert_equal(2, @containers[0].pack)
62
+ end
63
+
64
+ def test_1d_three_full_packings
65
+ @containers[0].packings_limit = 4
66
+ 3.times { @containers[0].items << @items[0] << @items[1] }
67
+ 18.times { @containers[0].items << @items[0] }
68
+ assert_equal(3, @containers[0].pack)
69
+ end
70
+
71
+ def test_2d_one_full_packing_two_identical_items
72
+ 2.times { @containers[1].items << @items[2] }
73
+ assert_equal(1, @containers[1].pack)
74
+ assert_equal(0, @containers[1].packings[0].remaining_volume)
75
+ end
76
+
77
+ def test_2d_one_full_packing_multiple_items
78
+ 4.times { @containers[1].items << @items[0] }
79
+ 7.times { @containers[1].items << @items[1] }
80
+ @containers[1].items << @items[2]
81
+ check_pack_in_between(@containers[1], 1, 2)
82
+ end
83
+
84
+ def test_2d_three_full_packings
85
+ @containers[1].packings_limit = 5
86
+ 8.times { @containers[1].items << @items[0] }
87
+ 14.times { @containers[1].items << @items[1] }
88
+ 4.times { @containers[1].items << @items[2] }
89
+ check_pack_in_between(@containers[1], 3, 4)
90
+ end
91
+
92
+ def test_3d_one_full_packing_with_identical_items
93
+ 6.times { @containers[2].items << @items[3] }
94
+ assert_equal(1, @containers[2].pack)
95
+ assert_equal(0, @containers[2].packings[0].remaining_volume)
96
+ end
97
+
98
+ def test_3d_one_full_packing_with_multiple_items
99
+ 20.times { @containers[2].items << @items[0] }
100
+ 10.times { @containers[2].items << @items[1] }
101
+ 8.times { @containers[2].items << @items[2] }
102
+ 4.times { @containers[2].items << @items[3] }
103
+ assert_equal(1, @containers[2].pack)
104
+ assert_equal(0, @containers[2].packings[0].remaining_volume)
105
+ end
106
+
107
+ def test_3d_three_full_packings
108
+ @containers[2].packings_limit = 5
109
+ 35.times { @containers[2].items << @items[0] }
110
+ 30.times { @containers[2].items << @items[1] }
111
+ 10.times { @containers[2].items << @items[2] }
112
+ 15.times { @containers[2].items << @items[3] }
113
+ check_pack_in_between(@containers[2], 3, 4)
114
+ end
115
+
116
+ def test_benchmark
117
+ puts "\n\nBenchmarking\n============"
118
+ iterations = 500
119
+ containers = []
120
+
121
+ (1..iterations).each do |i|
122
+ container_dimensions = [1 + rand(100), 1 + rand(50), 1 + rand(10)]
123
+ container_weight_limit = 1 + rand(1000)
124
+ container = BoxPacker::Container.new("c#{i}", container_dimensions, container_weight_limit)
125
+ container.packings_limit = 50
126
+
127
+ (1..(1+rand(40))).each do |j|
128
+ item_dimensions = container_dimensions.map { |c_dimension| 1 + rand(c_dimension) / (1 + rand(5)) }
129
+ item_weight = 1 + rand(container_weight_limit / (1 + rand(10)))
130
+ container.items << BoxPacker::Item.new("i#{j}", item_dimensions, item_weight)
131
+ end
132
+ containers << container
133
+ end
134
+
135
+ Benchmark.bm(15) do |bm|
136
+ bm.report('Approx packings') do
137
+ containers.each{ |container| container.pack }
138
+ end
139
+ bm.report('Volume') do
140
+ containers.each{ |container| container.pack(:sort_by_volume) }
141
+ end
142
+ bm.report('Shuffled') do
143
+ containers.each{ |container| container.pack(:sort_by_shuffle) }
144
+ end
145
+ end
146
+
147
+ puts "\nBenchmark data\n=============="
148
+ puts "iterations: #{iterations}"
149
+ benchmark_stats = Hash.new{0}
150
+ containers.each do |container|
151
+ benchmark_stats[:avg_container_volume] += container.volume
152
+ benchmark_stats[:avg_packings_count] += container.packings.count
153
+ benchmark_stats[:avg_items_count] += container.items.count
154
+ benchmark_stats[:avg_item_volume] += container.items.map(&:volume).reduce(:+) / container.items.count.to_f
155
+ end
156
+ benchmark_stats.each do |k, v|
157
+ benchmark_stats[k] = v / containers.count.to_f
158
+ puts "#{k}: #{benchmark_stats[k]}"
159
+ end
160
+ puts "\n"
161
+ end
162
+
163
+ private
164
+
165
+ def check_pack_in_between(container, lower_bound, upper_bound)
166
+ assert(container.pack.between?(lower_bound, upper_bound), "Did not pack into #{lower_bound} (or #{upper_bound}) packings")
167
+ assert(container.packings.map(&:remaining_volume).reduce(:+) % container.volume == 0 , "Total remaining volume doesn't add up")
168
+ end
169
+
170
+ end
171
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: box_packer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max White
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-22 00:00:00.000000000 Z
11
+ date: 2014-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,6 +53,7 @@ files:
53
53
  - box_packer.gemspec
54
54
  - lib/box_packer.rb
55
55
  - lib/box_packer/version.rb
56
+ - lib/tc_box_packer.rb
56
57
  homepage: ''
57
58
  licenses:
58
59
  - MIT