これだけ分かるとNxNxNのルービックキューブは全部解ける！

## はじめに

[フューチャーAdventCalender2 2019](https://qiita.com/advent-calendar/2019/future2)の25日目(The last of this year!)です。
ちなみにアドベントカレンダー1の記事は[こちら](https://qiita.com/advent-calendar/2019/future)から。

 今年で入社4年目になりますが、趣味はパズルとそれらを解くためのアルゴリズムです。
職場のデスク上には写真のような様々なルービックキューブを置いています。特に怒られることなく、好きなものに囲まれつつ自由な雰囲気の中で楽しく仕事ができています。

<img width="400px" alt="IMG_4098.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120601/3bd40baf-3f98-dbeb-feb1-2ae0b1ca3003.jpeg">

## 本題

一般な人は、「怖くて触りたくない」、もしくは、「一面だけ頑張って揃えられるが、それ以上は壊したくないので撤退する」といった方が少なくないと思います。

インターネットで調べたら、↓のようなルービックキューブの6面完全攻略法がいっぱい出てきます。

<img width="200px" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120601/905cc5b3-394e-622e-4a28-d8cb5ef5bd80.png">
[初心者向け解け方例](https://macozy.com/rubik/3rc/index.html)

それらを取扱説明書として片手にキューブを完成させ、「ウンウンできた」と満足することもいいでしょう。しかし私はそれをあまり推奨しません。理由は以下となります。

- あまりにも手順が煩雑すぎて、完全に理解するまで根気がなくなる
- それぞれステップかつそれぞれすごく多いパターン数かつそれぞれ長い手順、全然覚えられない
- 手順を見ながらなんとか6面揃えたとしても、全部のパターンに対して手順を覚えないと、独立に解けると言えない
- 手順を全部覚えきった人にとっても、なぜかその手順で揃えるのを理解しづらいので腑に落ちない

なので、本記事では、**手順なし**に汎用的なルービックキューブの揃え方を紹介します。しかも、その汎用性は、3x3x3のルービックキューブに限らなく、NxNxNまで適用できる**簡単な**方法を説明します。記憶より理解を重視する人への福音です。

### この記事が説明しないこと

- スピード復元、もしくは、復元の最短経路を探索するアルゴリズム、その実装
- 覚えにくい複雑な復元アルゴリズム
- 変な形なルービックキューブ (例: [2x2x3 tower cube](https://www.jaapsch.net/puzzles/cube223.htm)、[megaminx](https://ruwix.com/twisty-puzzles/megaminx-gigaminx-teraminx-petaminx/) など)
- ルービックキューブ以外のパズル (例: [チャイニーズリング](https://ja.wikipedia.org/wiki/%E3%83%81%E3%83%A3%E3%82%A4%E3%83%8B%E3%83%BC%E3%82%BA%E3%83%AA%E3%83%B3%E3%82%B0)、[箱入り娘]

### この記事が説明すること

- 具体的なケースバイケースのテクニックではなく、超汎用的にNxNxNルービックキューブに対する方法論
- 見た瞬間にすぐ覚える1個のシンプルな手わざの紹介
- その手わざを用いて、他のピースに影響のない前提で、同時に3つのピースの場所を交換する方法
- その手わざを用いて、他のピースに影響のない前提で、同時に2つのピースを向きを回転する方法

### この記事を読むことで身につくこと

- 初めてルービックキューブを触る人でも、解き方の方向性が分かる
- 最速の解き方ではないけど、一番ベーシックの手わざを組み合わせてルービックキューブのどんな状況でも解ける(論理上)
- 3x3x3だけではなく、2x2x2や4x4x4及びそれ以上のハイレイヤーのルービックキューブでも解け方が分かる
- 自分なりの方法でルービックキューブを解く人にはヒントになり、できないケースでもこの方法を知っておくと安心

### 前提知識

- 説明の方便上、一般に使われている回転記号 `F` `R2` `U'` などを使う → [こちら](https://ja.wikibooks.org/wiki/%E3%83%AB%E3%83%BC%E3%83%93%E3%83%83%E3%82%AF%E3%82%AD%E3%83%A5%E3%83%BC%E3%83%96/%E5%9B%9E%E8%BB%A2%E8%A8%98%E5%8F%B7)に参考してください
- 各ピースが「位置」と「向き」は2種類の状態を持っている
- 他のパズルにもあるかもしれないが、ルービックキューブには、[パリティ](https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%AA%E3%83%86%E3%82%A3_(%E3%83%91%E3%82%BA%E3%83%AB))(ありえない状態)が存在します。有名なパリティは下図のように解けない15パズルがあります。 → [[1]](https://www.speedsolving.com/wiki/index.php/Parity) (14と15は論理上交換不可能)

<img width="500px" alt="解けない15パズル" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120601/90325c52-289c-b26b-58e0-99dc7a923683.png">

ルービックキューブを壊さない限り、どうしても、ありえない状態(パリティ)の例を2個挙げます。
(デモの中に、三角のPlayボタン`▶`を押すと動的なデモが始まります)

- 不可能状態1: 1個のコーナーピースが向きが違う → [[デモ]](https://alg.cubing.net/?stage=F2L&title=Impossible%20case%201:%20corner%20twisted&setup=z__y_RUR-URU2R-L-U-LU-L-U2L_y-_z&alg=y.y.y.y&view=fullscreen)
- 不可能状態2: 向きを変えずに2個のエッジピースが交換される → [[デモ]](https://alg.cubing.net/?stage=F2L&title=Impossible%20case%202:%202%20edges%20swapped&setup=M2U2M2z2&alg=y.y.y.y&view=fullscreen)

パリティについての数学原理などは割愛しますが、ざっくりとルービックキューブの制約を以下にまとめます。

- 1色のセンターピース、2色のエッジピースと3色のコーナーピース、お互いに場所交換することが不可能
- 他のピースに影響しない前提で、単独にエッジピースとコーナーピースの向きを回転することが不可能
- ↑に対して、2個のピースA,Bは、同時に逆方向の向き回転(例、A時計回り、B反時計回り)なら可能
- 他のピースに影響しない前提で、2個のピースA,Bは、向きを変えずに場所のみ交換すること(A=>B=>A)が不可能
- ↑と同条件で3個のピースA,B,Cの場所交換(A=>B=>C=>A)なら可能

したがって、影響範囲が最も小さく、一番ベーシックな可能な操作は、ただ以下の2個あります。

- 3つピースA,B,Cの場所を交換する (順番例: A=>B=>C=>A)
- 2つのピースA,Bの向きを逆方向に回転する (例: A反時計回り、B時計回り)

### ゴールドフィンガー (Gold Finger)

この手わざは僕の発明ではないですが、インターネットで検索してもなかなか出ないため、「ゴールドフィンガー(Gold Finger)」(以下略称`GF`)と命名しました。石を金に変えられる仙人の指というイメージで、万能的な技を表しています。

ゴールドフィンガーは、実はとても簡単(Simple is beautiful)です。見た瞬間、もう覚えられます。
さっそく見てみましょう。 → [[デモ]](https://alg.cubing.net/?alg=R-_D2_R&stage=LL&title=Gold%20Finger%20(Corner)&view=playback)

びっくりするほどシンプルでしょう。でも、「それですべてのルービックキューブを解ける？嘘でしょう!」と思われますが、急がば回れ、まずは`GF`の操作の性質を分析しましょう。

- `性質1.` `GF`の逆動作は`GF`自身なので、`GF`は2回実施すると元に戻ります。 -> [[デモ]](https://alg.cubing.net/?alg=R-_D2_R%0AR-_D2_R&stage=LL&title=Gold%20Finger%20(Corner)%20x2&view=playback)
- `性質2.` `GF`は上の層の1ピース(上右前)を下の層(下左後)に持ってく効果があります。もう一回実行すると、戻ってきます。

`性質1.`からの推論は、`GF`を2回、もしくは、偶数回実施すると、全体は無変化になります。後ほどの説明で分かるが、それはとても優れている性質です。

`性質2.`の使い道を説明する前に、まずプログラミングの時、変数aとbの値交換(swap)のやり方を思い出してみてください。

```go
func swap(a, b *int) {
  var temp = *a
  *a = *b
  *b = temp
}
```
**本記事のソースコードはGolangの文法に準じます。*

`temp`変数を臨時的な置き場として用いて、`a`と`b`を交換していますね。
では、今度は、`a`,`b`,`c`の3つの変数を順次に一個ずらして次の変数に値をシフトする問題を考えましょう。
要するに、`b,c,a = a,b,c`のような代入をやりたいです。しかし、ルービックキューブに適用するために、以下の制限も含めて考えてほしいです。

**【制限】代入を使えなくて、`swap`しか使えません。**

ちょっと考えたら、以下のように、`a`,`b`,`c`,`a`を順次にある`temp`と交換すればいいですね。

```go
func shift(a, b, c *int){
  var temp
  swap(a, &temp) // aの値を変数tempに入れる
  swap(b, &temp) // 変数tempにあるaの値をbに入れる, bの値を変数tempに入れる
  swap(c, &temp) // 変数tempにあるbの値をcに入れる, cの値を変数tempに入れる
  swap(a, &temp) // 変数tempにあるcの値をaに入れる, aにある元々tempの値を変数tempに還元する
}
```

ちょっと脱線しましたが、本題に戻ります。`GF`の`性質2.`を活用したら、上層の上右前のコーナーピースAが下層の`Temp`ピースと交換し、退避されたイメージですね。
さて、例えば上層のコーナーピースA B Cを順次場所交換したいなら、4つのswap

```
A <=> Temp
B <=> Temp
C <=> Temp
A <=> Temp
```

を順次実行すればいいですね。ルービックキューブ言語に翻訳すると、A,B,C,Aに対して順次に`GF`を実行してあげればいいです。

ここまで読んだ方の中には、次の疑問を持つ方もいらっしゃるのではないでしょうか？
> A,B,Cは順次に変えられますしTempも元の位置に戻れますが、他のピースはバラバラになりませんか？

答えは、大丈夫です。
`GF`の優れている`性質1.`を振り返りましょう。偶数回実行したら、元に戻ります!

実行時のコツは上層のA,B,C,Aに対して`GF`を実行する時、他の層の相対位置は変わらないことです。
言い換えると、GFを実行する前に、対象コーナーピースを同じ場所(例:上右前)に持ってこないといけません。

つまり、他のピースを影響しないで、上層のA,B,CをA=>B=>C=>A順番でシフトする時、以下のように実行すればいいです。

1. Aを上右前に置く
1. `GF`を実行
1. Bを上右前に置く
1. `GF`を実行
1. Cを上右前に置く
1. `GF`を実行
1. Aを上右前に置く
1. `GF`を実行

さて、効果を確認しましょう。  -> [[デモ]](https://alg.cubing.net/?alg=(R-_D2_R).U-.(R-_D2_R).U-.(R-_D2_R).U2.(R-_D2_R)&stage=LL&type=alg&view=playback&title=Permute%20Corners%20by%20GF)

### エッジピースにも活用

考え方は理解したら、同じ方法をエッジピースの場所交換にも簡単に展開できますね。
ちょっとだけ改造した(GF for Edge)略称GFE -> [[デモ]](https://alg.cubing.net/?alg=(R-_E2_R).U-.(R-_E2_R).U-.(R-_E2_R).U2.(R-_E2_R)&stage=LL&type=alg&title=Permutate%20Edges%20by%20GFE&view=playback)
を使いかえたらOK！

ただ半周回す層を従来の下層から中間層に変えただけですね。(Simple is beautiful)


### 3x3x3 => NxNxN

Nが大きいほど難しいイメージですが、手順のステップ数は確かに増えますが、実は難しさは割と収まってそれ以上増えません。

前述の`GF`や`GFE`は汎用的な方法なので、全部適用できます。

9x9x9のコーナーピース場所交換 -> [[デモ]](https://alg.cubing.net/?alg=R-_D2_R%0AU-%0AR-_D2_R%0AU-%0AR-_D2_R%0AU2%0AR-_D2_R%0A&title=Gold%20Finger%20(high%20layers)&puzzle=9x9x9&type=alg&view=playback)
10x10x10のエッジピース場所交換 -> [[デモ]](https://alg.cubing.net/?alg=R-_3%26%2345%3B3d2_R%0AU-%0AR-_3%26%2345%3B3d2_R%0AU-%0AR-3%26%2345%3B3d2_R%0AU2%0AR-_3%26%2345%3B3d2_R%0A&title=Gold%20Finger%20Corner%20(high%20layers)&puzzle=10x10x10&type=alg&view=playback)

### ピースの向きを回転

`GF`を用いて、3つのピースを向き変えずに場所交換することが確かにできますが、ピース向き回転をどうすればいいですかね。
前述までは右手の層で`GF`を実行しただけですが、実は、どの層で実行しても`GF`の基本性質は変わりません。
例えば、鏡に映ったように、前層でやる`GF Mirrored`(略称`GFM`)鏡像操作も前述のすべてのことができます。 -> [[デモ]](https://alg.cubing.net/?alg=(F_D2_F-).U-.(F_D2_F-).U-.(F_D2_F-).U2.(F_D2_F-)&stage=LL&type=alg&title=Gold%20Finger%20Mirrored)

回転の実現方法のポイントは、
**`GF`で退避したピースを`GFM`で別方向から持って返せばいいです。**
もちろん他のピースに影響しないように、もう一回順に`GFM`と`GF`を実行しなければなりません。

つまり、他のピースに影響しないで、上層のコーナーピースA,Bを向き回転(A反時計回り、B時計回り)する時、以下のように実行すればいいです。

1. Aを上右前に置く
1. `GF`を実行してTempに退避する
1. `GFM`を実行してTempから持って返す
1. Bを上右前に置く
1. `GFM`を実行
1. `GF`を実行

さて、効果を確認しましょう。  -> [[デモ]](https://alg.cubing.net/?alg=(R-_D2_R).(F_D2_F-).U-.(F_D2_F-).(R-_D2_R).U&stage=LL&type=alg&title=Orientate%20by%20GF%20and%20GFM&view=playback)

もちろん、エッジピースの向き回転も似たようなやり方で簡単にできます。それを割愛します。
また、上層のA,B,C配置によって、GFとGFMを使って場所交換と向き回転の二重効果を同時に得ることも可能です。興味があったら、ぜひチャレンジしてみてください。


## 結論

ルービックキューブは怖くありません。最も基本な場所交換と向き回転ができれば、それを組み合わせてNxNxNでも解けます。
複雑の問題を簡単化する方法論を念頭に置けば、どんな難問でも解ける自信を身に付けます。
僕はこれからもいろいろチャレンジし続けたいと思います。

**最後に、メリークリスマス～ 良いお年を〜**:christmas_tree::christmas_tree::christmas_tree::tada::tada::tada:


![merry_xmas.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120601/800aba42-19c0-4ea1-e78b-1e64b6eb99de.gif)