Langton's ant: Difference between revisions
Content added Content deleted
(→{{header|Python}}: more pythonic version (but should use a class)) |
|||
Line 5,397: | Line 5,397: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
<lang python> |
|||
{{trans|D}} |
|||
"""Langton's ant implementation.""" |
|||
<lang python>width = 75 |
|||
from enum import Enum, IntEnum |
|||
height = 52 |
|||
nsteps = 12000 |
|||
class Dir: up, right, down, left = range(4) |
|||
class Turn: left, right = False, True |
|||
class Color: white, black = '.', '#' |
|||
M = [[Color.white] * width for _ in range(height)] |
|||
class Dir(IntEnum): |
|||
x = width // 2 |
|||
"""Possible directions.""" |
|||
y = height // 2 |
|||
dir = Dir.up |
|||
UP = 0 |
|||
RIGHT = 1 |
|||
while i < nsteps and 0 <= x < width and 0 <= y < height: |
|||
DOWN = 2 |
|||
turn = Turn.left if M[y][x] == Color.black else Turn.right |
|||
LEFT = 3 |
|||
M[y][x] = Color.white if M[y][x] == Color.black else Color.black |
|||
dir = (4 + dir + (1 if turn else -1)) % 4 |
|||
dir = [Dir.up, Dir.right, Dir.down, Dir.left][dir] |
|||
if dir == Dir.up: y -= 1 |
|||
elif dir == Dir.right: x -= 1 |
|||
elif dir == Dir.down: y += 1 |
|||
elif dir == Dir.left: x += 1 |
|||
else: assert False |
|||
i += 1 |
|||
class Color(Enum): |
|||
print ("\n".join("".join(row) for row in M))</lang> |
|||
"""Possible colors.""" |
|||
The output is the same as the basic D version. |
|||
WHITE = " " |
|||
BLACK = "#" |
|||
def invert_color(grid, x, y): |
|||
"""Invert the color of grid at x, y coordinate.""" |
|||
if grid[y][x] == Color.BLACK: |
|||
grid[y][x] = Color.WHITE |
|||
else: |
|||
grid[y][x] = Color.BLACK |
|||
def next_direction(grid, x, y, direction): |
|||
"""Compute next direction according to current position and direction.""" |
|||
if grid[y][x] == Color.BLACK: |
|||
turn_right = False |
|||
else: |
|||
turn_right = True |
|||
direction_index = direction.value |
|||
if turn_right: |
|||
direction_index = (direction_index + 1) % 4 |
|||
else: |
|||
direction_index = (direction_index - 1) % 4 |
|||
directions = [Dir.UP, Dir.RIGHT, Dir.DOWN, Dir.LEFT] |
|||
direction = directions[direction_index] |
|||
return direction |
|||
def next_position(x, y, direction): |
|||
"""Compute next position according to direction.""" |
|||
if direction == Dir.UP: |
|||
y -= 1 |
|||
elif direction == Dir.RIGHT: |
|||
x -= 1 |
|||
elif direction == Dir.DOWN: |
|||
y += 1 |
|||
elif direction == Dir.LEFT: |
|||
x += 1 |
|||
return x, y |
|||
def print_grid(grid): |
|||
"""Display grid.""" |
|||
print(80 * "#") |
|||
print("\n".join("".join(v.value for v in row) for row in grid)) |
|||
def ant(width, height, max_nb_steps): |
|||
"""Langton's ant.""" |
|||
grid = [[Color.WHITE] * width for _ in range(height)] |
|||
x = width // 2 |
|||
y = height // 2 |
|||
direction = Dir.UP |
|||
i = 0 |
|||
while i < max_nb_steps and 0 <= x < width and 0 <= y < height: |
|||
invert_color(grid, x, y) |
|||
direction = next_direction(grid, x, y, direction) |
|||
x, y = next_position(x, y, direction) |
|||
print_grid(grid) |
|||
i += 1 |
|||
if __name__ == "__main__": |
|||
ant(width=75, height=52, max_nb_steps=12000) |
|||
</lang> |
|||
The output is similar to the basic D version. |
|||
=={{header|R}}== |
=={{header|R}}== |