ラングトンのアリ
ラングトンのアリの描画 どう書く?org にインスパイヤされて、ラングトンのアリの軌跡を表示するプログラムを作ります。 ラングトンのアリ - Wikipedia を見れば分かりますが、以下のようなものです。(以下、Wikipedia からの引用)
* 黒いマスにアリがいた場合、90°右に方向転換し、そのマスの色を反転させ、1マス前進する。 * 白いマスにアリがいた場合、90°左に方向転換し、そのマスの色を反転させ、1マス前進する。
まとめて関数化すればもっとスマートになると思いますが、とりあえず作成してみたレベルのものを載せておきます。
#! /usr/local/bin/gawk -f
# langtons_ant.awk
# ラングトンのアリ
# usage: gawk -f langtons_ant.awk
BEGIN {
srand();
# 端末の高さと幅を取得する
get_terminal_cmd = "stty -a";
while (get_terminal_cmd | getline > 0) {
if ($4 == "rows") {
rows = $5;
sub(/;/, "", rows);
}
if ($6 == "columns") {
cols = $7;
sub(/;/, "", cols);
}
}
close(get_terminal_cmd);
cols--;
# 配列の初期化 (全て白)
for (i = 1; i <= cols; i++) {
for (j = 1; j <= rows; j++) {
arr[i, j] = ".";
}
}
# 中心に現在地点を配置する
current_x = int(cols / 2);
current_y = int(rows / 2);
for (;;) {
count++;
if (count == 1) {
post_x = current_x - 1;
post_y = current_y;
}
if (arr[current_x, current_y] == ".") {
if (post_x == current_x - 1) {
new_x = current_x; new_y = current_y - 1;
}
if (post_x == current_x + 1) {
new_x = current_x; new_y = current_y + 1;
}
if (post_y == current_y - 1) {
new_x = current_x + 1; new_y = current_y;
}
if (post_y == current_y + 1) {
new_x = current_x - 1; new_y = current_y;
}
arr[current_x, current_y] = "#";
post_x = current_x;
post_y = current_y;
current_x = new_x;
current_y = new_y;
} else {
if (post_x == current_x - 1) {
new_x = current_x; new_y = current_y + 1;
}
if (post_x == current_x + 1) {
new_x = current_x; new_y = current_y - 1;
}
if (post_y == current_y - 1) {
new_x = current_x - 1; new_y = current_y;
}
if (post_y == current_y + 1) {
new_x = current_x + 1; new_y = current_y;
}
arr[current_x, current_y] = ".";
post_x = current_x;
post_y = current_y;
current_x = new_x;
current_y = new_y;
}
# 50 回に 1 回表示する
if (count % 50 == 0) {
plot(arr, cols + 1, rows - 1);
system("sleep 0.1");
}
}
}
# 指定された位置で表示する
function plot(arr, x_size, y_size, i, j, k, len, str) {
for (j = 1; j <= y_size; j++) {
for (i = 1; i <= x_size; i++) {
if (arr[i, j] == "") {
arr[i, j] == ".";
} else {
len = length(arr[i, j]);
str = arr[i, j];
for (k = 1; k <= len; k++) {
arr[i + k - 1, j] = substr(str, k, 1);
}
}
line = sprintf("%s%s", line, arr[i, j]);
}
print line;
line = "";
}
}
plot() 関数は以前AWK Users JP :: コンソールアナログ時計で用いたものを再利用しています。
実行してみます。 初期値に依存しますが、図形がどんどん成長して以下のようになっていきます。
............................................................................... ............................................................................... ............................................................................... ............................................................................... ..................................##.......#................................... .................................##......#.#................................... ................................#.##..###.##................................... ................................#..#.#.#.####.................................. .................................#.#.#.#..#.#.................................. ...................................#.....#..................................... ......................................###...................................... ....................................###..#..................................... ................................#.#.#..#.#.#................................... ................................###....#.#..#.................................. .................................#...##..##.#.................................. ..................................##......##................................... .........................................##.................................... ............................................................................... ............................................................................... ............................................................................... ...............................................................................
awk 単独だと表示能力が乏しいので、他のツールと合わせて表示させたいものです。


