お覚悟決めなさい!

最近娘2がプリキュアに興味を持ち始めてかわいいです。
数年前に娘1がスマイルとドキドキで通った道ですね。

てことで。3歳の誕生日プレゼントにプリンセスパフュームを購入。
キーを挿して回すと光ったり喋ったりするんです。

3人のプリキュアそれぞれのキーがあって、
それぞれ違うこと喋るんです。

http://precure.channel.or.jp/goods/perfume/precure.channel.or.jp

なんとなく、どういう仕組みなのかなーって。気になってるところにこんな記事を見つけて。
(ネタバレ注意)
GO!プリンセスプリキュア:プリンセスパフュームの万能ドレスアップキーを作った : クラウドルアーズブログ

でも、万能鍵作るの面倒だし、娘が使ってない時に適当に指で押しながらボケーッと考察してみました。

仕組み

鍵を差し込んで90度回す。
本体側にボタンが3つあって、それが鍵側の突起で押される仕組み。
90度回す間に鍵側の突起は3つ分だけ通り過ぎるので、3つのボタンが3回押される仕組みで動いてるっぽい。

キュアフローラーの変身はこんな感じ。

ボタン1 ボタン2 ボタン3
1回目 ON OFF OFF
2回目 OFF ON OFF
3回目 OFF ON ON

これって423か。頑張ってプログラマーっぽく書いてみた。

考察あそび

手元に鍵が4つある。3つはプリキュアの変身用のキーで、1つは占いとかのキー。

フローラ変身 423
マーメイド変身 413
トゥインクル変身 463
占い 153

8x8x8=512通りある?

0はなさそう

7x7x7=343通り
に減った。

あ、そうだ。折角だからコードで書こう。

  @Test
  public void testPrincessPerfume() {
    @Data
    class Value {
      final int i,j,k;
    }

    // 全部入り
    List<Value> values = new ArrayList<>();
    for (int i = 1; i <= 7; i++) {
      for (int j = 1; j <= 7; j++) {
        for (int k = 1; k <= 7; k++) {
          values.add(new Value(i, j, k));
        }
      }
    }
    assertThat(values.size(), is(343));
  }

逆回し対応

鍵を最後まで回して逆回しをしたら、例えばフローラの鍵(423)だと324って動きができちゃうので
324で反応するメッセージは用意しなさそう。だから324って鍵はなさそうだなーと思った。

それと、例えば323って鍵があって、これを逆回ししたら323になってしまうので、
鍵を外すときにまたメッセージがなってしまう。これも避けたいよね。

    // 逆回し対応
    values = values.stream()
        .filter(v -> v.i < v.k)
        .collect(Collectors.toList());
    assertThat(values.size(), is(147));

147個に減った。

連続する同じ数字

同じ数字は連続しないんじゃないかなーと思った。
回してる途中でちょっと戻してまた進めた時に、同じ数字が押されて、別のメッセージがでてしまったら嫌だなって思うから。

    // 連続する数字を除去
    values = values.stream()
        .filter(v -> (v.i != v.j && v.j != v.k))
        .collect(Collectors.toList());
    assertThat(values.size(), is(105));

105通りか。

触ってみた

ってところで触ってみた。
いくつか新しいメッセージを見つけたんだけど。
なんとなく、全部3で終わってるっぽい?ふーん。

3で終わるものだけにする

って言っても、さっき、逆回し対応でごにょったから、フィルタリングしたあと3を末尾に持ってこよっと。

    // 3終わりのものだけを取得
    values = values.stream()
        .filter(v -> (v.i == 3 || v.k == 3))
        .map(v -> v.i == 3 ? new Value(v.k, v.j, v.i) : v)
        .collect(Collectors.toList());
    assertThat(values.size(), is(30));

30個か!全部試せそうな量だ。

てことで全部試してみた

ほほー。20個ヒットした。結構ヒットしたなー。色んなメッセージ出てきた。
でも、以下の10個は何も当たらない。

173,273,713,723,743,753,763,473,573,673

ん。これ、7も特別な意味を持ってそうだなー。
3終わりだけだと思ってたけど、7終わりもあるんじゃね?これ。

ちょっと考えなおす

3か7で終わるとして、じゃあ「逆回し」「連続」の条件を考えると
結局3と7は1番目と2番目にはでてこないってことか。

public class PrincessPerfume {
  @Test
  public void testPrincessPerfume() {
    @Data
    class Value {
      final int i, j, k;
    }

    List<Value> values = new ArrayList<>();
    for (int i = 1; i <= 7; i++) {
      for (int j = 1; j <= 7; j++) {
        for (int k = 1; k <= 7; k++) {
          values.add(new Value(i, j, k));
        }
      }
    }

    List<String> candidates = values.stream()
        // 3か7で終わる
        .filter(v -> (v.k == 3 || v.k == 7))
        // 3と7は最後にしか出てこない
        .filter(v -> (v.i != 3 && v.j != 3))
        .filter(v -> (v.i != 7 && v.j != 7))
        // 連続する数字はない
        .filter(v -> (v.i != v.j))
        .sorted((v1, v2) -> {
          return (v1.k * 100 + v1.i * 10 + v1.j)
              - (v2.k * 100 + v2.i * 10 + v2.j);
        })
        .map(v -> "" + v.i + v.j + v.k)
        .collect(Collectors.toList());

    System.out.println(candidates.size());
    System.out.println(candidates);
  }
}
40
[123, 143, 153, 163, 213, 243, 253, 263, 413, 423, 453, 463, 513, 523, 543, 563, 613, 623, 643, 653,
127, 147, 157, 167, 217, 247, 257, 267, 417, 427, 457, 467, 517, 527, 547, 567, 617, 627, 647, 657]

3終わりの20個はさっき見つけたから。7終わりの20個があるっぽいなーって試したらほんとにでてきた(∩´∀`)∩ワーイ。

答え合わせ

ま、誰かまとめてるだろーと思ってググったらあった。合ってた!
(ネタバレ注意)
解析 - リンクルストーン@ ウィキ - アットウィキ

買ってよかった。面白かったー。