Last active
August 29, 2015 14:01
-
-
Save chadbrewbaker/372a8075362b81c1adbf to your computer and use it in GitHub Desktop.
Laser maze problem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Chad Brewbaker May 10, 2014 | |
#Laser maze problem | |
def get_coords(s) | |
return s.gsub(/[vVlLrR]/, ' ').strip.split(',').map {|i| i.to_i}.dup | |
end | |
get_coords("1,7V") != [1,7] ? abort("ERROR in get_coords") : nil | |
def laser_paths(line = "") | |
if(line =~ /RL/) | |
return {"N" => "W", "S"=>"N", "E" => "W", "W"=> "N"} | |
end | |
if(line =~ /RR/) | |
return {"N" => "S", "S"=>"E", "E" => "S", "W"=> "E"} | |
end | |
if(line =~ /LR/) | |
return {"N" => "E", "S"=>"N", "E" => "N", "W"=> "E"} | |
end | |
if(line =~ /LL/) | |
return {"N" => "S", "S"=>"W", "E" => "W", "W"=> "S"} | |
end | |
if(line =~ /L/) | |
return {"N" => "E", "S"=>"W", "E" => "N", "W"=> "S"} | |
end | |
if(line =~ /R/) | |
return {"N" => "W", "S"=>"E", "E" => "S", "W"=> "N"} | |
end | |
return {"N" => "S", "S"=>"N", "E" => "W", "W"=> "E"} | |
end | |
def consume_line(l,maze) | |
if(l =~ /-/ ) # SPAM | |
return maze | |
end | |
coords = get_coords(l) | |
if(l =~ /[HV]/ ) #laser | |
maze["Lasers"] = maze["Lasers"].push( [coords,l.dup]) | |
return maze | |
end | |
if( l =~ /[LR]/) #mirror | |
maze[coords] = laser_paths(l) | |
return maze | |
end | |
maze["Boundary"] = coords | |
return maze | |
end | |
def get_laser_vectors(maze) | |
lasers = [] | |
boundary = maze["Boundary"] | |
maze["Lasers"].each{ |l| | |
coords = l[0] | |
if(l[1] =~ /H/ ) | |
if(boundary[0]-1 == coords[0]) | |
lasers.push([coords.dup, "E"]) | |
end | |
if(coords[0]==0) | |
lasers.push([coords.dup, "W"]) | |
end | |
end | |
if(l[1] =~ /V/) | |
if(boundary[1]-1 == coords[0]) | |
lasers.push([coords.dup, "N"]) | |
end | |
if(coords[1]==0) | |
lasers.push([coords.dup, "S"]) | |
end | |
end | |
} | |
return lasers | |
end | |
def opposite(direction) | |
h = {"N" => "S", "S"=>"N", "E" => "W", "W"=> "E"} | |
return h[direction] | |
end | |
opposite("N") != "S" ? abort("ERROR in opposite") : nil | |
def next_cell(vec,path) | |
h = {"N" =>[0,1] , "E" => [1,0] , "W" => [-1,0], "S" => [0,-1]} | |
direction = h[path[vec[1]]] | |
new_coord = vec[0].zip(direction).map{ |x,y| x + y } | |
return [ new_coord, opposite(path[vec[1]]) ] | |
end | |
next_cell([[1,1],"N"], {"N" => "S", "S"=>"N", "E" => "W", "W"=> "E"}) != [[1,0],"N"] ? abort("ERROR in next_cell") : nil | |
next_cell([[1,1],"E"], {"N" => "S", "S"=>"N", "E" => "W", "W"=> "E"}) != [[0,1],"E"] ? abort("ERROR in next_cell") : nil | |
def in_maze(coords, boundary) | |
if(coords[0] < 0 || coords[0] >= boundary[0]) | |
return false | |
end | |
if(coords[1] < 0 || coords[1] >= boundary[1]) | |
return false | |
end | |
return true | |
end | |
in_maze([0,0],[1,1]) == false ? abort("ERROR in in_maze") : nil | |
in_maze([1,0],[1,1]) == true ? abort("ERROR in in_maze") : nil | |
in_maze([0,1],[1,1]) == true ? abort("ERROR in in_maze") : nil | |
in_maze([-1,0],[1,1]) == true ? abort("ERROR in in_maze") : nil | |
in_maze([0,-1],[1,1]) == true ? abort("ERROR in in_maze") : nil | |
def to_hv(str) | |
if str =~ /[EW]/ | |
return "H" | |
else | |
return "V" | |
end | |
end | |
to_hv("E") != "H" ? abort("ERROR in to_hv") : nil | |
to_hv("N") != "V" ? abort("ERROR in to_hv") : nil | |
def print_laserpos(lasers) | |
lasers.each{|l| | |
suffix = (l[1] =~ /H/ )? " Horizontal": " Vertical" | |
puts "Laser Start: "+ l[0][0].to_s + ", " + l[0][1].to_s + suffix | |
} | |
end | |
def print_laser_outputs(laser_outputs) | |
laser_outputs.each{|l| | |
suffix = (l =~ /H/ )? " Horizontal": " Vertical" | |
coords = get_coords(l) | |
puts "Exit Point: "+ coords[0].to_s + ", " + coords[1].to_s + suffix | |
} | |
end | |
#-- Main driver code --# | |
#Default to cells with no mirrors | |
maze = Hash.new({"N" => "S", "S"=>"N", "E" => "W", "W"=> "E"}) | |
maze["Lasers"] = [] | |
maze["Boundary"] = [1,1] | |
STDIN.read.split("\n").each do |line| | |
maze = consume_line(line,maze) | |
end | |
laser_vectors = get_laser_vectors(maze) | |
seen_vectors = {} | |
outputs = {} | |
while(laser_vectors.size > 0) | |
vec = laser_vectors.pop | |
if(maze[vec[0]]) | |
if(seen_vectors[vec.to_s].nil?) | |
#only need to persist mirror paths to avoid cycles | |
seen_vectors[vec.to_s] = true | |
else | |
next | |
end | |
end | |
path = maze[vec[0]] | |
new_vec = next_cell(vec,path) | |
if(!in_maze(new_vec[0],maze["Boundary"])) | |
outputs[ vec[0][0].to_s + "," + vec[0][1].to_s + to_hv(new_vec[1]) ] = true | |
else | |
laser_vectors.push(new_vec) | |
end | |
end | |
puts "Dimensions: "+ maze["Boundary"][0].to_s + ", "+maze["Boundary"][1].to_s | |
print_laserpos(maze["Lasers"]) | |
print_laser_outputs(outputs.keys.to_a) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment