Langton's ant: Difference between revisions
Content added Content deleted
Line 3,252: | Line 3,252: | ||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
<lang ruby>class Ant |
<lang ruby>class Ant |
||
Directions = [:north, :east, :south, :west] |
|||
class OutOfBoundsException < StandardError; end |
|||
def initialize(plane, pos_x, pos_y) |
|||
class Plane |
|||
@plane = plane |
|||
def initialize(x, y) |
|||
@position = Position.new(plane, pos_x, pos_y) |
|||
@size_x, @size_y = x, y |
|||
@cells = Array.new(y) {Array.new(x, :white)} |
|||
end |
|||
def white?(px, py) |
|||
@cells[py][px] == :white |
|||
end |
|||
def toggle_colour(px, py) |
|||
@cells[py][px] = (white?(px, py) ? :black : :white) |
|||
end |
|||
def check_bounds(px, py) |
|||
unless (0 <= px and px < @size_x) and (0 <= py and py < @size_y) |
|||
raise OutOfBoundsException, "(#@size_x, #@size_y)" |
|||
end |
|||
end |
|||
def to_s |
|||
@cells.collect {|row| |
|||
row.collect {|cell| cell == :white ? "." : "#"}.join + "\n" |
|||
}.join |
|||
end |
|||
end |
|||
dir_move = [[:north, [0,-1]], [:east, [1,0]], [:south, [0,1]], [:west, [-1,0]]] |
|||
Move = Hash[dir_move] |
|||
directions = dir_move.map{|dir, move| dir} # [:north, :east, :south, :west] |
|||
Right = Hash[ directions.zip(directions.rotate).to_a ] |
|||
Left = Right.invert |
|||
def initialize(size_x, size_y, pos_x=size_x/2, pos_y=size_y/2) |
|||
@plane = Plane.new(size_x, size_y) |
|||
@pos_x, @pos_y = pos_x, pos_y |
|||
@direction = :south |
@direction = :south |
||
@plane.check_bounds(@pos_x, @pos_y) |
|||
end |
end |
||
attr_reader :plane, :direction, :position |
|||
def run |
def run |
||
moves = 0 |
moves = 0 |
||
loop do |
loop do |
||
begin |
begin |
||
if $DEBUG and moves % 100 == 0 |
|||
system "clear" |
|||
puts "%5d %s" % [moves, position] |
|||
puts plane |
|||
end |
|||
moves += 1 |
moves += 1 |
||
move |
move |
||
Line 3,278: | Line 3,307: | ||
moves |
moves |
||
end |
end |
||
def move |
def move |
||
plane. |
@plane.toggle_colour(@pos_x, @pos_y) |
||
advance |
|||
if plane. |
if @plane.white?(@pos_x, @pos_y) |
||
@direction = Right[@direction] |
|||
turn(:right) |
|||
else |
else |
||
@direction = Left[@direction] |
|||
turn(:left) |
|||
end |
end |
||
end |
end |
||
def |
def advance |
||
dx, dy = Move[@direction] |
|||
@pos_x += dx |
|||
@pos_y += dy |
|||
when :left then @direction = Directions[(idx - 1) % Directions.length] |
|||
@plane.check_bounds(@pos_x, @pos_y) |
|||
when :right then @direction = Directions[(idx + 1) % Directions.length] |
|||
end |
|||
end |
end |
||
end |
|||
def position |
|||
"(#@pos_x, #@pos_y)" |
|||
class Plane |
|||
def initialize(x, y) |
|||
@x = x |
|||
@y = y |
|||
@cells = Array.new(y) {Array.new(x) {Cell.new}} |
|||
end |
end |
||
attr_reader :x, :y |
|||
def at(position) |
|||
@cells[position.y][position.x] |
|||
end |
|||
def to_s |
def to_s |
||
@ |
@plane.to_s |
||
row.collect {|cell| cell.white? ? "." : "#"}.join + "\n" |
|||
}.join |
|||
end |
end |
||
end |
end |
||
class Cell |
|||
def initialize |
|||
@colour = :white |
|||
end |
|||
attr_reader :colour |
|||
def white? |
|||
colour == :white |
|||
end |
|||
def toggle_colour |
|||
@colour = (white? ? :black : :white) |
|||
end |
|||
end |
|||
class Position |
|||
def initialize(plane, x, y) |
|||
@plane = plane |
|||
@x = x |
|||
@y = y |
|||
check_bounds |
|||
end |
|||
attr_accessor :x, :y |
|||
def advance(direction) |
|||
case direction |
|||
when :north then @y -= 1 |
|||
when :east then @x += 1 |
|||
when :south then @y += 1 |
|||
when :west then @x -= 1 |
|||
end |
|||
check_bounds |
|||
end |
|||
def check_bounds |
|||
unless (0 <= @x and @x < @plane.x) and (0 <= @y and @y < @plane.y) |
|||
raise OutOfBoundsException, to_s |
|||
end |
|||
end |
|||
def to_s |
|||
"(%d, %d)" % [x, y] |
|||
end |
|||
end |
|||
class OutOfBoundsException < StandardError; end |
|||
# |
# |
||
# the simulation |
# the simulation |
||
# |
# |
||
ant = Ant |
ant = Ant.new(100, 100) |
||
moves = ant.run |
moves = ant.run |
||
puts "out of bounds after #{moves} moves: #{ant.position}" |
puts "out of bounds after #{moves} moves: #{ant.position}" |
||
puts ant |
puts ant</lang> |
||
{{out}} |
|||
output |
|||
<pre style="height: 40ex; overflow: scroll">out of bounds after 11669 moves: (26, -1) |
<pre style="height: 40ex; overflow: scroll">out of bounds after 11669 moves: (26, -1) |
||
..........................#.#....................................................................... |
..........................#.#....................................................................... |