注目セルとそのムーア近傍と合わせて 9 つのセルに含まれている、発火状態(レベル 5 ~ 8)にあるセルの数をカウントする。
フィールドの外は全部空き地(レベル 0)とする。
上 が lua に読み込んだ現世代行列、下が lua から返されたカウント数。
-- nspire 側で用意した行列を lua に読み込む。 local matSute = var.recall("mat") -- 発火レベルの範囲を定義する local fireRange = {lower = 5, upper = 8} -- できた行列を確認する。 function on.paint(gc) local temp = countFire(matSute, fireRange.lower, fireRange.upper) drawMat(temp, 0, 0, 15, 7, gc) end -- 注目セルとそのムーア近傍と合計 9 セルに含まれている発火セルの数を数える部分函数(行列, 下限, 上限) function countFire(mat, boundLo, boundHi) -- 返すための空行列を作る。 local matReturn = newMat(#mat, #mat[1]) -- 読み込んだ mat の外周を空き地(レベル 0)で埋める。 -- まず、読み込んだ mat よりも 2 行・2 列多い空行列を作る。 local matTemp = newMat(#mat + 2, #mat[1] + 2) -- 今作った、2 行・2 列多い空行列の 2 行目、2 列目から mat を上書きする。 for r = 2, #matTemp - 1 do for c = 2, #matTemp[1] - 1 do matTemp[r][c] = mat[r-1][c-1] end end for r = 2, #matTemp - 1 do for c = 2, #matTemp[1] - 1 do -- 注目セルとそのムーア近傍と合計 9 セルを抜き出してリスト化する。 local matSub = subMat(matTemp, r-1,c-1,r+1,c+1) matSub = mat2list(matSub) -- 抜き出したリストを走査して、範囲内の数字が見つかったら個数を数える。 local n = countIf(matSub, boundLo, true, boundHi, true) -- 返す行列に、カウントアップした数字を代入する。 matReturn[r-1][c-1] = n end end return matReturn end -- 空行列函数(行数, 列数) function newMat(rowDim, colDim) local mat = {} for r = 1, rowDim do mat[r] = {} for c = 1, colDim do mat[r][c] = 0 end end return mat end -- 行列表示函数、(穴なし行列, 原点座標, 1 辺の長さ, フォントサイズ, gc) function drawMat(mat, x0, y0, sideLen, fontSize, gc) for r = 1, table.maxn(mat) do for c = 1, table.maxn(mat[r]) do gc:setFont("sansserif", "r", fontSize) gc:setColorRGB(0x000000) gc:drawString(mat[r][c], x0 + (c - 1) * sideLen, y0 + (r - 1) * sideLen, "top") end end end -- 範囲内の数字の個数を数える(穴なしリスト, 下限, 含む, 上限, 含む) function countIf(list, lowBound, lowIncl, upBound, upIncl) local n = 0 for i = 1, table.maxn(list) do if lowIncl == false and upIncl == false and lowBound < list[i] and list[i] < upBound then n = n + 1 --[[ 下限 < ? < 上限 --]] elseif lowIncl == false and upIncl == true and lowBound < list[i] and list[i] <= upBound then n = n + 1 --[[ 下限 < ? <= 上限 --]] elseif lowIncl == true and upIncl == false and lowBound <= list[i] and list[i] < upBound then n = n + 1 --[[ 下限 <= ? < 上限 --]] elseif lowIncl == true and upIncl == true and lowBound <= list[i] and list[i] <= upBound then n = n + 1 --[[ 下限 <= ? <= 上限 --]] end end return n end -- 行列の一部を行列として抜き出す(穴なし行列, 左上のどこから右下のどこまでを抜き出す) function subMat(mat, rowTop, colLeft, rowBottom, colRight) local matReturn = {} for r = 1, (rowBottom - rowTop + 1) do matReturn[r] = {} for c = 1, (colRight - colLeft + 1) do matReturn[r][c] = mat[rowTop + (r - 1)][colLeft + (c - 1)] end end return matReturn end -- 行列をリスト化する(穴なし行列) function mat2list(mat) local n = 1 local listReturn = {} for r = 1, table.maxn(mat) do for c = 1, table.maxn(mat[r]) do listReturn[n] = mat[r][c] n = n + 1 end end return listReturn end