Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -1,10 +1,17 @@
[[wp:Langton's ant|Langton's ant]] models an ant sitting on a plane of cells, all of which are white initially, facing in one of four directions. Each cell can either be black or white. The ant moves according to the color of the cell it is currently sitting in, with the following rules:
[[wp:Langton's ant|Langton's ant]] is a cellular automaton that models an ant sitting on a plane of cells, all of which are white initially, facing in one of four directions.
Each cell can either be black or white.
The ant moves according to the color of the cell it is currently sitting in, with the following rules:
# If the cell is black, it changes to white and the ant turns left;
# If the cell is white, it changes to black and the ant turns right;
# The Ant then moves forward to the next cell, and repeat from step 1.
This rather simple ruleset leads to an initially chaotic movement pattern, and after about 10000 steps, a cycle appears where the ant moves steadily away from the starting location in a diagonal corridor about 10 pixels wide. Conceptually the ant can then travel to infinitely far away.
This rather simple ruleset leads to an initially chaotic movement pattern, and after about 10000 steps, a cycle appears where the ant moves steadily away from the starting location in a diagonal corridor about 10 pixels wide.
Conceptually the ant can then travel infinitely far away.
For this task, start the ant near the center of a 100 by 100 field of cells, which is about big enough to contain the initial chaotic part of the movement. Follow the movement rules for the ant, terminate when it moves out of the region, and show the cell colors it leaves behind.
For this task, start the ant near the center of a 100 by 100 field of cells, which is about big enough to contain the initial chaotic part of the movement.
Follow the movement rules for the ant, terminate when it moves out of the region, and show the cell colors it leaves behind.
The problem has received some analysis, for more details, please take a look at the Wikipedia article.
The problem has received some analysis; for more details, please take a look at the Wikipedia article.
;See also
* [[Conway's Game of Life]]

View file

@ -0,0 +1,93 @@
# usage: awk -v debug=0 -f langton.awk
# Simulates the cellular automaton "Langton's ant",
# see http://en.wikipedia.org/wiki/Langton%27s_ant
function turnRight() {
dir++
if( dir>4 ) { dir=1 }
}
function turnLeft() {
dir--
if( dir<1 ) { dir=4 }
}
function move() {
if (dir==1) { y--; z="^" }
if (dir==3) { y++; z="v" }
if (dir==2) { x++; z=">" }
if (dir==4) { x--; z="<" }
}
function ant() {
if( debug ) AntStat() ##
if( grid[x,y]==0 ) { turnLeft() } else { turnRight() }
if( grid[x,y]==0 ) { color=1 } else { color=0 }
if( debug ) print( "# action", color, dir, z ) ##
grid[x,y] = color
move()
}
###
function AntStat() {
printf( "Move# %d : Ant @ x=%d y=%d dir=%d %s color=%d\n",
moveNr, x,y, dir,z, grid[x,y] )
}
function dumpGrid() {
AntStat()
printf( "Grid:" )
for(xx=1; xx<=limit/10; xx++) {
printf( "....+....%s", xx )
}
printf "\n"
cSum=0
for(yy=1; yy <= limit; yy++) {
printf( "%4d:",yy )
for(xx=1; xx <= limit; xx++) {
c = grid[xx,yy]
if( c ) cSum++
c1++
c2+=grid[xx,yy]
if( (xx==x)&&(yy==y) ) { c=z } # Ant
printf( c )
}
printf( "\n" )
}
printf( "Cells: %d 'black' cells: %d Moves: %d\n\n", limit*limit, cSum, moveNr )
}
BEGIN {
print( "Langton's ant\n" )
limit = 72
for(x=1; x <= limit; x++) {
for(y=1; y <= limit; y++) {
grid[x,y] = 0
}
}
moveNr = 0
x = 36
y = 28
dir = 1 # 1=up/north 2=right/east 3=down/south 4=left/west
z = "!"
while( moveNr < 11200 ) {
moveNr++
ant()
if(x<0 || x>limit) break
if(y<0 || y>limit) break
# Snapshots:
if (moveNr==163 || moveNr==1297 || moveNr==10095 ) dumpGrid()
if (y<=5 ) break
}
dumpGrid()
}
END { print("END.") }

View file

@ -1,20 +1,56 @@
SetBatchLines -1
n := 0, x := 50, y := 50, d := 1 ; starting positions and orientation
While x > 0 and x < 100 and y > 0 and y < 100 ; In this loop the ant moves
d := d + !!(a%x%_%y%) - !(a%x%_%y%)
,d := d=5 ? 1 : d=0 ? 4 : d
,a%x%_%y% := !a%x%_%y%
,x := x + (d=3) - (d=1)
,y := y + (d=4) - (d=2)
Loop 99 ; in this loop the ant's movements are compiled into a string
{
y := A_Index
Loop 99
x := A_Index
,o .= a%x%_%y% ? "#" : "."
o .= "`r`n"
#NoEnv
SetBatchLines, -1
; Directions
Directions := {0: "North", 1: "East", 2: "South", 3: "West"}
; Initialize the plane (set all cells to white)
White := 0xFFFFFF
Plane := []
PW := PH := 100
loop, % PH {
I := A_Index
loop, % PW
Plane[I, A_Index] := White
}
clipboard := o ; set the string to the clipboard
; Let it run
DI := D := 0 ; initial direction
X := Y := 50 ; initial coordinates
while (X > 0) && (X <= PW) && (Y > 0) && (Y <= PH) {
D := (D + ((Plane[X, Y] ^= White) ? 1 : 3)) & 3
if (D & 1)
X += -(D = 3) + (D = 1)
else
Y += -(D = 0) + (D = 2)
}
; Show the result
HBM := CreateDIB(Plane, PW, PH, 400, 400, 0)
Gui, Margin, 0, 0
Gui, Add, Text, x0 y0 w20 h440 Center 0x200, W
Gui, Add, Text, x20 y0 w400 h20 Center 0x200, N
Gui, Add, Picture, x20 y20 w400 h400 0x4E hwndHPIC ; SS_REALSIZECONTROL = 0x40 | SS_BITMAP = 0xE
DllCall("User32.dll\SendMessage", "Ptr", HPIC, "UInt", 0x172, "Ptr", 0, "Ptr", HBM) ; STM_SETIMAGE = 0x172
Gui, Add, Text, xp+5 yp h20 0x200 BackgroundTrans, % "Initial direction: " . Directions[DI]
Gui, Add, Text, x20 y420 w400 h20 Center 0x200, S
Gui, Add, Text, x420 y0 w20 h440 Center 0x200, E
Gui, Show, , Langton's ant (%PW%x%PH%)
Return
GuiClose:
ExitApp
CreateDIB(PixelArray, PAW, PAH, BMW := 0, BMH := 0, Gradient := 1) { ; SKAN, 01-Apr-2014 / array version by just me
SLL := (PAW * 3) + (PAW & 1)
VarSetCapacity(BMBITS, SLL * PAH, 0)
P := &BMBITS
loop, % PAH {
R := A_Index
loop, % PAW
P := Numput(PixelArray[R, A_Index], P + 0, "UInt") - 1
P += (PAW & 1)
}
HBM := DllCall("Gdi32.dll\CreateBitmap", "Int", PAW, "Int", PAH, "UInt", 1, "UInt", 24, "Ptr", 0, "UPtr")
HBM := DllCall("User32.dll\CopyImage", "Ptr", HBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
DllCall( "Gdi32.dll\SetBitmapBits", "Ptr", HBM, "UInt", SLL * PAH, "Ptr", &BMBITS)
if (!Gradient)
HBM := DllCall("User32.dll\CopyImage", "Ptr", HBM, "UInt", 0, "Int", 0, "Int", 0, "Int", 8, "UPtr")
return DllCall("User32.dll\CopyImage", "Ptr", HBM, "UInt", 0, "Int", BMW, "Int", BMH, "UInt", 0x200C, "UPtr")
} ; http://ahkscript.org/boards/viewtopic.php?f=6&t=3203

View file

@ -1,25 +1,26 @@
import std.stdio, std.traits;
void main() @safe {
import std.stdio, std.traits;
void main() {
enum width = 75, height = 52;
enum maxSteps = 12_000;
enum Direction { up, right, down, left }
enum Color : char { white = '.', black = '#' }
uint x = width / 2, y = height / 2;
auto M = new Color[][](height, width);
auto dir = Direction.up;
enum width = 75, height = 52;
enum maxSteps = 12_000;
enum Direction { up, right, down, left }
enum Color : char { white = '.', black = '#' }
uint x = width / 2, y = height / 2;
Color[width][height] M;
auto dir = Direction.up;
for (int i = 0; i < maxSteps && x < width && y < height; i++) {
immutable turn = M[y][x] == Color.black;
dir = [EnumMembers!Direction][(dir + (turn ? 1 : -1)) & 3];
M[y][x] = (M[y][x] == Color.black) ? Color.white : Color.black;
final switch(dir) with (Direction) {
case up: y--; break;
case right: x--; break;
case down: y++; break;
case left: x++; break;
}
}
with (Color)
for (int i = 0; i < maxSteps && x < width && y < height; i++) {
immutable turn = M[y][x] == black;
dir = [EnumMembers!Direction][(dir + (turn ? 1 : -1)) & 3];
M[y][x] = (M[y][x] == black) ? white : black;
final switch(dir) with (Direction) {
case up: y--; break;
case right: x--; break;
case down: y++; break;
case left: x++; break;
}
}
writefln("%-(%s\n%)", cast(char[][])M);
writefln("%(%-(%c%)\n%)", M);
}

View file

@ -0,0 +1,35 @@
program langtons_ant
implicit none
integer, parameter :: dp = selected_real_kind(15,300)
real(kind=dp), parameter :: pi = 3.1415926535897932_dp
integer, parameter :: grid_size = 100
integer, dimension(:,:), allocatable :: grid
integer, dimension(3) :: ant = (/ grid_size/2, grid_size/2, 0 /)
integer :: i
allocate(grid(1:grid_size, 1:grid_size))
grid = 1 !Grid initially white
do
grid(ant(1) , ant(2)) = -grid(ant(1) , ant(2)) ! Flip the color of the current square
ant(3) = modulo(ant(3) + grid(ant(1),ant(2)),4) ! Rotate the ant depending on the current square
ant(1) = ant(1) + nint( sin(ant(3) * pi / 2.0_dp) ) ! Move the ant in x
ant(2) = ant(2) + nint( cos(ant(3) * pi / 2.0_dp) ) ! Move the ant in y
!exit if the ant is outside the grid
if (((ant(1) < 1) .or. (ant(1) > grid_size)) .or. ((ant(2) < 1) .or. (ant(2) > grid_size))) exit
end do
!Print out the final grid
open(unit=21, file="ant.dat")
do i = 1, grid_size
write(21,*) int(grid(:,i) + 1 / 2.0_dp)
end do
close(21)
deallocate(grid)
end program langtons_ant

View file

@ -0,0 +1,51 @@
make "size 100
make "white 1
make "black 2
make "sum sum :white :black
make "chars [. #]
make "origin quotient :size 2
make "grid mdarray (list :size :size)
make "directions [ [1 0] [0 1] [-1 0] [0 -1] ]
repeat size [
local "y
make "y repcount
repeat size [
mdsetitem (list repcount :y) :grid :white
]
]
make "x quotient :size 2
make "y quotient :size 2
make "direction sum 1 random count :directions
while [(and (:x > 0) (:x <= :size) (:y > 0) (:y <= :size))] [
local "color
make "color mditem (list :x :y) :grid
local "delta
ifelse [equal? :color :white] [
make "delta 1
] [
make "delta -1
]
make "direction sum 1 (modulo (:direction + :delta - 1) count :directions)
make "dir (item :direction :directions)
mdsetitem (list :x :y) :grid (sum :sum minus :color)
make "x sum :x first :dir
make "y sum :y last :dir
]
repeat size [
local "y
local "blank
make "y repcount
make "blank "true
repeat size [if ( (mditem (list repcount :y) :grid) = :black ) [make "blank "false]]
if [not :blank] [
repeat size [
type item (mditem (list repcount :y) :grid) :chars
]
print []
]
]
bye

View file

@ -0,0 +1,107 @@
local socket = require 'socket' -- needed for socket.sleep
local curses = require 'curses' -- used for graphics
local naptime = 0.02 -- seconds
local world_x, world_y = 100, 100
local world = (function (x, y)
local wrl = {}
for i = 1, y do
wrl[i] = {}
for j = 1, x do
wrl[i][j] = 0
end
end
return wrl
end)(world_x, world_y)
-- directions: 0 up, clockwise
local ant = {
x = math.floor(world_x / 2),
y = math.floor(world_y / 2),
dir = 0,
step = function(self)
if self.dir == 0 then self.y = self.y - 1
elseif self.dir == 1 then self.x = self.x + 1
elseif self.dir == 2 then self.y = self.y + 1
else self.x = self.x - 1
end
end
}
world.step = function (self, ant)
if self[ant.y][ant.x] == 0 then -- white
-- change cell color
self[ant.y][ant.x] = 1
-- change dir
ant.dir = (ant.dir + 1) % 4
ant:step()
-- boundary conditions
if ant.x < 1 then ant.x = world_x
elseif ant.x > world_x then ant.x = 1
end
if ant.y < 1 then ant.y = world_y
elseif ant.y > world_y then ant.y = 1
end
else
-- change cell color
self[ant.y][ant.x] = 0
-- change dir
ant.dir = (ant.dir - 1) % 4
ant:step()
-- boundary conditions
if ant.x < 1 then ant.x = world_x
elseif ant.x > world_x then ant.x = 1
end
if ant.y < 1 then ant.y = world_y
elseif ant.y > world_y then ant.y = 1
end
end
end
world.draw = function (self, ant)
for i = 1, #self do
for j = 1, #self[i] do
if i == ant.y and j == ant.x then
win:attron(curses.color_pair(3))
win:mvaddch(i,j,"A")
--win:attroff(curses.color_pair(3))
elseif self[i][j] == 0 then
win:attron(curses.color_pair(1))
win:mvaddch(i,j," ")
--win:attroff(curses.color_pair(1))
elseif self[i][j] == 1 then
win:attron(curses.color_pair(2))
win:mvaddch(i,j," ")
--win:attroff(curses.color_pair(2))
else error("self[" .. i .. "][" .. j .. "] is " .. self[i][j] .. "!")
end
end
end
end
local it = 1
curses.initscr()
curses.start_color()
curses.echo(false)
curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_WHITE)
curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_BLACK)
curses.init_pair(3, curses.COLOR_RED, curses.COLOR_WHITE)
curses.init_pair(4, curses.COLOR_WHITE, curses.COLOR_BLACK)
win = curses.newwin(world_y + 1, world_x, 0, 0)
win:clear()
repeat
world:draw(ant)
win:move(world_y, 0)
win:clrtoeol()
win:attron(curses.color_pair(4))
win:addstr("Iteration: " .. it .. ", nap = " .. naptime*1000 .. "ms")
win:refresh()
world:step(ant)
it = it + 1
--local c = stdscr:getch()
--if c == '+' then naptime = naptime - (naptime / 10)
--elseif c == '-' then naptime = naptime + (naptime / 10)
--end
socket.sleep(naptime)
until false

View file

@ -5,7 +5,7 @@ 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 xrange(height)]
M = [[Color.white] * width for _ in range(height)]
x = width // 2
y = height // 2
@ -25,4 +25,4 @@ while i < nsteps and 0 <= x < width and 0 <= y < height:
else: assert False
i += 1
print "\n".join("".join(row) for row in M)
print ("\n".join("".join(row) for row in M))

View file

@ -1,41 +1,37 @@
/*REXX program implements Langton's ant and displays the path it walked.*/
parse arg dir . /*allow specification: ant facing*/
/*binary colors: 0=white, 1=black*/
/*REXX program implements Langton's ant walk and displays the ant's path*/
parse arg dir char . /*allow specification: ant facing*/
if char=='' then char='#' /*binary colors: 0≡white, 1≡black*/
@.=0 /*define stem array (all white).*/
lb=1 ; rb=100 /* left boundry, right boundry.*/
bb=1 ; tb=100 /*bottom " top " */
x=(rb-lb)%2 ; y=(tb-bb)%2 /*approximate center (walk start)*/
Lb=1 ; Rb=100 /* left boundry, right boundry.*/
Bb=1 ; Tb=100 /*bottom " top " */
x=(Rb-Lb)%2 ; y=(Tb-Bb)%2 /*approximate center (walk start)*/
if dir=='' then dir=random(1,4) /*ant is facing random direction,*/
/*1=north 2=east 3=south 4=west*/
$.=1; $.0=4; $.2=2; $.3=3; $.4=4 /*1≡north 2≡east 3≡south 4≡west*/
/*───────────────────────────────────────────ant walks hither & thither.*/
do steps=1 until x<lb | x>rb | y<bb | y>tb /*walk until out-of-bounds*/
black=@.x.y /*get color code of ant's cell. */
@.x.y=\@.x.y /*"flip" the color of the cell. */
if black then dir=dir-1 /*if cell was black, turn left. */
else dir=dir+1 /* " " " white, " right. */
if dir==0 then dir=4 /*ant should be facing "west". */
if dir==5 then dir=1 /* " " " " "north". */
select /*ant walks direction it's facing*/
when dir==1 then y=y+1 /*walking north? Then go "up". */
when dir==2 then x=x+1 /* " east? " " "right"*/
when dir==3 then y=y-1 /* " south? " " "down".*/
when dir==4 then x=x-1 /* " west? " " "left".*/
end /*select*/
end /*steps*/
do steps=1 until x<Lb | x>Rb | y<Bb | y>Tb /*walk until out─of─bounds*/
black=@.x.y; @.x.y= \ @.x.y /*ant's cell color code; flip it.*/
if black then dir=dir-1 /*if cell was black, turn left.*/
else dir=dir+1 /* " " " white, turn right.*/
dir=$.dir /*possibly adjust for under/over.*/
select /*ant walks direction it's facing*/
when dir==1 then y= y + 1 /*walking north? Then go "up". */
when dir==2 then x= x + 1 /* " east? " " "right"*/
when dir==3 then y= y - 1 /* " south? " " "down".*/
when dir==4 then x= x - 1 /* " west? " " "left".*/
end /*select*/
end /*steps*/
/*───────────────────────────────────────────the ant is finished walking*/
say center(" Langton's ant walked" steps 'steps. ',79,""); say
/*Display Langton's ant's trail. */
do minx =lb to rb /*find leftmost non-blank column.*/
do y=bb to tb /*search row by row for it. */
if @.minx.y then leave minx /*found one, now quit searching. */
end /*y*/
end /*minx*/ /*above code crops left of array.*/
say center(" Langton's ant walked" steps 'steps. ', 79, ""); say
/* [↓] show Langton's ant's trail*/
do minx =Lb to Rb /*find leftmost nonblank column.*/
do y=Bb to Tb /*search row by row for the min. */
if @.minx.y then leave minx /*found one, now quit searching. */
end /*y*/
end /*minx*/ /*above code crops left of array.*/
do y=tb to bb by -1; _='' /*display a plane (row) of cells.*/
do x=minx to rb /*process a "row" of cells. */
_=_ || @.x.y /*build a cell row for display. */
end /*x*/
_=translate(_,'#',10) /*color the cells: black | white.*/
if _\='' then say strip(_,'T') /*say line, strip trailing blanks*/
end /*y*/
/*stick a fork in it, we're done.*/
do y=Tb to Bb by -1; _= /*display a plane (row) of cells.*/
do x=minx to Rb; _=_ || @.x.y /*build a cell row for display. */
end /*x*/
_=strip(translate(_,char,10), 'T') /*color the cells: black | white.*/
if _\=='' then say _ /*say line, strip trailing blanks*/
end /*y*/ /*stick a fork in it, we're done.*/

View file

@ -0,0 +1,27 @@
class Ant
MOVE = [[1,0], [0,1], [-1,0], [0,-1]] # [0]:east, [1]:south, [2]:west, [3]:north
def initialize(size_x, size_y, pos_x=size_x/2, pos_y=size_y/2)
@plane = Array.new(size_y) {Array.new(size_x, true)} # true -> white, false -> black
@sx, @sy = size_x, size_y
@px, @py = pos_x, pos_y # start position
@direction = 0 # south
@moves = 0
move while (0 <= @px and @px < @sx) and (0 <= @py and @py < @sy)
end
def move
@moves += 1
@direction = (@plane[@py][@px] ? @direction+1 : @direction-1) % 4
@plane[@py][@px] = !@plane[@py][@px]
@px += MOVE[@direction][0]
@py += MOVE[@direction][1]
end
def to_s
["out of bounds after #{@moves} moves: (#@px, #@py)"] +
(0...@sy).map {|y| (0...@sx).map {|x| @plane[y][x] ? "." : "#"}.join}
end
end
puts Ant.new(100, 100).to_s

View file

@ -0,0 +1,76 @@
struct Ant {
x: uint,
y: uint,
dir: Direction
}
impl Ant {
fn move(&mut self, vec: &mut Vec<Vec<u8>>) {
let pointer = vec.get_mut(self.y).get_mut(self.x);
//change direction
match *pointer {
0 => self.dir = self.dir.right(),
1 => self.dir = self.dir.left(),
_ => fail!("Unexpected colour in grid")
}
//flip colour
//if it's 1 it's black
//if it's 0 it's white
*pointer ^= 1;
//move direction
match self.dir {
North => self.y -= 1,
South => self.y += 1,
East => self.x += 1,
West => self.x -= 1,
}
}
}
enum Direction {
North,
East,
South,
West
}
impl Direction {
fn right(self) -> Direction {
match self {
North => East,
East => South,
South => West,
West => North,
}
}
fn left(self) -> Direction {
//3 rights equal a left
self.right().right().right()
}
}
fn main(){
//create a 100x100 grid using vectors
let mut grid: Vec<Vec<u8>> = Vec::from_elem(100, Vec::from_elem(100, 0u8));
let mut ant = Ant {
x: 50, y: 50, dir: North
};
while ant.x < 100 && ant.y < 100 {
ant.move(&mut grid);
}
for each in grid.iter() {
//construct string
//using iterator methods to quickly convert the vector
//to a string
let string = each.iter()
.map(|&x| String::from_byte(x+32))
.fold(String::new(), |x, y| x+y)
.replace("!", "#");
println!("{}", string);
}
}

View file

@ -0,0 +1,30 @@
$ include "seed7_05.s7i";
const type: direction is new enum UP, RIGHT, DOWN, LEFT end enum;
const proc: main is func
local
const integer: width is 75;
const integer: height is 52;
var array array boolean: m is height times width times FALSE;
var direction: dir is UP;
var integer: x is width div 2;
var integer: y is height div 2;
begin
while x in {1 .. width} and y in {1 .. height} do
dir := direction conv ((ord(dir) + 2 * ord(m[y][x]) - 1) mod 4);
m[y][x] := not m[y][x];
case dir of
when {UP}: decr(y);
when {RIGHT}: decr(x);
when {DOWN}: incr(y);
when {LEFT}: incr(x);
end case;
end while;
for key x range m do
for y range 1 to width do
write(".#"[succ(ord(m[x][y]))]);
end for;
writeln;
end for;
end func;