Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion [SOLUTION] Packing (#62)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
horndud...@gmail.com  
View profile  
 More options Jan 16 2006, 12:31 am
Newsgroups: comp.lang.ruby
From: horndud...@gmail.com
Date: 15 Jan 2006 21:31:05 -0800
Local: Mon, Jan 16 2006 12:31 am
Subject: [QUIZ][SOLUTION] Packing (#62)
Here's my solution. I keep track of the positions of the boxes in each
truckbed and generate the ascii only when it is printed. I was trying
to be fancy with the insertion points, but it became too difficult to
maintain so I just added every point and removed those covered by and
surrounding a box during insertion. I sort the boxes by size to put the
biggest ones in first. I'm fairly happy with my solution. Thanks for
the quiz!

-----Horndude77

class TruckBed
    def initialize(width,height)
        @width,@height = width,height
        @boxes = {}

        #This list maintains where it is possible to add boxes
        @insertion_points = [(0...width).to_a * height,
(0...height).map{|i| [i]*width}.flatten].transpose
        sort_insertion_points
    end

    def insert(box)
        @insertion_points.each do |pos|
            [box, box.reverse].each do |curr_box|
                if fits_at? curr_box, pos then
                    @boxes[pos] = curr_box
                    (-1).upto(curr_box[0]) do |x|
                        (-1).upto(curr_box[1]) do |y|
                            @insertion_points.delete [x+pos[0],
y+pos[1]]
                        end
                    end
                    sort_insertion_points
                    return true
                end
            end
        end
        false
    end

    #Stable sort: keep relative order
    #This way we control where insertions happen
    def sort_insertion_points
        n = 0
        @insertion_points.sort_by{|x| n+=1; [x[1], n]}
        @insertion_points.sort_by{|x| n+=1; [x[0], n]}
    end

    #See if box fits at pos
    def fits_at?(box, pos)
        box_min = pos
        box_max = [pos[0]+box[0]-1, pos[1]+box[1]-1]
        return false if (box_max[0] >= @width) || (box_max[1] >=
@height)
        #check for box intersections
        @boxes.each do |curr_pos, curr_box|
            curr_box_min = [curr_pos[0]-1, curr_pos[1]-1]
            curr_box_max = [curr_pos[0]+curr_box[0],
curr_pos[1]+curr_box[1]]
            return false if box_min[0] <= curr_box_max[0] && box_max[0]

>= curr_box_min[0] &&

                    box_min[1] <= curr_box_max[1] && box_max[1] >=
curr_box_min[1]
        end
        true
    end

    def to_s
        bed = Array.new(@width) { Array.new(@height) {'-'} }
        @boxes.each do |pos,box|
            box[0].times do |x|
                box[1].times do |y|
                    bed[x+pos[0]][y+pos[1]] = 'X'
                end
            end
        end
        bed.transpose.reverse.map {|r| r.join }.join("\n")
    end
end

class String
    def to_dims
        split('x').map {|i| i.to_i}
    end
end

truck_bed_dims = ARGF.gets.to_dims
boxes = ARGF.gets.split.map {|box| box.to_dims.sort.reverse}.sort
{|a,b| a[0]*a[1] <=> b[0]*b[1]}

truck_beds = [TruckBed.new(*truck_bed_dims)]

while boxes.size > 0
    box = boxes.pop
    truck_beds.each do |bed|
        if(bed.insert box) then
            box = nil
            break
        end
    end
    if(box) then
        bed = TruckBed.new(*truck_bed_dims)
        bed.insert(box)
        truck_beds << bed
    end
end

puts
puts truck_beds.join("\n\n")


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.