明治大学総合数理AdventCalender2017も1週間を越えました。長いですね。。
本稿では前回「箱玉系について」に出てきた箱玉系を、Processingで実装する。(ただ実装しても面白くないので)運動方程式を求めて、それを使って実装してみる。
箱玉系の運動方程式
箱玉系を実装するには、まず箱玉系の時間発展がどのように
を求める必要がある。
箱玉系を、$u_n^t$が$0,1$の値をとる二値CAと捉えなおす。
左側にある玉の数が減らなかったときは、
箱玉系のルール(左から順に、右側の一番近い空箱へ移す)により、
次の時間において、必ず$0$になる。
これが箱玉系の運動方程式となる。(やっと実装できる。)
箱玉系の実装
Processing で実装した。
本体とBox classで構成。
(無駄な計算してるけどまあいいか。)
Code ([GitHub](https://github.com/massss/box-and-ball))
Main
final int boxSize = 40;
final int num = 25;
int Width = num * boxSize;
boolean isRunning = false;
Box[] boxes = new Box[num];
int[] tempBoxes = new int[num];
int t = 0;
int delay = 50;
int framerate;
void settings() {
size(Width, boxSize + 50);
}
void setup() {
background(255);
for (int i = 0; i < num; i++) {
boxes[i] = new Box(i, 0);
}
}
void draw() {
background(255);
if (t % delay == 0) {
framerate = (int)frameRate;
if (isRunning) {
for (int i = 0; i < num; i++) {
tempBoxes[i] = boxes[i].ball;
}
for (int i = 0; i < num; i++) {
boxes[i].calcState();
}
}
t = 0;
}
t++;
for (int i = 0; i < num; i++) {
boxes[i].display();
}
fill(250, 0, 0);
textAlign(LEFT);
textSize(30);
if (isRunning) {
text("Run", 0, height - 10);
} else {
text("Stop", 0, height - 10);
}
textAlign(RIGHT);
textSize(18);
text("frameRate: " + framerate +" / " + delay, width - 10, height - 10);
}
void mouseClicked() {
int cellColumn = (int)(mouseX / boxSize);
if (cellColumn < boxes.length) {
boxes[cellColumn].changeState();
}
}
void mouseDragged() {
int cellColumn = (int)(mouseX / boxSize);
if (0 < mouseX && mouseX < Width && 0 < mouseY && mouseY < boxSize) {
boxes[cellColumn].changeState();
}
}
void keyReleased() {
if (key == ' ') {
isRunning = !isRunning;
} else if (key == 'r' || key == 'R') {
randomSetup();
} else if (key == 'c' || key == 'C') {
setup();
} else if (keyCode == UP) {
if (delay != 100) {
delay += 10;
}
} else if (keyCode == DOWN) {
if (delay != 10) {
delay -= 10;
}
} else if (keyCode == ENTER) {
printInfo();
}
}
void randomSetup() {
for (int i = 0; i < num; i++) {
float coinSpeed = random(1);
int coin;
if (coinSpeed > 0.8) {
coin = 1;
} else {
coin = 0;
}
boxes[i].ball = coin;
}
}
void printInfo() {
for (int i = 0; i < num; i++) {
if (i == num - 1) {
println(boxes[i].ball);
} else {
print(boxes[i].ball + ", ");
}
}
}
BoxClass
class Box {
int pos;
int num;
int ball;
Box (int num, int ball) {
this.pos = num * boxSize;
this.num = num;
this.ball = ball;
}
void changeState() {
if (ball == 1) {
this.ball = 0;
}else {
this.ball = 1;
}
}
void calcState() {
int countPast = 0;
int countNext = 0;
for (int i = 0; i < this.num; i++) {
if (boxes[i].ball == 1) {
countNext++;
}
if (tempBoxes[i] == 1) {
countPast++;
}
}
this.ball = min(countPast - countNext, 1 - this.ball);
}
void display() {
fill(255);
rect(pos, 0, boxSize, boxSize);
fill(0);
if (ball == 1) {
ellipse(pos + boxSize / 2, boxSize / 2, boxSize * 2/3, boxSize * 2/3);
}
}
}
Command
Key or mouse | Processing |
---|---|
click |
add or remove ball |
drag |
〃 |
r , R
|
setup balls randomly |
c , C
|
clear all balls |
↑ |
up delay rate |
↓ |
down delay rate |
space |
run or stop |
ENTER |
print data in console |