-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The vimscript (and Haskell) presented at the Boston Vim meetup, showi…
…ng Conway's Game of Life.
- Loading branch information
0 parents
commit 00eadae
Showing
4 changed files
with
159 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,59 @@ | |||
import Data.Maybe | |||
|
|||
data Cell = Alive | Dead deriving (Eq, Show) | |||
|
|||
tick board = rowsTick 0 board board | |||
|
|||
rowsTick _ [] _ = [] | |||
rowsTick rowNumber (row:rows) board = | |||
(rowTick row board rowNumber 0):(rowsTick (rowNumber+1) rows board) | |||
|
|||
rowTick [] _ _ _ = [] | |||
rowTick (cell:cells) board rowNumber columnNumber = | |||
tickedCell:(rowTick cells board rowNumber (columnNumber+1)) | |||
where tickedCell = cellTick cell board rowNumber columnNumber | |||
|
|||
cellTick cell board rowNumber columnNumber = | |||
transition cell $ liveNeighborsCount board rowNumber columnNumber | |||
|
|||
liveNeighborsCount board rowNumber columnNumber = | |||
length $ filter (Alive==) neighboringCells | |||
where neighboringCells = [ | |||
board `at` (rowNumber-1,columnNumber-1), | |||
board `at` (rowNumber-1,columnNumber), | |||
board `at` (rowNumber-1,columnNumber+1), | |||
board `at` (rowNumber, columnNumber-1), | |||
board `at` (rowNumber, columnNumber+1), | |||
board `at` (rowNumber+1, columnNumber-1), | |||
board `at` (rowNumber+1, columnNumber), | |||
board `at` (rowNumber+1, columnNumber+1)] | |||
|
|||
transition Alive 2 = Alive | |||
transition Alive 3 = Alive | |||
transition Dead 3 = Alive | |||
transition _ _ = Dead | |||
|
|||
at board (rowNumber, columnNumber) | |||
| rowNumber < 0 || columnNumber < 0 = Dead | |||
| otherwise = maybe Dead id foundCell | |||
where | |||
foundCell = | |||
(listToMaybe $ drop rowNumber board) >>= | |||
listToMaybe . drop columnNumber | |||
|
|||
|
|||
inputBoard = [ | |||
[Alive,Alive,Dead ,Dead ] | |||
,[Dead ,Alive,Dead ,Dead ] | |||
,[Alive,Alive,Dead ,Alive] | |||
,[Dead ,Dead ,Dead ,Dead ] | |||
] | |||
|
|||
outputBoard = [ | |||
[Alive,Alive,Dead ,Dead ] | |||
,[Dead ,Dead ,Dead ,Dead ] | |||
,[Alive,Alive,Alive,Dead ] | |||
,[Dead ,Dead ,Dead ,Dead ] | |||
] | |||
|
|||
main = putStrLn $ show $ tick inputBoard == outputBoard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,84 @@ | |||
function! Transition(cell, numberOfLiveNeighbors) | |||
if a:cell == "*" && (a:numberOfLiveNeighbors == 2 || a:numberOfLiveNeighbors == 3) | |||
return "*" | |||
elseif a:cell == "o" && a:numberOfLiveNeighbors == 3 | |||
return "*" | |||
else | |||
return "o" | |||
endif | |||
endfunction | |||
|
|||
function! At(matrix, x, y) | |||
if a:x < 0 || a:y < 0 | |||
return "o" | |||
else | |||
return get(get(a:matrix, a:x, []), a:y, "o") | |||
endif | |||
endfunction | |||
|
|||
function! NeighboringCells(board, x, y) | |||
return [ At(a:board, a:y-1, a:x-1), At(a:board, a:y-1, a:x), At(a:board, a:y-1, a:x+1), At(a:board, a:y, a:x-1), At(a:board, a:y, a:x+1), At(a:board, a:y+1, a:x-1), At(a:board, a:y+1, a:x), At(a:board, a:y+1, a:x+1) ] | |||
endfunction | |||
|
|||
function! LiveNeighborsCount(board, x, y) | |||
let l:neighbors = NeighboringCells(a:board, a:x, a:y) | |||
return count(l:neighbors, "*") | |||
endfunction | |||
|
|||
function! CellTick(cell, board, x, y) | |||
let l:neighborsCount = LiveNeighborsCount(a:board, a:x, a:y) | |||
return Transition(a:cell, l:neighborsCount) | |||
endfunction | |||
|
|||
function! RowTick(row, board, x, y) | |||
if a:row == [] | |||
return [] | |||
else | |||
let l:cell = a:row[0] | |||
let l:cells = a:row[1:] | |||
let l:transitionedCell = CellTick(l:cell, a:board, a:x, a:y) | |||
return [l:transitionedCell] + RowTick(l:cells, a:board, a:x+1, a:y) | |||
endif | |||
endfunction | |||
|
|||
function! RowsTick(y, rs, board) | |||
if a:rs == [] | |||
return [] | |||
else | |||
let l:row = a:rs[0] | |||
let l:rows = a:rs[1:] | |||
let l:transitionedRow = RowTick(l:row, a:board, 0, a:y) | |||
return [l:transitionedRow] + RowsTick(a:y+1, l:rows, a:board) | |||
endif | |||
endfunction | |||
|
|||
function! Tick(board) | |||
return RowsTick(0, a:board, a:board) | |||
endfunction | |||
|
|||
function! UITick() | |||
let l:board = [] | |||
for unparsedRow in getbufline(bufnr('%'), 1, '$') | |||
let l:parsedRow = split(unparsedRow, ' ') | |||
let l:board = add(l:board, l:parsedRow) | |||
endfor | |||
|
|||
let l:nextBoard = Tick(l:board) | |||
|
|||
let l:nextBuffer = [] | |||
for nextRow in l:nextBoard | |||
let l:nextLine = join(nextRow, ' ') | |||
let l:nextBuffer = add(l:nextBuffer, l:nextLine) | |||
endfor | |||
|
|||
normal! ggdG | |||
exe "normal! i".join(l:nextBuffer, "\<cr>")."\<esc>" | |||
endfunction | |||
|
|||
function! RunGameOfLife() | |||
while 1 | |||
call UITick() | |||
redraw | |||
sleep 1 | |||
endwhile | |||
endfunction |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,9 @@ | |||
source test_unit.vim | |||
source game_of_life.vim | |||
|
|||
call AssertEqual(Transition("*", 2), "*" ) | |||
call AssertEqual(Transition("*", 3), "*" ) | |||
call AssertEqual(Transition("o", 3), "*" ) | |||
call AssertEqual(Transition("*", 4), "o" ) | |||
|
|||
call AssertEqual(At([["a","b"],["c","d"]], 4, 5), "o") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,7 @@ | |||
function! AssertEqual(actual, expected) | |||
if a:actual == a:expected | |||
echon "." | |||
else | |||
echom "Expected " . a:expected . " but got " . a:actual | |||
end | |||
endfunction |