2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -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 (a link is below)..
|
||||
|
||||
|
||||
;See also:
|
||||
* Wikipedia: [https://en.wikipedia.org/wiki/Langton%27s_ant Langton's ant].
|
||||
|
||||
|
||||
;Related task:
|
||||
* Rosetta Code: [[Conway's Game of Life]].
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
1
Task/Langtons-ant/Haskell/langtons-ant-1.hs
Normal file
1
Task/Langtons-ant/Haskell/langtons-ant-1.hs
Normal file
|
|
@ -0,0 +1 @@
|
|||
import Data.Set (member,insert,delete,Set)
|
||||
5
Task/Langtons-ant/Haskell/langtons-ant-2.hs
Normal file
5
Task/Langtons-ant/Haskell/langtons-ant-2.hs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-- functional sequence
|
||||
(>>>) = flip (.)
|
||||
|
||||
-- functional choice
|
||||
p ?>> (f, g) = \x -> if p x then f x else g x
|
||||
5
Task/Langtons-ant/Haskell/langtons-ant-3.hs
Normal file
5
Task/Langtons-ant/Haskell/langtons-ant-3.hs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
data State = State { antPosition :: Point
|
||||
, antDirection :: Point
|
||||
, getCells :: Set Point }
|
||||
|
||||
type Point = (Float, Float)
|
||||
10
Task/Langtons-ant/Haskell/langtons-ant-4.hs
Normal file
10
Task/Langtons-ant/Haskell/langtons-ant-4.hs
Normal 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
|
||||
5
Task/Langtons-ant/Haskell/langtons-ant-5.hs
Normal file
5
Task/Langtons-ant/Haskell/langtons-ant-5.hs
Normal 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)
|
||||
8
Task/Langtons-ant/Haskell/langtons-ant-6.hs
Normal file
8
Task/Langtons-ant/Haskell/langtons-ant-6.hs
Normal 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
|
||||
6
Task/Langtons-ant/Haskell/langtons-ant-7.hs
Normal file
6
Task/Langtons-ant/Haskell/langtons-ant-7.hs
Normal 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
|
||||
|
|
@ -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
|
||||
27
Task/Langtons-ant/PowerShell/langtons-ant.psh
Normal file
27
Task/Langtons-ant/PowerShell/langtons-ant.psh
Normal 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 '' }
|
||||
|
|
@ -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. */
|
||||
|
|
|
|||
63
Task/Langtons-ant/Vim-Script/langtons-ant.vim
Normal file
63
Task/Langtons-ant/Vim-Script/langtons-ant.vim
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue