Created
August 10, 2013 17:37
-
-
Save MrAlexLau/6201331 to your computer and use it in GitHub Desktop.
A simple solution to the "robots vs lasers" puzzle
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
#a simple solution to the "robots vs lasers" puzzle | |
#see http://www.puzzlenode.com/puzzles/4-robots-vs-lasers | |
#usage: | |
#simply run this program with ruby and pass the input file name as the sole argument | |
#example: ruby robots.rb sample-input.txt | |
######################################################### | |
#just use a structure since we only need to hold data | |
#could use a class but it'd be overkill for this example | |
FactoryLine = Struct.new :north_lasers, :conveyor_belt, :south_lasers | |
def read_input(filename) | |
factory_floor = [] | |
factory_line = FactoryLine.new() | |
i = 0 | |
#open the file and read the factory floor input | |
#each factory floor is made of many factory lines | |
#each factory line has 4 lines of text: | |
# 1. the north lasers | |
# 2. the conveyor belt | |
# 3. the south lasers | |
# 4. a blank line separating it from the next factory line | |
# example: | |
# #|#|#|## | |
# ---X---- | |
# ###||### | |
File.open(filename).each_line{ |line| | |
#i mod 4 since there is a new factory line after every 4 lines of input | |
if (i % 4) == 0 | |
factory_line[:north_lasers] = line.strip! | |
elsif (i % 4) == 1 | |
factory_line[:conveyor_belt] = line.strip! | |
elsif (i % 4) == 2 | |
factory_line[:south_lasers] = line.strip! | |
factory_floor << factory_line #append the line to the factory floor array | |
factory_line = FactoryLine.new() | |
end | |
i += 1 | |
} | |
return factory_floor | |
end | |
#put this check in a function so it's easier to test | |
def get_position(conveyor_belt) | |
return conveyor_belt.index("X") | |
end | |
#calculate the total number of hits on the robot | |
#given a laser array (north or south), where the robot is, and if it's going east or west | |
def number_of_hits(laser_array, robot_position, east_west, north_south) | |
number_of_hits = 0 | |
if east_west == :west | |
click = 0 | |
#count from the current position down to the west-most position (aka lowest index) | |
for i in robot_position.downto(0) | |
# if the current index has a laser, check to see if it shoots | |
if laser_array[i] == "|" | |
if north_south == :north and click.even? | |
#the lasers shoot from the north side on even clicks | |
number_of_hits += 1 | |
elsif north_south == :south and click.odd? | |
#the lasers shoot from the south side on odd clicks | |
number_of_hits += 1 | |
end | |
end | |
click += 1 | |
end | |
elsif east_west == :east | |
click = 0 | |
# if the current index has a laser, check to see if it shoots | |
for i in robot_position.upto(laser_array.length - 1) | |
if laser_array[i] == "|" | |
if north_south == :north and click.even? | |
#the lasers shoot from the north side on even clicks | |
number_of_hits += 1 | |
elsif north_south == :south and click.odd? | |
#the lasers shoot from the south side on odd clicks | |
number_of_hits += 1 | |
end | |
end | |
click += 1 | |
end | |
end | |
return number_of_hits | |
end | |
#calculate and print which directions the robot should take | |
#based on its current position in the factory line | |
def get_direction(factory_line) | |
robot_position = get_position(factory_line[:conveyor_belt]) | |
hits_east = 0 | |
hits_west = 0 | |
#calculate the hits going east | |
hits_east = number_of_hits(factory_line[:north_lasers], robot_position, :east, :north) + number_of_hits(factory_line[:south_lasers], robot_position, :east, :south) | |
#calculate the hits going west | |
hits_west = number_of_hits(factory_line[:north_lasers], robot_position, :west, :north) + number_of_hits(factory_line[:south_lasers], robot_position, :west, :south) | |
#return EAST if number of hits going east | |
#is larger than the number of hits going west | |
if hits_east < hits_west | |
return "GO EAST" | |
end | |
#otherwise return WEST if hits_west is greater | |
#or the 2 are equal | |
return "GO WEST" | |
end | |
#actually run the program here | |
#read the input file and print the directions | |
factory_floor = read_input(ARGV[0]) | |
factory_floor.each do |factory_line| | |
puts get_direction(factory_line) | |
end | |
#test methods | |
raise "get_position test 1 failed" unless (get_position("--X---") == 2) | |
raise "get_position test 2 failed" unless (get_position("X------") == 0) | |
raise "get_position test 3 failed" unless (get_position("----X") == 4) | |
raise "number_of_hits test 1 failed" unless (number_of_hits("#|#|#|##", 3, :west, :north) == 2) | |
raise "number_of_hits test 2 failed" unless (number_of_hits("###||###", 3, :west, :north) == 1) | |
raise "number_of_hits test 3 failed" unless (number_of_hits("#|#|#|##", 2, :east, :south) == 2) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment