調子に乗って RxJava でもやってみた。
Javaの講義、試験が「自作関数を作り記述しなさい」って問題だったからズン」「ドコ」のいずれかをランダムで出力し続けて「ズン」「ズン」「ズン」「ズン」「ドコ」の配列が出たら「キ・ヨ・シ!」って出力した後終了って関数作ったら満点で単位貰ってた
— てくも (@kumiromilk) 2016年3月9日
がんばって Observable.window
を使ってみた。
//zondoko.java
// なんちゃってラムダ使用。あと Android。
public void doZondoko() {
final Random random = new Random();
final List<String> PATTERN = Arrays.asList("ずん", "ずん", "ずん", "ずん", "どこ");
final String K = "キ・ヨ・シ!";
Observable.concat( // ※ の Observable<List<String>> を直列に連結
Observable.interval(500, TimeUnit.MILLISECONDS)
.map(_ -> random.nextInt(2) == 0 ? "ずん" : "どこ") // ランダムに ずん or どこ
.window(PATTERN.size(), 1) // 要素数5のWindowを1ずつズラしてく
.map(window -> window.toList())) // Observable<Observable<String>> を Observable<List<String>> に変換 ※
.flatMap(window -> {
if (sequenceEqual(window, PATTERN)) { // パターンと一致していたら…
final List<String> says = new ArrayList<>();
says.addAll(window);
says.add(K); // キ・ヨ・シ!を追加
return Observable.concat(
Observable.just(says),
Observable.just(Collections.<String>emptyList())); // 終了判定用の空リスト
} else {
return Observable.just(window);
}
})
.takeWhile(says -> !says.isEmpty()) // 空リストになるまで繰り返す
.subscribe(says -> Log.d(TAG, dump(says)));
}
/** リストとリストの要素一致 */
private boolean sequenceEqual(List<String> listA, List<String> listB) {
Iterator<String> iterA = listA.iterator();
Iterator<String> iterB = listB.iterator();
while (iterA.hasNext() && iterB.hasNext()) {
if (iterA.next() != iterB.next()) {
return false;
}
}
return (!iterA.hasNext() && !iterB.hasNext());
}
/** リスト内容をダンプ */
private String dump(List<String> list) {
final StringBuilder b = new StringBuilder();
for (String s : list) {
if (!TextUtils.isEmpty(b.toString())) {
b.append(", ");
}
b.append(s);
}
return b.toString();
}
どこ, ずん, どこ, どこ, ずん
ずん, どこ, どこ, ずん, どこ どこ, どこ, ずん, どこ, ずん どこ, ずん, どこ, ずん, どこ ずん, どこ, ずん, どこ, どこ どこ, ずん, どこ, どこ, ずん ずん, どこ, どこ, ずん, ずん どこ, どこ, ずん, ずん, ずん どこ, ずん, ずん, ずん, ずん ずん, ずん, ずん, ずん, どこ, キ・ヨ・シ!
「window(5, 1) -> toList -> concat してるならそれは buffer(5, 1)
やんけ」というのを こちら で知って、 buffer
版も書いてみた。
//Zondoko_buffer.java
public void doZondoko() {
final Random random = new Random();
final List<String> PATTERN = Arrays.asList("ずん", "ずん", "ずん", "ずん", "どこ");
final String K = "キ・ヨ・シ!";
Observable.interval(500, TimeUnit.MILLISECONDS)
.map(_ -> random.nextInt(2) == 0 ? "ずん" : "どこ") // ランダムに ずん or どこ
.buffer(PATTERN.size(), 1) // 要素数5のBufferを1ずつズラしてく
.flatMap(buf -> {
if (sequenceEqual(buf, PATTERN)) { // パターンと一致していたら…
final List<String> says = new ArrayList<>();
says.addAll(buf);
says.add(K); // キ・ヨ・シ!を追加
return Observable.concat(
Observable.just(says),
Observable.just(Collections.<String>emptyList())); // 終了判定用の空リスト
} else {
return Observable.just(buf);
}
})
.takeWhile(says -> !says.isEmpty()) // 空リストになるまで繰り返す
.subscribe(says -> Log.d(TAG, dump(says)));
}