box_packer 0.0.1 → 0.0.2
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 +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
|