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 +8 -8
- data/README.md +2 -0
- data/lib/box_packer/version.rb +1 -1
- data/lib/box_packer.rb +1 -1
- data/lib/tc_box_packer.rb +171 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MmU3YzNiYTFmYzA1YTM5MzFiYTc0NDA4MzYzODQ4YWQwZGM1OTI5Yg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NjdhYzg2OGM1ZjRhZDBjNTBiOWVlYzkwNjE5NGFlMDRjZmIwNTIzYw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZTNkNmJmZWI4ODI5YzE0MjY2ZTcyZjI2OWJkZWE4NjhjY2VmNDg3MDBkOTI4
|
10
|
+
YjQ1MDEwY2UwZDhlYjA1NjI0OWJhODhkNGQ4YmQ4MjNkZDZiZTkzZmVhNmVk
|
11
|
+
NzE3MWM0MTA2M2VmYTg0YTk0NzQxYTc2NWFjNmYyNTMzNTkxNDY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OThjYjRlOWRhMDQ5OTMyNzNjNDI0M2QxNTRmYzE0NGM4ODYyMTM2YzA2MTVj
|
14
|
+
YTE0ZDdlMmM5MGI4MDU0MTRmYWI3Nzc5NjU0YTRiYjllNWRiNTM0NDFiMGFm
|
15
|
+
OGZmMTljZmJmZTFhYjA4YTgzMDU1MzQwNDkxODVhNDhlZTY1NzU=
|
data/README.md
CHANGED
data/lib/box_packer/version.rb
CHANGED
data/lib/box_packer.rb
CHANGED
@@ -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.
|
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-
|
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
|