Created
March 31, 2012 18:00
-
-
Save spaghetticode/2267162 to your computer and use it in GitHub Desktop.
Mikamai Coding Contest: #3
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
class Maze | |
BREADCRUMBS = '.' | |
WALKABLE = ' ' | |
WALL = 'X' | |
DEAD_END = 'D' | |
attr_reader :map, :coords | |
def initialize(map) | |
@map = map | |
@coords = to_a | |
end | |
def draw_path | |
coords.each_with_index do |row, y| | |
row.each_with_index do |icon, x| | |
@y, @x = y, x | |
walk | |
end | |
end | |
end | |
def to_a | |
rows.inject([]) do |board, row| | |
board << row.split(//).inject([]) {|arr, icon| arr << icon} | |
end | |
end | |
def to_s | |
coords.inject('') do |maze, row| | |
maze << "#{row.join}\n" | |
end.gsub(DEAD_END, ' ') | |
end | |
def walk | |
if current_position == WALKABLE | |
coords[@y][@x] = walkable? ? BREADCRUMBS : DEAD_END | |
end | |
end | |
def rows | |
@rows ||= map.split("\n") | |
end | |
def width | |
rows.first.size | |
end | |
def walkable? | |
nearby_coords.select do |position| | |
[WALL, DEAD_END].include? get(position) | |
end.size < 3 | |
end | |
def current_position | |
get [@y, @x] | |
end | |
def get(coord) | |
coords[coord.first][coord.last] | |
end | |
def nearby_coords | |
[[@y-1, @x], [@y+1, @x], [@y, @x-1], [@y, @x+1]] | |
end | |
end | |
require 'rspec' | |
map = <<-MAZE | |
XXXXXXXXXXXX | |
# XXX X o | |
XXX X X X XX | |
XX XX | |
XXXXXXXXXXXX | |
MAZE | |
solution = <<-MAZE | |
XXXXXXXXXXXX | |
#...XXX X..o | |
XXX.X X X.XX | |
XX .......XX | |
XXXXXXXXXXXX | |
MAZE | |
describe Maze do | |
subject { Maze.new(map) } | |
it 'assings map' do | |
subject.map.should == map | |
end | |
describe '#rows' do | |
it 'splits map in rows' do | |
subject.rows.size.should == 5 | |
end | |
end | |
describe '#width' do | |
it 'returns the map width' do | |
subject.width.should == 12 | |
end | |
end | |
describe '#to_a' do | |
it 'returns bidimensional array' do | |
subject.to_a.should be_an(Array) | |
subject.to_a.first.should be_an(Array) | |
end | |
end | |
describe '#to_s' do | |
it 'returns a string' do | |
subject.to_s.should be_a(String) | |
end | |
context 'when path has not been walked yet' do | |
it 'returns original map' do | |
subject.to_s.should == map | |
end | |
end | |
end | |
describe '#coords' do | |
it 'returns the maze in array format' do | |
subject.coords.should == subject.to_a | |
end | |
end | |
describe '#get' do | |
it 'wraps array access to coords' do | |
subject.get([1,2]).should == subject.coords[1][2] | |
end | |
end | |
describe '#current_position' do | |
it 'should return the icon in the current position' do | |
subject.instance_eval { @x, @y = 11, 1 } | |
subject.current_position.should == 'o' | |
end | |
end | |
describe '#nearby_coords' do | |
it 'returns an array of coordinates' do | |
subject.instance_eval { @x, @y = 2, 1} | |
subject.nearby_coords.should =~ [[0, 2], [2, 2], [1, 1], [1,3]] | |
end | |
end | |
describe '#walkable?' do | |
context 'when the coord is surrounded by 3 or more walls/dead ends' do | |
it 'is false' do | |
subject.instance_eval {@x, @y = 2, 3} | |
subject.should_not be_walkable | |
end | |
end | |
context 'when the coord is surrounded by less than 3 walls/dead ends' do | |
it 'is true' do | |
subject.instance_eval {@x, @y = 1, 1} | |
subject.should be_walkable | |
end | |
end | |
end | |
describe '#walk' do | |
context 'when the coord is walkable' do | |
it 'should change it to breadcrumbs icon' do | |
subject.instance_eval { @x, @y = 1, 1 } | |
subject.walk | |
subject.get([1, 1]).should == '.' | |
end | |
end | |
end | |
describe '#draw_path' do | |
it 'should draw the path to exit' do | |
subject.draw_path | |
subject.to_s.should == solution | |
end | |
end | |
end | |
puts Maze.new(map).tap {|bc| bc.draw_path}.to_s | |
require 'benchmark' | |
Benchmark.bm do |bm| | |
bm.report 'Andrea Longhi' do | |
10000.times { Maze.new(map).draw_path } | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment