I have interpreted that AAAupdate
is a temporary variable used as a workspace and the size of AAAupdate
is determined from the size of AAA
.
In this case, it is terribly inconvenient to fix the sizes of AAA
and AAAupdate
by hardcoding them in the module.
To avoid this, you can prepare functions to set the initial values of AAA
and AAAupdate
in the module, and use them outside the module.
The basic pattern is as follows:
module Foo
struct Board{...} ...including state and tmp... end
function initialboard(...) ...; Board(...) end
function update!(board::Board, niters) ...update state with tmp... end
end
# Construct initial board as a global variable
board = Foo.initialboard(...)
# Update the board by the `Foo.update!` method
Foo.update!(board, 1000)
Working example: Game of Life
Jupyter notebook: https://github.com/genkuroki/public/blob/main/0014/Game%20of%20Life.ipynb
The size of the internal temporary workspace tmp
is automatically determined by the size of the given state
of board
.
module LifeGame (53 lines)
module LifeGame
using Plots
using ProgressMeter
struct Board{T}
state::T
tmp::T
end
Board(state) = Board(state, similar(state))
function fivexfive(n=200)
state = zeros(Int8, n, n)
m = n Γ· 2
state[m-2:m+2, m-2:m+2] .= [1 1 1 0 1; 1 0 0 0 0; 0 0 0 1 1; 0 1 1 0 1; 1 0 1 0 1]
Board(state)
end
randboard(n=200) = Board(rand(Int8[0, 1], n, n))
P(i, m) = ifelse(i == m, 1, i+1)
Q(i, m) = ifelse(i == 1, m, i-1)
function _update!(v, u)
m, n = size(u)
@inbounds for j in 1:n, i in 1:m
iβ, iβ, jβ, jβ = P(i, m), Q(i, m), P(j, n), Q(j, n)
N = u[iβ,jβ] + u[i,jβ] + u[iβ,jβ] + u[iβ,j] + u[iβ,j] + u[iβ,jβ] + u[i,jβ] + u[iβ,jβ]
v[i,j] = N == 3 ? 1 : (N == 2 && !iszero(u[i,j])) ? 1 : 0
end
end
function update!(board::Board, niters=1)
state, tmp = board.state, board.tmp
for _ in 1:nitersΓ·2
_update!(tmp, state)
_update!(state, tmp)
end
if isodd(niters)
_update!(tmp, state)
state .= tmp
end
end
function gif!(board::Board, niters, nskips=1; gifname="life.gif", fps=20, size=(240, 240))
prog = Progress(niters, 0)
anim = @animate for t in 1:niters
heatmap(board.state; size, colorbar=false, ticks=false, axis=false, frame=false)
update!(board, nskips)
next!(prog)
end
gif(anim, gifname; fps)
end
end
boardrandom = LifeGame.randboard()
LifeGame.gif!(boardrandom, 500; gifname="liferandom.gif")
Progress: 100%|βββββββββββββββββββββββββββββββββββββββββ| Time: 0:00:26
board5x5 = LifeGame.fivexfive()
LifeGame.gif!(board5x5, 2000; gifname="life5x5.gif", fps=60)
Progress: 100%|βββββββββββββββββββββββββββββββββββββββββ| Time: 0:01:05