1. kazurof

    Posted

    kazurof
Changes in title
+ズンドコキヨシをJavaで
Changes in tags
Changes in body
Source | HTML | Preview

流行りのズンドコキヨシをJavaで書いてみた。

Streamで書いてみた

Zundoko.java
import java.util.stream.Stream;

public class Zundoko {
  public static void main(String args[]) {
    StringBuilder sb = new StringBuilder();
    Stream<String> stream = Stream.generate(() -> Math.random() > 0.5 ? "ズン" : "ドコ");
    try {
      stream.peek(s -> {
        System.out.print(s);
        sb.append(s);
        if (sb.toString().endsWith("ズンズンズンズンドコ")) {
          throw new RuntimeException();
        }
      }).forEach(s -> {
      });
    } catch (RuntimeException r) {
      System.out.print("キ・ヨ・シ!");
    }
  }
}

むりやりStreamで書いてみたが、終了の判定が例外処理で美しくない。それに終端処理したいがためだけに空のforEachをしてるし。Eclipse Collections を使えばRuby並に簡潔に行けるかなと思ってちょっと調べたが、そうでもないようだ。(私が知らないだけかもですが)

マルチスレッドで書いてみた

ZundokoThread.java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ZundokoThread {
  public static void main(String args[]) {
    ExecutorService zunSer = Executors.newFixedThreadPool(1);
    ExecutorService dokoSer = Executors.newFixedThreadPool(1);
    ZundokoPool pool = new ZundokoPool(zunSer, dokoSer);

    zunSer.submit(new PutTask("ズン", pool));
    dokoSer.submit(new PutTask("ドコ", pool));
  }
}

class PutTask implements Runnable {
  String text;
  ZundokoPool pool;

  public PutTask(String text, ZundokoPool pool) {
    this.text = text;
    this.pool = pool;
  }

  @Override
  public void run() {
    while (true) {
      try {
        Thread.sleep((long) Math.random() * 100);
      } catch (InterruptedException e) {
        break;
      }
      pool.put(text);
    }
  }
}

class ZundokoPool {
  StringBuilder sb = new StringBuilder();
  ExecutorService zunSer;
  ExecutorService dokoSer;

  public ZundokoPool(ExecutorService zunSer, ExecutorService dokoSer) {
    this.zunSer = zunSer;
    this.dokoSer = dokoSer;
  }

  synchronized void put(String str) {
    sb.append(str);
    if (sb.toString().endsWith("ズンズンズンズンドコ")) {
      System.out.println(sb + "キ・ヨ・シ!");
      zunSer.shutdownNow();
      dokoSer.shutdownNow();
    }
  }
}

本当は、Math.random() を使わないで書くという一発芸を狙ってスレッドで書いてみたが、各スレッドの動作頻度をバラけさせるために結局使ってしまった。重要ポイントは、InterruptedExceptionをキャッチしたら breakするところだと思う。これをやらないと、キ・ヨ・シ!を出力した後もスレッドの処理が終わらない。また、これをやってもキ・ヨ・シ!出力後にZundokoPool#put()が呼ばれる場合がある。ロックの管理をもっと丁寧に細かくやれば回避できるかな?

もっと別の書き方ないかなあ。もっと面白い書き方ないかなあ。セミコロンレスJavaもコードゴルフ決して悪くないが新鮮味に欠ける。(実際に書いたほうが絶対的に偉いんだけど。)