Task: Langton's ant



C#: using System;

namespace LangtonAnt
{
    public struct Point
    {
        public int X;
        public int Y;

        public Point(int x, int y)
        {
            X = x;
            Y = y;
        }
    }

    enum Direction
    {
        North, East, West, South
    }

    public class Langton
    {
        public readonly bool [,] IsBlack;
        private Point _origin;
        private Point _antPosition = new Point(0, 0);
        public bool OutOfBounds { get; set;}

        
        private Direction _antDirection = Direction.East;

        private readonly Direction[] _leftTurn = new[] { Direction.West, Direction.North, Direction.South, Direction.East };
        private readonly Direction[] _rightTurn = new[] { Direction.East, Direction.South, Direction.North, Direction.West };
        private readonly int[] _xInc = new[] { 0, 1,-1, 0};
        private readonly int[] _yInc = new[] {-1, 0, 0, 1};

        public Langton(int width, int height, Point origin)
        {
            _origin = origin;
            IsBlack = new bool[width, height];
            OutOfBounds = false;
        }

        public Langton(int width, int height) : this(width, height, new Point(width / 2, height / 2)) {}

        private void MoveAnt()
        {
            _antPosition.X += _xInc[(int)_antDirection];
            _antPosition.Y += _yInc[(int)_antDirection];
        }

        public Point Step()
        {
            if (OutOfBounds)
            {
                throw new InvalidOperationException("Trying to step after ant is out of bounds");
            }
            Point ptCur = new Point(_antPosition.X + _origin.X, _antPosition.Y + _origin.Y);
            bool leftTurn = IsBlack[ptCur.X, ptCur.Y];
            int iDirection = (int) _antDirection;
            _antDirection = leftTurn ? _leftTurn[iDirection] : _rightTurn[iDirection];
            IsBlack[ptCur.X, ptCur.Y] = !IsBlack[ptCur.X, ptCur.Y];
            MoveAnt();
            ptCur = new Point(_antPosition.X + _origin.X, _antPosition.Y + _origin.Y);
            OutOfBounds = 
                ptCur.X < 0 ||
                ptCur.X >= IsBlack.GetUpperBound(0) ||
                ptCur.Y < 0 ||
                ptCur.Y >= IsBlack.GetUpperBound(1);
            return _antPosition;
        }
    }
    class Program
    {
        static void Main()
        {
            Langton ant = new Langton(100, 100);

            while (!ant.OutOfBounds) ant.Step();

            for (int iRow = 0; iRow < 100; iRow++)
            {
                for (int iCol = 0; iCol < 100; iCol++)
                {
                    Console.Write(ant.IsBlack[iCol, iRow] ? "#" : " ");
                }
                Console.WriteLine();
            }

            Console.ReadKey();
        }
    }
}









Ada: with Ada.Text_IO;

procedure Langtons_Ant is

   Size: constant Positive := 100; 

   subtype Step is Integer range -1 .. +1;

   procedure Right(N, W: in out Step) is
      Tmp: Step := W;
   begin
      W := - N;
      N := Tmp;
   end Right;

   procedure Left(N, W: in out Step) is
   begin
      for I in 1 .. 3 loop
         Right(N, W);
      end loop;
   end Left;

   Color_Character: array(Boolean) of Character :=
     (False => ' ', True => '#');

   Is_Black: array (1 .. Size, 1 .. Size) of Boolean :=
     (others => (others => False)); 

   Ant_X, Ant_Y: Natural := Size/2; 
   Ant_North: Step := 1; Ant_West: Step := 0; 

   Iteration: Positive := 1;

begin
   loop 
      if Is_Black(Ant_X, Ant_Y) then
         Left(Ant_North, Ant_West);
      else
         Right(Ant_North, Ant_West);
      end if;
      Is_Black(Ant_X, Ant_Y) := not Is_Black(Ant_X, Ant_Y);
      Ant_X := Ant_X - Ant_North; 
      Ant_Y := Ant_Y - Ant_West;  
      Iteration := Iteration + 1;
    end loop;

exception
   when Constraint_Error => 
      for X in 1 .. Size loop
         for Y in 1 .. Size loop
            Ada.Text_IO.Put(Color_Character(Is_Black(X, Y)));
         end loop;
         Ada.Text_IO.New_Line;
      end loop;
      Ada.Text_IO.Put_Line("# Iteration:" & Integer'Image(Iteration));
end Langtons_Ant;