2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,17 +1,27 @@
[[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.
::#   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.
<br>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.
;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.
;See also
* [[Conway's Game of Life]]
The problem has received some analysis; for more details, please take a look at the Wikipedia article &nbsp; (a link is below)..
;See also:
* &nbsp; Wikipedia: &nbsp; [https://en.wikipedia.org/wiki/Langton%27s_ant Langton's ant].
;Related task:
* &nbsp; Rosetta Code: &nbsp; [[Conway's Game of Life]].
<br><br>

View file

@ -1,27 +1,25 @@
defmodule Langtons do
def ant(sizex, sizey) do
{px, py} = {div(sizex,2), div(sizey,2)} # start position
move(HashSet.new, sizex, sizey, px, py, {1,0}, 0)
move(MapSet.new, sizex, sizey, px, py, {1,0}, 0)
end
defp move(plane, sx, sy, px, py, _, step) when px<0 or sx<px or py<0 or sy<py, do:
print(plane, sx, sy, px, py, step)
defp move(plane, sx, sy, px, py, dir, step) do
{plane2, {dx,dy}} = if Set.member?(plane, {px,py}),
do: {Set.delete(plane, {px,py}), turn(dir, :right)},
else: {Set.put(plane, {px,py}), turn(dir, :left)}
{plane2, {dx,dy}} = if {px,py} in plane,
do: {MapSet.delete(plane, {px,py}), turn_right(dir)},
else: {MapSet.put(plane, {px,py}), turn_left(dir)}
move(plane2, sx, sy, px+dx, py+dy, {dx,dy}, step+1)
end
defp turn({dx, dy}, :right), do: {dy, -dx}
defp turn({dx, dy}, _), do: {-dy, dx}
defp turn_right({dx, dy}), do: {dy, -dx}
defp turn_left({dx, dy}), do: {-dy, dx}
defp print(plane, sx, sy, px, py, step) do
IO.puts "out of bounds after #{step} moves: (#{px}, #{py})"
Enum.each(0..sy, fn j ->
Enum.map(0..sx, fn i ->
if Set.member?(plane, {i,j}), do: "#", else: "."
end) |> Enum.join |> IO.puts
IO.puts Enum.map(0..sx, fn i -> if {i,j} in plane, do: "#", else: "." end)
end)
end
end

View file

@ -0,0 +1 @@
import Data.Set (member,insert,delete,Set)

View file

@ -0,0 +1,5 @@
-- functional sequence
(>>>) = flip (.)
-- functional choice
p ?>> (f, g) = \x -> if p x then f x else g x

View file

@ -0,0 +1,5 @@
data State = State { antPosition :: Point
, antDirection :: Point
, getCells :: Set Point }
type Point = (Float, Float)

View file

@ -0,0 +1,10 @@
step :: State -> State
step = isBlack ?>> (setWhite >>> turnRight,
setBlack >>> turnLeft) >>> move
where
isBlack (State p _ m) = member p m
setBlack (State p d m) = State p d (insert p m)
setWhite (State p d m) = State p d (delete p m)
turnRight (State p (x,y) m) = State p (y,-x) m
turnLeft (State p (x,y) m) = State p (-y,x) m
move (State (x,y) (dx,dy) m) = State (x+dx, y+dy) (dx, dy) m

View file

@ -0,0 +1,5 @@
task :: State -> State
task = iterate step
>>> dropWhile ((< 50) . distance . antPosition)
>>> getCells . head
where distance (x,y) = max (abs x) (abs y)

View file

@ -0,0 +1,8 @@
import Graphics.Gloss
main = display w white (draw (task initial))
where
w = InWindow "Langton's Ant" (400,400) (0,0)
initial = State (0,0) (1,0) mempty
draw = foldMap drawCell
drawCell (x,y) = Translate (10*x) (10*y) $ rectangleSolid 10 10

View file

@ -0,0 +1,6 @@
main = simulate w white 500 initial draw (\_ _ -> step)
where
w = InWindow "Langton's Ant" (400,400) (0,0)
initial = State (0,0) (1,0) mempty
draw (State p _ s) = pictures [foldMap drawCell s, color red $ drawCell p]
drawCell (x,y) = Translate (10*x) (10*y) $ rectangleSolid 10 10

View file

@ -1,81 +0,0 @@
data Color = Black | White
deriving (Read, Show, Enum, Eq, Ord)
putCell c = putStr (case c of Black -> "#"
White -> ".")
toggle :: Color -> Color
toggle color = toEnum $ 1 - fromEnum color
data Dir = East | North | West | South
deriving (Read, Show, Enum, Eq, Ord)
turnLeft South = East
turnLeft dir = succ dir
turnRight East = South
turnRight dir = pred dir
data Pos = Pos { x :: Int, y :: Int }
deriving (Read)
instance Show Pos where
show p@(Pos x y) = "(" ++ (show x) ++ "," ++ (show y) ++ ")"
-- Return the new position after moving one unit in the given direction
moveOne pos@(Pos x y) dir =
case dir of
East -> Pos (x+1) y
South -> Pos x (y+1)
West -> Pos (x-1) y
North -> Pos x (y-1)
-- Grid is just a list of lists
type Grid = [[Color]]
colorAt g p@(Pos x y) = (g !! y) !! x
replaceNth n newVal (x:xs)
| n == 0 = newVal:xs
| otherwise = x:replaceNth (n-1) newVal xs
toggleCell g p@(Pos x y) =
let newVal = toggle $ colorAt g p
in replaceNth y (replaceNth x newVal (g !! y)) g
printRow r = do { mapM_ putCell r ; putStrLn "" }
printGrid g = mapM_ printRow g
data State = State { move :: Int, pos :: Pos, dir :: Dir, grid :: Grid }
printState s = do {
putStrLn $ show s;
printGrid $ grid s
}
instance Show State where
show s@(State m p@(Pos x y) d g) =
"Move: " ++ (show m) ++ " Pos: " ++ (show p) ++ " Dir: " ++ (show d)
nextState s@(State m p@(Pos x y) d g) =
let color = colorAt g p
new_d = case color of White -> (turnRight d)
Black -> (turnLeft d)
new_m = m + 1
new_p = moveOne p new_d
new_g = toggleCell g p
in State new_m new_p new_d new_g
inRange size s@(State m p@(Pos x y) d g) =
x >= 0 && x < size && y >= 0 && y < size
initialState size = (State 0 (Pos (size`div`2) (size`div`2)) East [ [ White | x <- [1..size] ] | y <- [1..size] ])
--- main
size = 100
allStates = initialState size : [nextState s | s <- allStates]
main = printState $ last $ takeWhile (inRange size) allStates

View file

@ -0,0 +1,27 @@
$Size = 100
$G = @()
1..$Size | ForEach { $G += ,( @( 1 ) * $Size ) }
$x = $y = $Size / 2
# Direction of next move
$Dx = 1
$Dy = 0
# While we are still on the grid...
While ( $x -ge 0 -and $y -ge 0 -and $x -lt $Size -and $y -lt $Size )
{
# Change direction
$Dx, $Dy = ( $Dy * $G[$x][$y] ), -( $Dx * $G[$x][$y] )
# Change state of current square
$G[$x][$y] = -$G[$x][$y]
# Move forward
$x += $Dx
$y += $Dy
}
# Convert to strings for output
ForEach ( $Row in $G ) { ( $Row | ForEach { ( ' ', '', '#')[$_+1] } ) -join '' }

View file

@ -1,37 +1,36 @@
/*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)*/
if dir=='' then dir=random(1,4) /*ant is facing random direction,*/
$.=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; @.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
/* [↓] show 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 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; _=_ || @.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.*/
/*REXX program implements Langton's ant walk and displays the ant's path (finite field).*/
parse arg dir char seed . /*obtain optional arguments from the CL*/
if datatype(seed, 'W') then call random ,,seed /*Integer? Then use it as a RANDOM SEED*/
if dir=='' | dir=="," then dir=random(1, 4) /*ant is facing a random direction, */
if char=='' | char=="," then char= '#' /*binary colors: 0≡white, 1≡black. */
parse value scrSize() with sd sw . /*obtain the terminal's depth and width*/
sd=sd-6; sw=sw-1 /*adjust for terminal's useable area. */
x=1000000 ; y=1000000 /*start ant's walk in middle of nowhere*/
$.=1; $.0=4 ; $.2=2; $.3=3; $.4=4 /* 1≡north 2≡east 3≡south 4≡west.*/
@.=0 ; minx=x; miny=y; maxx=x; maxy=y /*define stem array, default: all white*/
/* [↓] ant walks hither and thither. */
do steps=1 until (maxx-miny>sw) | (maxy-miny>sd) /*'til the ant is out─of─bounds.*/
black=@.x.y; @.x.y= \ @.x.y /*invert (flip) ant's cell color code.*/
if black then dir=dir-1 /*if cell color was black, turn left.*/
else dir=dir+1 /* " " " " white, turn right.*/
dir=$.dir /*possibly adjust for under/over. */
select /*ant walks the direction it's facing. */
when dir==1 then y= y + 1 /*is ant 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*/
minx=min(minx, x); maxx=max(maxx, x) /*find the minimum and maximum of X. */
miny=min(miny, y); maxy=max(maxy, y) /* " " " " " " Y. */
end /*steps*/
/*finished walking, it's out-of-bounds.*/
say center(" Langton's ant walked " steps ' steps. ', 79, "")
@.1000000.1000000='' /*show the ant's initial starting point*/
@.x.y= '' /*show where the ant went out-of-bounds*/
/* [↓] show Langton's ant's trail. */
do y=maxy to miny by -1; _= /*display a single row of cells. */
do x=minx to maxx; _=_ || @.x.y /*build a cell row for the display. */
end /*x*/
_=strip( translate(_, char, 10), 'T') /*color the cells: black or white. */
if _\=='' then say _ /*display line (strip trailing blanks).*/
end /*y*/ /*stick a fork in it, we're all done. */

View file

@ -0,0 +1,63 @@
" return character under cursor
function! CurrChar()
return matchstr(getline('.'), '\%' . col('.') . 'c.')
endfunction
" draw all-white grid (arguments are characters to use for white and black)
function! LangtonClear(white, black)
let l:bufname = 'langtons.ant'
if bufexists(l:bufname)
let l:winnum = bufwinnr(l:bufname)
if l:winnum == -1
execute 'sbuffer ' . bufnr(l:bufname)
else
execute l:winnum . 'wincmd w'
endif
else
execute 'new ' . l:bufname
end
execute '1,$ delete _'
call append(0, repeat(a:white,100))
execute 'normal! 1Gyy99p'
goto 5100
let b:directions = [ 'k', 'l', 'j', 'h' ]
let b:direction = 0
let b:white = a:white
let b:black = a:black
endfunction
" move the ant one step
function! LangtonStep()
let l:ch = CurrChar()
if l:ch == b:white
let l:ch = b:black
let b:direction = (b:direction + 1) % 4
elseif l:ch == b:black
let l:ch = b:white
let b:direction = (b:direction + 3) % 4
endif
execute 'normal! r'.l:ch.b:directions[b:direction]
endfunction
" run until we hit the edge
" optional arguments specify white and black characters;
" default . and @, respectively.
function! RunLangton(...)
let l:white='.'
let l:black='@'
if a:0 > 0
let l:white=a:1
if a:0 > 1
let l:black=a:2
endif
endif
call LangtonClear(l:white, l:black)
while 1
let l:before = getpos('.')
call LangtonStep()
let l:after = getpos('.')
if l:before == l:after
break
endif
endwhile
endfunction