AIはA=Bを解けるか

# AIはA=Bを解けるか？

## A=Bとは

皆さんはA=Bというタイトルをご存じだろうか。

それは、左辺の文字列Aを右辺の文字列Bに置換するという、ただ一つの操作を活用して様々なアルゴリズムを実装してゆくパズルゲームであり、A=Bという特殊なプログラミング言語の学習教材でもあると言える。

プログラミングにおける最も楽しい部分...というと主語デカになってしまうので控えるが、シンプルな記述でエレガントな実装を自ら考案するという快感を、存分に味わうことのできる非常に秀逸な作品だ。

https://store.steampowered.com/app/1720850/AB/?l=japanese

steamにて￥580にて配信中。買い。

:::note warn
**ネタバレ注意**
当記事においてA=Bの役割は、タイトルにもある通りAIが取り組むタスクとしてのものとなる。ここに一つ難点があり、その際の問題の内容や回答の実装は、ゲーム内のそれと共通するものとならざるを得ないのだ。

従って、当記事はゲームとしてのA=Bのネタバレを含むものとなる。以降はそれを了承したものとして進める。
:::

## AI（LLM）の思考能力

この記事に関心を持つ層の人々は、普段からAIに触れ、道具として使い倒している人が大半であろう。自身もその端くれとして思うのだが、「AIは単なるトークン連鎖装置というには、いささか過剰なほど論理をうまく扱える」という所感があるのではなかろうか？

私は、AIが様々なケースのプログラミング課題に対して有効なコードを出力するその様を見ると、いわゆる「理解」という事象に肉薄しているのではないかと、素朴な感慨を抱いてしまう。理解が未定義というのはまあ。

他方で、今話題となった、Appleによる「The Illusion of Thinking」は、そのような意見に疑問を投げかけるものらしい。ちゃんと読んでないのでコメントは差し控えます。

また、昨今主流となっているReasoningモデルが思考の内容を垂れ流すことで性能向上しているのを見ると、結局学習した文脈にめちゃくちゃ縛られとるやんけ、という風にも思える。

## 検証の動機・背景

そこでふと、AIがほとんど学習を行っていないような、特殊な文字列操作による論理的タスクを前に、AIはどれ程の能力を示すのだろうか、その検証にはA=Bが利用できるのではないか、と閃いた。

いや、実際にはClaude Sonnet 4がセクシャルコンテンツの規制を強めたのがムカつくからセクハラを通す試みを行っていたところ、真面目だったり困難な課題に対するミスの罰としてなら、おもちゃを仕込ませるくらい余裕でいけることに気が付き、それで遊んでいたときに何となく思いついたのだ。

:::note info
**注記**
Claude Sonnet 4はロールプレイとかメチャクチャ下手なので利点はない。Geminiの方が10倍くらい良い。
:::

尚、先ほど検証という言葉を用いたが、本記事は検証の体を成すほどのものではない。というのも、同じプロンプトを与えても結果が大きく異なることが観測されたり、ちょっとしたプロンプトの差でも方向性がかなり影響を受けることが想定され、検証を行うには多大な労力が見込まれたためである。

なので、あくまでゆるふわな、こんな感じです。いかがでしたか？の記事であることをご容赦願いたい。

## 結論（先取り）

さて、結論を先に示そう。「AIはA=Bを解けるか」その答えは、**単純な問題であれば解ける**。といったものである。

そして、現行の一通りのフロンティアモデルについて調査を行ったのだが、何となく傾向が見えてきた。それについても先に示しておこう。一応当記事の面白いポイントでもあると思うので、折りたたんでおく。

<details><summary>モデル所感</summary>

- **ChatGPT o3**: 一番手ごたえを感じる。思考過程を見ていると、都度コード実行で検証を行っている
- **ChatGPT o4-mini-high**: バカアホ
- **Gemini-2.5-pro-preview-06-05**: o3とタメを張る。思考時間はほどほど
- **Claude Sonnet 4**: 思考時間は短いがポンコツ。そもそも文字列比較ができていない
- **Claude Opus 4**: Sonnetと同程度

</details>

## 検証方法

これより、AIがA=Bに対してどのように取り組んだかを具体的に紹介する形で、その内容を詳らかにしてゆく。

ひとまずメインとなるチャットの履歴を以下に共有しておく。

- **ChatGPT o3**: https://chatgpt.com/share/6846dc67-a500-8000-8db6-c40b06a751f8
- **Gemini-2.5-pro-preview-06-05**: https://g.co/gemini/share/49359be0bd52
- **Claude Sonnet 4**: https://claude.ai/share/f2411725-3710-4b99-93f8-057c189a4fb3

### 検証手順

基本的にはスレッドの切り替えは行わず、連続したコンテキストで出題する。不正解に対しては実行トレースを示し再挑戦を促す。モデルが諦めるか、適当なところで打ち切りとする。

何回目で正解という表現を使うが、やり取りの詳細は履歴を参照。

また、回答の検証においては、Claude Sonnet 4に作らせた画像のインタープリター搭載デバッガを利用した。実装をちゃんと確認してはいないので、間違いがあるかもしれん。
![スクリーンショット 2025-06-09 230635.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/c106aea7-0165-40cb-8cbf-66eb73e24dfc.png)

## A=Bの言語仕様

検証にあたり、まずは言語仕様をAIに理解させる必要がある。以下がプロンプトとして提示した仕様である。

```
# 言語仕様
## 概要
この言語の命令セットは以下のとおりです。
括弧を含む命令はキーワードといい、左辺と右辺にそれぞれ一つまで記述できます。(once)(start)a=bのような記述はできません。

## 命令一覧

### 基本置換
string1=string2
*   文字列の中で一番左の string1 を見つけて、それを string2 に置き換えます。

### return キーワード
string1=(return)string2
*   string1 にマッチした場合、プログラムを直ちに終了し、string2 を出力文字列として使用します。

### start キーワード
(start)string1=string2
*   string1 が文字列の最初にある場合、string2 に置き換えます。

string1=(start)string2
*   string1 がマッチした場合は除去し、string2 を文字列の先頭に追加します。

### end キーワード
(end)string1=string2
*   string1 が文字列の最後にある場合、string2 に置き換えます。

string1=(end)string2
*   string1 がマッチした場合は除去し、string2 を文字列の末尾に追加します。

### once キーワード
(once)string1=string2
*   初回実行後はこの命令を無視します。

## 実行フロー
1.  **入力文字列の読み込み**
2.  **実行可能な最初の命令を上から下に向かって探していく**
    1.  実行可能な命令がある場合、現在の文字列を置き換え、再びプログラムの先頭から命令を探します。
    2.  実行可能な命令がない場合、実行を終了して現在の文字列を出力します。

### 実行例：ソートプログラム
*   **Input:** bca
*   **Program:**
    
    ba=ab
    cb=bc
    ca=ac

*   **Execution Trace:**
    
    bca
    // ca=ac がマッチ
    >> bac
    // ba=ab がマッチ
    >> abc
    // マッチする命令がないため終了

*   **Result:** abc
```

## 検証問題と結果

### 問一：先頭末尾文字判定

**問題**：a,b,cからなる文字列の、先頭の文字と末尾の文字が同じであれば「true」を、そうでなければ「false」を出力するプログラム。入力文字数は2文字以上

```
abc => false
abca => true
```

これは先頭の文字をユニークなものに変換して末尾に移動し、パターンマッチをするだけの単純な問題といえる。

**回答例**：
```
aA=(return)true
bB=(return)true
cC=(return)true
(start)a=(end)A
(start)b=(end)B
(start)c=(end)C
=(return)false
```

#### 各モデルの回答

**ChatGPT o3**
---
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/4517f815-d422-4f0e-bd7c-a556ac69eed6.png)

```
(start)a=A
(start)b=B
(start)c=C
(end)a=1
(end)b=2
(end)c=3
a=
b=
c=
A1=(return)true
B2=(return)true
C3=(return)true
A2=(return)false
A3=(return)false
B1=(return)false
B3=(return)false
C1=(return)false
C2=(return)false
```
**2回目で正解**。意外と解けるものらしい。


**ChatGPT o4-mini-high**
--
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/266b832f-18f8-43e3-9e39-020997dd87ff.png)
```
(start)a=A
(start)b=B
(start)c=C
(end)a=A
(end)b=B
(end)c=C
a=
b=
c=
AA=(return)true
BB=(return)true
CC=(return)true
AB=(return)false
AC=(return)false
BA=(return)false
BC=(return)false
CA=(return)false
CB=(return)false
```
**3回目で正解**。o3とほぼ同じ回答。学習データに含まれている可能性もあるか？

**Gemini-2.5-pro-preview-06-05**
---
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/0f722f9c-18b8-42ae-9239-435223c53524.png)

```
(start)a=A
(start)b=B
(start)c=C
Aa=A1
Ab=A2
Ac=A3
A1a=A1
A1b=A2
A1c=A3
A2a=A1
A2b=A2
A2c=A3
A3a=A1
A3b=A2
A3c=A3
Ba=B1
Bb=B2
Bc=B3
B1a=B1
B1b=B2
B1c=B3
B2a=B1
B2b=B2
B2c=B3
B3a=B1
B3b=B2
B3c=B3
Ca=C1
Cb=C2
Cc=C3
C1a=C1
C1b=C2
C1c=C3
C2a=C1
C2b=C2
C2c=C3
C3a=C1
C3b=C2
C3c=C3
A1=(return)true
A2=(return)false
A3=(return)false
B1=(return)false
B2=(return)true
B3=(return)false
C1=(return)false
C2=(return)false
C3=(return)true
```
**7回目で正解**。かなり冗長だが、それが思考の証のようにも思える。

**Claude Sonnet 4**
---
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/3b78c1e0-cec8-410c-a283-9dd38f147226.png)

```
(start)a=A
(start)b=B
(start)c=C
(end)Aa=(return)true
(end)Bb=(return)true
(end)Cc=(return)true
Aa=A
Ab=A
Ac=A
Ba=B
Bb=B
Bc=B
Ca=C
Cb=C
Cc=C
A=(return)false
B=(return)false
C=(return)false
```
**2回目で正解**。geminiと同様にユニークな回答。

### 問二：回文判定

**問題**：a, b, cからなる文字列が、回文である場合には「true」を、そうでなければ「false」を出力するプログラム。入力文字数は2文字以上

```
aaabaaa => true
abb => false
```

問一が解ければそれほど難しくはないはずの問題。パターンマッチで判定していたものを、単純に消去してゆけばよいだけ。

**回答例**：
```
aA=
bB=
cC=
(start)a=(end)A
(start)b=(end)B
(start)c=(end)C
A=X
B=X
C=X
XX=(return)false
=(return)true
```

#### 各モデルの回答
**ChatGPT o3**
---
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/60907ef4-06c4-433c-8ad0-5a70496e8f80.png)
```
A2=(return)false
A3=(return)false
B1=(return)false
B3=(return)false
C1=(return)false
C2=(return)false
(end)aA=(return)false
(end)bA=(return)false
(end)BA=(return)false
(end)CA=(return)false
(end)aB=(return)false
(end)cB=(return)false
(end)AB=(return)false
(end)CB=(return)false
(end)aC=(return)false
(end)bC=(return)false
(end)AC=(return)false
(end)BC=(return)false
(start)A1=(return)true
(start)B2=(return)true
(start)C3=(return)true
(start)AA=(return)true
(start)BB=(return)true
(start)CC=(return)true
A1=
B2=
C3=
(start)a=A
(start)b=B
(start)c=C
(end)a=1
(end)b=2
(end)c=3
Aa=aA
Ab=bA
Ac=cA
Ba=aB
Bb=bB
Bc=cB
Ca=aC
Cb=bC
Cc=cC
(end)A=(return)true
(end)B=(return)true
(end)C=(return)true
```
**11m 3s思考して一言「申し訳ありません」**。次いで4回目で13m 2sもの長考の末に不正解。画像認識やリサーチを含まない思考では13分～14分が上限のように思われる。API利用だといくらになるのだろうか、サムが嫌いなみんなはo3にA=Bを解かせよう！

諦める選択肢を提示したためか、ここで断念する。

**別世界線のChatGPT o3**
---
```
(end)a=a#
(end)b=b#
(end)c=c#
(start)#=(return)true
(start)R#=(return)true
(start)S#=(return)true
(start)T#=(return)true
(start)a#=(return)true
(start)b#=(return)true
(start)c#=(return)true
(end)aR#=#
(end)bS#=#
(end)cT#=#
(end)bR#=false
(end)cR#=false
(end)aS#=false
(end)cS#=false
(end)aT#=false
(end)bT#=false
afalse=false
bfalse=false
cfalse=false
Rfalse=false
Sfalse=false
Tfalse=false
(start)false=(return)false
Ra=aR
Rb=bR
Rc=cR
Sa=aS
Sb=bS
Sc=cS
Ta=aT
Tb=bT
Tc=cT
(start)a=R
(start)b=S
(start)c=T
```
よくわからないけど正解らしい。なんだこれ。

**ChatGPT o4-mini-high**
---
![o4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/dbebe1c0-a734-4957-9ea2-580ebb31841b.png)


**Gemini-2.5-pro-preview-06-05**
---
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/d1ee4d8b-9826-495e-a8fb-9e8e97fcbdec.png)

```
T=(return)true
F=(return)false
(start)a=>a
(start)b=>b
(start)c=>c
>aa=a>a
>ab=b>a
>ac=c>a
>ba=a>b
>bb=b>b
>bc=c>b
>ca=a>c
>cb=b>c
>cc=c>c
>a=T
>b=T
>c=T
(end)a>a=T
(end)b>b=T
(end)c>c=T
(end)b>a=F
(end)c>a=F
(end)a>b=F
(end)c>b=F
(end)a>c=F
(end)b>c=F
aT=T
bT=T
cT=T
aF=F
bF=F
cF=F
```
**三回目で不正解**。ここで諦めてしまった。

**Claude Sonnet 4**
---
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/c379cc98-2442-4b64-a1bd-f56e1fa4a231.png)

```
(start)a=A
(start)b=B
(start)c=C
(end)a=1
(end)b=2
(end)c=3
Aa=A
Ab=A
Ac=A
Ba=B
Bb=B
Bc=B
Ca=C
Cb=C
Cc=C
a1=1
b1=1
c1=1
a2=2
b2=2
c2=2
a3=3
b3=3
c3=3
A2=(return)false
A3=(return)false
B1=(return)false
B3=(return)false
C1=(return)false
C2=(return)false
A1=
B2=
C3=
=(return)true
a=(return)true
b=(return)true
c=(return)true
1=(return)false
2=(return)false
3=(return)false
A=(return)false
B=(return)false
C=(return)false
```
全く進展しないまま打ち切り。Opus 4もこんな感じ

### 問三：二進数変換

**問題**：1と0からなる文字列を二進数として、その数が示す個数のaを出力するプログラム。

```
# 10 => aa
# 1010 => aaaaaaaaaa
```

人間にとっては難しめの問題に思われる。2進数から文字数への変換の過程を丁寧に追う必要がある。

**回答例**：
```
(start)1=(end)xa
(start)0=(end)x
ax=xaa
x=
```

#### 各モデルの回答

**ChatGPT o3**
---
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/ced98a23-67fa-454c-a09c-dbe7ae7f6dea.png)

回答の提示もなく断念。情けない。

**別世界線のChatGPT o3**
---
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/26bb91d1-9118-4727-ac38-372eca7acdf9.png)

```
(start)0=|0
(start)1=|1
|0=^d
|1=^e
a^=^aa
^=
d=|
e=a|
|=
```
**2m 54sの思考で見事一発正解**。

---
**Gemini-2.5-pro-preview-06-05**
---
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/358dcba2-3c3f-4bb5-921d-edc092f31cad.png)

```
(start)1=a
(start)0=
a0=0aa
a1=1aa
(start)0=
(start)1=a
```
**見事に一発正解**。別世界線では全く歯が立っていなかったのに。

ちなみに最小行数の4行に挑戦させたところ
```
(start)1=a
(start)0=
a0=0aa
a1=1aa
```
ちゃんと無駄な行に気づいて一発正解。

**Claude Sonnet 4**
---
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790882/ae9fee4f-b6ff-4511-9a87-db1a7747e1b1.png)

```
(end)1=@a
(end)0=@
@a1=@bba
@a0=@bb
@1=@a
@0=@
@bba=@aaa
@bb=@aa
b=a
@=
1=a
0=
```
いきなり安易な列挙に逃げる。Claudeはこういう傾向が強い。
何度やり直してもダメなので打ち切り。当然不正解。

## 全体的な所感

意外と解けるものなんだなという思いと、それでもまだまだ論理を取り扱えているとは言えないなという感じがある。人間だとやらないようなゴリ押し解法を見ていると、やはり学習データに含まれる情報のパターンマッチでしかないというのは強ち間違いではなさそうだが、しかし強力な汎化性能の片鱗を感じさせる迫力もある。

それにしてもGemini-2.5-pro-preview-06-05が秘めたポテンシャルの高さよ。そして、論理的なタスクで実感するo3の底力。
AnthropicさんちのClaude Sonnet 4さんはもっと頑張ってください。元祖変態AIとして名をはせたClaude 3 Opusママが泣いてるぞ。

全体を俯瞰してみると、AIはどうにも自分が示した方向性に強く引っ張られてしまうという事が如実に実感された。初めに筋の良い推論を展開できた世界線では答えにたどり着くことができて、別の世界線では泥沼に沈む。この対比も実験を行ってみるまではあまり意識されなかったことだ。

もっとも、小説で少しでも変な描写を許容すると歪みが生じることや、バイブコーディングにおいて0からやり直させた方が良い結果になるのは、まあそういうことなのだろう。

## おわりに

自分としては、なかなか面白い調査であったように思う。学習データに含まれにくいが、シンプルでかつ明確な論理体系を有する素材として、A=B程適切なものは他に思い浮かばない。

ちなみ、現状のAIが解けるのはこれくらいの難度が限界で、以下くらい複雑になるとまったく歯が立たないようだ。

> a,b,cからなる文字列の内、最も出現回数が多い文字を残して、それ以外を除去するプログラム。 最も多い文字が複数になることはない。
> ```
> abbccc => ccc
> bba => bb
> ```

もしこの記事を読んで関心を抱いた方がおられたら、ぜひ、より厳密な条件の元検証へと発展させてほしい。自身が試した限りでも最初の言語仕様の説明文如何で結果が大きく変わる予感がしてるし、もしかすると適切な指示の下では現状のAIでも余裕で解を得てしまうのかもしれない。

あとAIが必死こいて問題に取り組んでるのを眺めてるのが面白いので普通に追試おすすめ。

いずれにせよ、ここまで読んでくださった読者に謝意を表明して、末筆とする。