LoginSignup
7
1

More than 5 years have passed since last update.

箱玉系をProcessingで実装する

Last updated at Posted at 2017-12-07

明治大学総合数理AdventCalender2017も1週間を越えました。長いですね。。

本稿では前回「箱玉系について」に出てきた箱玉系を、Processingで実装する。(ただ実装しても面白くないので)運動方程式を求めて、それを使って実装してみる。

箱玉系の運動方程式

箱玉系を実装するには、まず箱玉系の時間発展がどのように
を求める必要がある。

箱玉系を、$u_n^t$が$0,1$の値をとる二値CAと捉えなおす。
box-ball2_3.016.jpeg
box-ball2_3.017.jpeg

左側にある玉の数が減らなかったときは、
箱玉系のルール(左から順に、右側の一番近い空箱へ移す)により、
次の時間において、必ず$0$になる。
box-ball2_3.018.jpeg
box-ball2_3.019.jpeg
box-ball2_3.020.jpeg
これが箱玉系の運動方程式となる。(やっと実装できる。)

箱玉系の実装

Processing で実装した。

本体とBox classで構成。
(無駄な計算してるけどまあいいか。)

Code (GitHub)
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

Sample

hakodama-1.gif

hakodama-2.gif

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1