Skip to content

Instantly share code, notes, and snippets.

@madebydna
Created April 30, 2011 14:17
Show Gist options
  • Save madebydna/949701 to your computer and use it in GitHub Desktop.
Save madebydna/949701 to your computer and use it in GitHub Desktop.
RMU Mentoring: Puzzlenode problem #4
#!/usr/bin/ruby
require 'pp'
f = File.open("input.txt", "r")
o = File.open("output.txt", "w+")
cases = f.readlines ''
cases.each do |c|
kase = c.split("\n").map{|i| i.split('')}
nl = kase[0]
r = kase[1]
sl = kase[2]
max = r.size - 1
start_pos = r.index('X')
#go west
even = true
hits_west = 0
start_pos.downto(0) { |i|
if even
if nl[i] == "|"
hits_west += 1
end
even = false
else
if sl[i] == "|"
hits_west += 1
end
even = true
end
}
#go east
even = true
hits_east = 0
start_pos.upto(max) { |i|
if even
if nl[i] == "|"
hits_east += 1
end
even = false
else
if sl[i] == "|"
hits_east += 1
end
even = true
end
}
if hits_west <= hits_east
o.puts "GO WEST"
else
o.puts "GO EAST"
end
end
module RobotSaver
def self.run
directions = File.open('output_new.txt', 'w+')
full_grid = File.read('input.txt')
conveyor_layouts = RobotFactory.individual_layouts(full_grid)
conveyor_layouts.each do |layout|
factory = RobotFactory.new(layout)
directions.puts factory.least_harmful_direction
end
end
end
class RobotFactory
attr_accessor :active_lasers
def initialize(layout)
@layout = {
:north_laser => layout.split("\n").first.strip,
:conveyor_belt => layout.split("\n")[1].strip,
:south_laser => layout.split("\n").last.strip
}
@robot_position = @layout[:conveyor_belt].index('X')
end
def west_hits
active_lasers[0..@robot_position].count("|")
end
def east_hits
active_lasers[@robot_position..-1].count("|")
end
def active_lasers
@active_lasers = ""
to_check = @robot_position.even? ? [north, south] : [south, north]
if @active_lasers.length == 0
(0..@layout[:conveyor_belt].size - 1).each do |i|
# i % 2 returns 0 or 1
# for even robot starting position the north lasers are on even positions and south lasers are on odd positions
# this is reversed for odd robot starting positions
@active_lasers << to_check[i % 2][i]
end
end
@active_lasers
end
def north
@layout[:north_laser]
end
def south
@layout[:south_laser]
end
def least_harmful_direction
west_hits <= east_hits ? "GO WEST" : "GO EAST"
end
def self.individual_layouts(grid)
grid.split( "\n\n" )
end
end
RobotSaver.run
Robots vs. Lasers Trick:
Create active laser string disregarding north, south or the robots position:
For example: active_lasers = "# | # | # #"
All lasers in this string are of the shooting kind
Then from the robot's position simply count the number of lasers to the east and to the west.
Two possibilities:
1. Robot start position is even:
0 1 2 3 4 5 potentially active north lasers are on even positions (0, 2, 4)
# | # # | #
- - X - - - <= even start position (pos. 2 becomes pos. 0, both are even)
0 1 2 3 4 5
| # # | # | potentially active south lasers are on odd positions (1, 3, 5)
Iterate through the length of the conveyor belt by index. While iterating, check north for active lasers on even positions and south for active lasers on odd positions.
2. Robot start position is odd:
0 1 2 3 4 5 potentially active north lasers are on odd positions (1, 3, 5)
# | # # | #
- - - X - - <= odd start position (pos 3 becomes pos 0, even and odd are reversed)
0 1 2 3 4 5
| # # | # | potentially active south lasers are on even positions (0, 2, 4)
Iterate through the length of the conveyor belt by index. While iterating, check north for active lasers on odd positions and south for active lasers on even positions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment