【コードゴルフ】シンプル・ライフゲーム
シンプルなライフゲームです。できるだけ短いコードを書いてください。
締切:11月19日(木)AM10:00
【ライフゲーム】
ライフゲームでは、格子状のフィールドの各マス目(セル)に対して、「生」と「死」の2つの状態を初期値として与え、次のルールによって世代変化します。
各セルについて、
「生」の状態の場合
・周囲の8セルのうち、「生」の状態のセルが2つまたは3つ存在する場合は、「生」の状態を継続する
・周囲の8セルのうち、「生」の状態のセルが1つ以下または4つ以上の場合は、「死」の状態になる
「死」の状態の場合
・周囲の8セルのうち、「生」の状態のセルが丁度3つ存在する場合は、「生」の状態になる
☆端のセルの扱い
フィールドの上下左右端のセルはループします。
つまり、左端のセルの左は右端のセル、上端のセルの上は下端のセルと考えてください。
[問題]
フィールドの初期状態と世代数Nを標準入力から受け取り、初期状態からN世代後の状態を出力してください。
なるべく短いプログラムを書けということなので,プログラム言語によってハンデがあるだろう。
AWK で書くと,以下のようなプログラム(可能な限り空白類は削除する)
function m(i,j){return(j==1?a[i,W]:a[i,j-1])+a[i,j]+(j==W?a[i,1]:a[i,j+1])}
function k(i,j){return(i==1?m(H,j):m(i-1,j))+m(i,j)+(i==H?m(1,j):m(i+1,j))}
BEGIN{getline N;getline H;getline W;for(i=1;i<=H;i++){getline s;for(j=1;j<=W;j++)a[i,j]=substr(s,j,1)=="*"}
for(l=1;l<=N;l++){for(i=1;i<=H;i++)for(j=1;j<=W;j++)b[i,j]=a[i,j]
for(i=1;i<=H;i++){for(j=1;j<=W;j++){c=k(i,j)-a[i,j];if(!a[i,j]&&c==3)b[i,j]=1
else if(a[i,j]&&(c<2||c>3))b[i,j]=0}}for(i=1;i<=H;i++)for(j=1;j<=W;j++)a[i,j]=b[i,j]}
for(i=1;i<=H;i++){for(j=1;j<=W;j++)printf a[i,j]==1?"*":".";print""}}
R で書くと以下のようになる(空白などは残す)
con = file("stdin", "r")
N = as.numeric(readLines(con, 1))
H = as.numeric(readLines(con, 1))
W = as.numeric(readLines(con, 1))
a = readLines(con)
a = matrix(unlist(strsplit(a, ""))=="*", ncol=nchar(a[1]), byrow=TRUE)
m = function(i, j) {
ifelse(j == 1, a[i, W], a[i, j-1])+a[i, j]+ifelse(j == W, a[i, 1], a[i, j+1])
}
k = function(i, j) {
ifelse(i == 1, m(H, j), m(i-1, j))+m(i, j)+ifelse(i == H, m(1, j), m(i+1, j))
}
for (l in seq_len(N)) {
b = a
for (i in 1:H) {
for (j in 1:W) {
c = k(i, j)-a[i, j]
if (!a[i, j] && c == 3) {
b[i, j] = 1
} else if (a[i, j] && (c < 2 || c > 3)) {
b[i, j] = 0
}
}
}
a = b
}
for (i in 1:H) {
cat(paste(gsub("0", "\\.", gsub("1", "\\*", paste(a[i, ], collapse=""))), "\n", sep=""))
}