ルービックキューブのソルバーライブラリ"kociemba"の使い方

# はじめに
ルービックキューブの解法を計算してくれるライブラリ[kociemba](https://github.com/muodov/kociemba)の紹介＆簡単な使い方を解説する記事です．


これから大学の授業等や夏休みの自由研究でルービックキューブのソルバーを探す人が，すぐにkociembaを見つけられるようにと思いこの記事を書きました．


# kociembaを使った作品例
このライブラリのおかげで，「全自動でルービックキューブを解くロボット」を作ることができました．
[Video: Automatic Rubik's Cube Solver](https://www.youtube.com/watch?v=ByR47PH_2RU&t=2s)

![Screenshot from 2020-07-05 22-13-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367429/7a94abc9-dd27-aaf8-d4f1-37f440a516de.png)



# kociembaとは？
kociembaとはルービックキューブソルバーのライブラリの名前です．
このkociembaという名前，もともとはルービックキューブを解くアルゴリズム[Kociemba's algorithm](https://en.wikipedia.org/wiki/Optimal_solutions_for_Rubik%27s_Cube#Kociemba's_algorithm)を考案したHerbert Kociembaという学者さんの名前です．このKociemba's algorithmをベースにこのライブラリが実装されています．
じつはルービックキューブ界隈には神の数字（God's Number）というものがあります．これはどんな状態からでもこの値以下の手数で６面全面をそろえることができるというものです．驚くべきことに，この数字は大きくても20ということが証明されています([参考](https://news.livedoor.com/article/detail/4950077/))．つまり，どんなにバラバラにしても20手以内で全面そろえることができるということです．

kociembaは必ずしもこの最善手は返しません．それでも，"good enough"な手数の解は返してくれます．

そもそも自分がこのライブラリを見つけたのは，学科の制作課題のために，ルービックキューブを解くライブラリを探していていた時でした．
当然ルービックキューブを解くためのライブラリは他にもたくさんありますが，とてつもなく遅かったり，使い方がさっぱりわからない，といったものも多く，当時はどれを使うのが一番いいのか分からず苦労しました．
Kociembaは，自分が試した中で最も使いやすく，かつ計算も早かった（概ね１秒以内に解を返してくれる）ので，ルービックキューブのライブラリを探しているという人にはお勧めします．

# インストール方法
自分の環境はUbuntu16.04 LTSでした．
pipで入れることができます．Python2.7, Python3.3+で確認済みのようです

```Shell
pip install kociemba
```

ubuntuなどUnixベースのOSを使っている人は以下のコマンドも必要なようです．

```
sudo apt-get install libffi-dev
```

# 使い方
以下のように`kociemba.solve()`の引数に現在の色の状態を表す文字列を入れると，全面そろえるための解（回し方）を返してくれます．記号の意味は後ほど解説します．

```Python:
>>> import kociemba

>>> kociemba.solve('DRLUUBFBRBLURRLRUBLRDDFDLFUFUFFDBRDUBRUFLLFDDBFLUBLRBD')
u"D2 R' D' F2 B D R2 D2 R' F2 D' F2 U' B2 L2 U2 D R2 U"

```

# ルービックキューブの操作記法
ここでは上の文字列の求め方と，返ってきた解の読み方について説明します．
###  軸は不動
まず理解すべきは，**軸は動かない**，ということです．
ルービックキューブができる人にとっては常識ですが，ルービックキューブの軸はどんなにネジ繰り回しても変わりません．以下の画像で，どう面を回しても，各面の中心のマスは動かないことが分かるかと思います．

![Screenshot from 2020-07-05 22-39-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367429/6c24c08d-15f6-31da-f346-303117492768.png)

この事実を利用すると，複雑に見える「ルービックキューブの状態」も，きちんと一意に決まる記号で表せることがわかります．

### 面の名前は中心マスの色で表す
各面の中心マスは動かないことがわかったので，どんなにバラバラな状態でも「中心が赤の面を回して」のように,面の中心のマスの色を指定することで，どの面かを指定することができるようになりました．

### 回転角度も記号で表す
次に考えるべきは「どれくらい回すか」の表し方です．ここは，面の名前さえ付けられれば簡単です．
kociembaでは以下のように回転角度を表します．RはRedの面だとして，

```
R: 時計回りに９０度
R': 反時計周りに90度
R2: 180度回転
```


# ソルバーへの入力方法
以上で，準備は終わりました．すでに面の表し方，回し方の記法は分かったと思います．あとは，どの順番に記号を連結してソルバーへの入力の文字列を作るかのみとなります．

ここで少しややこしいのですが，kociembaはどの向きで持っていようとも解けるように，各面を色ではなく（F(front), B(back), R(right), L(left), U(up), B(bottom)）で表します．そこでまず，これらの記号と自分のルービックキューブの色の対応を決めます．
例えば，ある面を正面と決めた時，正面の中心のマスの色が白であれば白色をFで表し，背面の中心のマスの色が黄色であれば黄色をBで表します．これを全ての面に対し行い，以下のように色と記号の対応を求めます．

- F(正面)→白
- B(背面)→黄色
- R(右)→緑
- L(左)→青
- ...


次に，以下の展開図をもとにどこの位置にどの色があるかを調べ上げます（ここは超大変）．

![Screenshot from 2020-07-05 23-06-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367429/ade56ec7-3309-434d-b66c-6f6e7f54b8c3.png)

例えば，一番上の`U1`の位置に黄色があったとすれば，`U1=B`とします．
その調子で，以下の順番で色を並べ，文字列$s$を作ります．

`s = [U1, U2, U3, U4, U5, U6, U7, U8, U9, R1, R2, R3, R4, R5, R6, R7, R8, R9, F1, F2, F3, F4, F5, F6, F7, F8, F9, D1, D2, D3, D4, D5, D6, D7, D8, D9, L1, L2, L3, L4, L5, L6, L7, L8, L9, B1, B2, B3, B4, B5, B6, B7, B8, B9]`

残すは実行だけです．

# 実行

以下のように，`kociemba.solve()`に文字列`s`を引数として与えることで解を得ます．

```python 
>>> import kociemba

>>> kociemba.solve('DRLUUBFBRBLURRLRUBLRDDFDLFUFUFFDBRDUBRUFLLFDDBFLUBLRBD')
u"D2 R' D' F2 B D R2 D2 R' F2 D' F2 U' B2 L2 U2 D R2 U"  # 解
```

後は，上でみた記法に従ってルービックキューブを回せば全面がそろいます．

ここまで読んでくれてありがとうございます．お疲れさまでした．

# まとめ

ルービックキューブソルバーライブラリ kociembaを紹介しました．本物であれ，CGであれ，ルービックキューブを解きたくて困ったらぜひ使ってみてください．

# 参考
[kociemba - GitHub](https://github.com/muodov/kociemba)
[Optimal solutions for Rubik's Cube](https://en.wikipedia.org/wiki/Optimal_solutions_for_Rubik%27s_Cube#Kociemba's_algorithm)