「 現代の Excel は チューリング完全らしいですしね」
「 じゃあ Excel で チューリング・マシンを作るのか?
無限のテープをどう表現する?」
[TuringMachineByExcelVBA.xlsm] file - [StateTable] sheet
:
State,Read,Write,Move,Transition
A,White,Orange,>,B
A,Orange,Orange,<,C
B,White,Orange,<,A
B,Orange,Orange,>,B
C,White,Orange,<,B
C,Orange,Orange,>,HALT
「 👆 とりあえず StateMachine
シートを作れだぜ。
セルに色も塗れだぜ」
[TuringMachineByExcelVBA.xlsm] file - [Tape] sheet
:
A
「 👆 もう1つ、 Tape
シートを作れだぜ。
A
の1文字だけ入っている」
「 空っぽの GUI
というシートを作って、
メインメニューから [開発] - [コードの表示]
を選べだぜ」
「 👆 何だか よくわからないが ボタン1_Click
という名前はそのまんまで
マクロの保存先を 今作業中のファイルに変えて、 [新規作成(N)]
ボタンを押そうぜ?」
「 プログラマーは 記憶 ではなく、 読み で進むのよ。
その方が 応用が利くから」
「 当たった とか 講師から出てきたらおかしい言葉 わらう」
「 👆 ボタンを右クリックして コンテキスト・メニューの [マクロの登録(N)]
を
クリックしてみようぜ?」
「 👆 何をすればいいのか分からん。 [OK]
ボタンを押してみようぜ?」
「 よっしゃ!
じゃあ そこに VBA Script (ぶい・びー・えー・すくりぷと)を書けばいいんだぜ」
📅 2023-01-25 wed 20:41
📖 セルに値を入れる:Excel VBA プログラミング入門
Worksheets("GUI").Range("A1").Value = "Hello, world!!"
「 👆 こんな感じに書けば GUI
シートの A1
セルに Hello, world!!
という文字を
入れてくれそうだな」
「 Excelでハローワールドを出力する
の実績を解除したな」
Worksheets("GUI").Range("A1").Interior.ColorIndex = 45 ' オレンジ
「 👆 こんな感じに書けば GUI
シートの A1
セルの背景色をオレンジ色に
してくれそうだな」
「 👆 じゃあ、 StateTable
シートの C2 セルの背景色が何色かとか、取得することはできるのかだぜ?」
📖 VBA セルの色を取得する (Interior.Color, ColorIndex)
Dim backgroundColor As Long
backgroundColor = Worksheets("StateTable").Range("C2").Interior.color ' 背景色
Debug.Print (backgroundColor)
Worksheets("GUI").Range("A1").Interior.color = backgroundColor
「 👆 こう書けば StateTable
シートの C2
セルの背景色を、 GUI
シートの A1
セルへ コピーできるはずだぜ!」
「 👆 背景色は コピーでけたが……。
Debug.Print( ... )
って何だぜ?」
📖 【エクセルVBA】初心者のうちから知っておくべきDebug.Printの使い方
「 👆 イミディエイト・ウィンドウ に値を表示するらしいぜ」
「 [Ctrl] + [G]
キーを打鍵すると 出てくるウィンドウだぜ」
「 そんなウィンドウの出し方、 画面のどこを探しても 無くね?」
「 コンピューター開発者は 私には分かる。だからお前も分かるだろ
という脳をしてる人 多いのよ。
伝え、継承する精神を持っている人は リタイア組ぐらいよ」
「 天才が 技術を継承するの 損だしな。
ネット上で 記事書いてるの リタイア組か、 業界が滅ぶ一歩手前で しかたなく 天才のケツ掃除してる人たちの どっちかだよな」
「 しかし 49407
なんて数字出てきても 嬉しくないな」
📅 2023-01-25 wed 21:36
「 じゃあ 次は長めの コンボ(Combo;連続技) やるから よく聴けだぜ」
「 👆 Tape
シートの A1
セルに入っている値 A
と、その背景色 白色 を取得して……」
「 👆 StateTable
シートの State
列に A
が、
Read
列に 背景色が白色のセルが
無いかなと探し……」
「 👆 そのまま 横へスライドし、
Write列 の背景色は オレンジ色、
Move列 は >
、
Transition列 は B
と いったん覚え……」
「 👆 Tape
シートを開き、
A1 セルから 1行下にいったところを、 Write 列にあるように オレンジ色 に塗り、
Move列が >
とあるように その右側に対して、
Transition列があるように B
を書き込もうぜ?」
「 いったん TuringMachineByExcelVBA.xlsm
ファイルを保存して閉じるぜ。
休憩だぜ」
📅 2023-01-25 wed 22:10 stop
📅 2023-01-25 wed 22:21 restart
「 よっしゃ 再開だぜ!
TuringMachineByExcelVBA.xlsm
ファイルを開けて、っと」
「 ファイルを開けるには、ダブル・クリック するんじゃないの?」
「 じゃあ Tape
シートの A1
セルの値 A
と背景色 白色 を取得して、
そのタプル(Tuple;組み)が StateTable
シートの何行目にあるか探し出して
イミディエイト・ウィンドウに デバッグプリント するところまで やりましょう!」
Sub ボタン1_Click()
Dim text As String
Dim backgroundColor As Long
text = Worksheets("Tape").Range("A1").Value ' セルの値
backgroundColor = Worksheets("Tape").Range("A1").Interior.color ' 背景色
Debug.Print (text)
Debug.Print (backgroundColor)
Worksheets("GUI").Range("A1").Value = text
Worksheets("GUI").Range("A1").Interior.color = backgroundColor
End Sub
「 👆 値と 背景色のコピーは できるようになったが、
次は 探すというやつだな」
「 👆 多分 StateTable
シートを 1行目から 7行目まで読むのは こんな雰囲気だろ。
VBA の if 文ってどうやって書くんだったかな?」
📖 ExcelのVBA(マクロ)でIf~Then~Elseを使って条件分岐する方法
「 👆 多分 if文は こんな雰囲気だろ。
Forループを途中で抜けるの VBAで どうやって書くんだったかな?」
Sub ボタン1_Click()
Dim text As String
Dim backgroundColor As Long
text = Worksheets("Tape").Range("A1").Value ' セルの値
backgroundColor = Worksheets("Tape").Range("A1").Interior.color ' 背景色
Debug.Print (text)
Debug.Print (backgroundColor)
Worksheets("GUI").Range("A1").Value = text
Worksheets("GUI").Range("A1").Interior.color = backgroundColor
Dim i As Long
Dim stateText As String
Dim readBackgroundColor As Long
Dim writeBackgroundColor As Long
Dim moveText As String
Dim transitionText As String
For i = 2 To 7
stateText = Worksheets("StateTable").Range("A" & i).Value ' セルの値
readBackgroundColor = Worksheets("StateTable").Range("B" & i).Interior.color ' 背景色
' 一致するか?
If text = stateText And backgroundColor = readBackgroundColor Then
writeBackgroundColor = Worksheets("StateTable").Range("C" & i).Interior.color ' 背景色
moveText = Worksheets("StateTable").Range("D" & i).Value ' セルの値
transitionText = Worksheets("StateTable").Range("E" & i).Value ' セルの値
Debug.Print (writeBackgroundColor)
Debug.Print (moveText)
Debug.Print (transitionText)
' TODO 次の処理へ
Exit For
End If
Next i
End Sub
📅 2023-01-25 wed 23:00
「 次は、
Tape
シートの A1 セルを スタート地点として、
1行 下りたセルの背景色を Write列のいう色に塗って、そこから
Move 列が >
だったら その右のセルへ、 Transition 列のいうテキストを入れましょう」
「 👆 Tape
シートの2行目を クリアーしておくぜ。
そして GUI
シートのボタンを押すぜ」
📅 2023-01-25 wed 23:21
「 👆 B2 セルをスタート地点として、 同様に さっきと同じことを やればいいんだぜ」
「 👆 文字が B
で、背景色が 白色 なのは 4行目だな。
下にオレンジ塗って 左へ A を書けばよさそうだな」
「 👆 説明するのを忘れていたが、上の行の背景色を、下の行へ 引き継ぐぜ」
Sub ボタン1_Click()
Dim text As String
Dim backgroundColor As Long
Dim i As Long
Dim stateText As String
Dim readBackgroundColor As Long
Dim writeBackgroundColor As Long
Dim moveText As String
Dim transitionText As String
' 1回目の処理
text = Worksheets("Tape").Range("A1").Value ' セルの値
backgroundColor = Worksheets("Tape").Range("A1").Interior.color ' 背景色
For i = 2 To 7
stateText = Worksheets("StateTable").Range("A" & i).Value ' セルの値
readBackgroundColor = Worksheets("StateTable").Range("B" & i).Interior.color ' 背景色
' 一致するか?
If text = stateText And backgroundColor = readBackgroundColor Then
writeBackgroundColor = Worksheets("StateTable").Range("C" & i).Interior.color ' 背景色
moveText = Worksheets("StateTable").Range("D" & i).Value ' セルの値
transitionText = Worksheets("StateTable").Range("E" & i).Value ' セルの値
' `Tape` シートの A1 セルの下のセルの背景色を Write列のいう色に塗る
Worksheets("Tape").Range("A2").Interior.color = writeBackgroundColor
' Move 列が `>` だったら その右のセルへ、 Transition 列のいうテキストを入れる
If moveText = ">" Then
Worksheets("Tape").Range("B2").Value = transitionText
End If
Exit For
End If
Next i
' TODO ★ 同様の2回目の処理
text = Worksheets("Tape").Range("B2").Value ' セルの値
backgroundColor = Worksheets("Tape").Range("B2").Interior.color ' 背景色
' ★ 上の行の背景色は引き継ぐ
Worksheets("Tape").Range("A3").Interior.color = Worksheets("Tape").Range("A2").Interior.color
Worksheets("Tape").Range("B3").Interior.color = Worksheets("Tape").Range("B3").Interior.color
For i = 2 To 7
stateText = Worksheets("StateTable").Range("A" & i).Value ' セルの値
readBackgroundColor = Worksheets("StateTable").Range("B" & i).Interior.color ' 背景色
' 一致するか?
If text = stateText And backgroundColor = readBackgroundColor Then
writeBackgroundColor = Worksheets("StateTable").Range("C" & i).Interior.color ' 背景色
moveText = Worksheets("StateTable").Range("D" & i).Value ' セルの値
transitionText = Worksheets("StateTable").Range("E" & i).Value ' セルの値
' `Tape` シートの A1 セルの下のセルの背景色を Write列のいう色に塗る
Worksheets("Tape").Range("B3").Interior.color = writeBackgroundColor
' ★ Move 列が `<` だったら その左のセルへ、 Transition 列のいうテキストを入れる
If moveText = "<" Then
Worksheets("Tape").Range("A3").Value = transitionText
End If
Exit For
End If
Next i
End Sub
📅 2023-01-25 wed 23:51 end
「 VBA でサブルーチンは どうやって書いたらいいんだぜ?」
📖 Excel VBA 処理の一部をサブルーチン化するCallステートメント
「 👆 スケルトン(Skeleton;穴埋めの穴じゃない方)を書こうぜ」
「 👆 スケルトンの中へ コードを こうやって 入れたらいいんじゃないかだぜ?」
「 👆 移動した跡の所には コール文(Call Statement)を置いておこうぜ?」
Sub ボタン1_Click()
' 1回目の処理
Call On1stClock
' 同様の2回目の処理
Call On2ndClock
End Sub
Private Sub On1stClock()
' 1回目のクロック
Dim text As String
Dim backgroundColor As Long
Dim i As Long
Dim stateText As String
Dim readBackgroundColor As Long
Dim writeBackgroundColor As Long
Dim moveText As String
Dim transitionText As String
text = Worksheets("Tape").Range("A1").Value ' セルの値
backgroundColor = Worksheets("Tape").Range("A1").Interior.color ' 背景色
For i = 2 To 7
stateText = Worksheets("StateTable").Range("A" & i).Value ' セルの値
readBackgroundColor = Worksheets("StateTable").Range("B" & i).Interior.color ' 背景色
' 一致するか?
If text = stateText And backgroundColor = readBackgroundColor Then
writeBackgroundColor = Worksheets("StateTable").Range("C" & i).Interior.color ' 背景色
moveText = Worksheets("StateTable").Range("D" & i).Value ' セルの値
transitionText = Worksheets("StateTable").Range("E" & i).Value ' セルの値
' `Tape` シートの A1 セルの下のセルの背景色を Write列のいう色に塗る
Worksheets("Tape").Range("A2").Interior.color = writeBackgroundColor
' Move 列が `>` だったら その右のセルへ、 Transition 列のいうテキストを入れる
If moveText = ">" Then
Worksheets("Tape").Range("B2").Value = transitionText
End If
Exit For
End If
Next i
End Sub
Private Sub On2ndClock()
' 2回目のクロック
Dim text As String
Dim backgroundColor As Long
Dim i As Long
Dim stateText As String
Dim readBackgroundColor As Long
Dim writeBackgroundColor As Long
Dim moveText As String
Dim transitionText As String
text = Worksheets("Tape").Range("B2").Value ' セルの値
backgroundColor = Worksheets("Tape").Range("B2").Interior.color ' 背景色
' ★ 上の行の背景色は引き継ぐ
Worksheets("Tape").Range("A3").Interior.color = Worksheets("Tape").Range("A2").Interior.color
Worksheets("Tape").Range("B3").Interior.color = Worksheets("Tape").Range("B3").Interior.color
For i = 2 To 7
stateText = Worksheets("StateTable").Range("A" & i).Value ' セルの値
readBackgroundColor = Worksheets("StateTable").Range("B" & i).Interior.color ' 背景色
' 一致するか?
If text = stateText And backgroundColor = readBackgroundColor Then
writeBackgroundColor = Worksheets("StateTable").Range("C" & i).Interior.color ' 背景色
moveText = Worksheets("StateTable").Range("D" & i).Value ' セルの値
transitionText = Worksheets("StateTable").Range("E" & i).Value ' セルの値
' `Tape` シートの A1 セルの下のセルの背景色を Write列のいう色に塗る
Worksheets("Tape").Range("B3").Interior.color = writeBackgroundColor
' ★ Move 列が `<` だったら その左のセルへ、 Transition 列のいうテキストを入れる
If moveText = "<" Then
Worksheets("Tape").Range("A3").Value = transitionText
End If
Exit For
End If
Next i
End Sub
📅2023-01-26 thu 19:16
「 👆 何回目のクロックでも使えるジェネラル(General)なサブルーチンを作ろうぜ?」
「 👆 違うところは5か所ぐらいなんだから、ここを違わないようにすればいいわけだぜ」
「 A列の右隣は B列 だが、
A
の右は何か尋ねたら B
が返ってくるような方法って VBA にあるのかだぜ?」
📖 【ExcelVBA】列名のアルファベットと列番号の数字を相互変換する
Sub ボタン1_Click()
' 1回目の処理
Call OnClock("A", 1)
' 同様の2回目の処理
Call OnClock("B", 2)
End Sub
Private Sub OnClock(previousFileAlphabet As String, previousRank As Long)
' TODO 毎クロック(n回目のクロック)
Dim previousText As String
Dim previousBackgroundColor As Long
Dim previousCell As String
Dim currentRank As Long
Dim currentCell As String
Dim stateText As String
Dim readBackgroundColor As Long
Dim writeBackgroundColor As Long
Dim moveText As String
Dim transitionText As String
Dim i As Long
previousCell = previousFileAlphabet & previousRank
currentRank = previousRank + 1
currentCell = previousFileAlphabet & currentRank
Debug.Print ("--------")
Debug.Print ("previousFileAlphabet:" & previousFileAlphabet)
Debug.Print ("previousRank :" & previousRank)
Debug.Print ("previousCell :" & previousCell)
Debug.Print ("currentRank :" & currentRank)
Debug.Print ("currentCell :" & currentCell)
' 開始行の背景色は、次行に引き継ぐ
If 2 <= previousRank Then
Dim aBackgroundColor As Long
Dim bBackgroundColor As Long
aBackgroundColor = Worksheets("Tape").Range("A" & previousRank).Interior.color
bBackgroundColor = Worksheets("Tape").Range("B" & previousRank).Interior.color
Worksheets("Tape").Range("A" & currentRank).Interior.color = aBackgroundColor
Worksheets("Tape").Range("B" & currentRank).Interior.color = bBackgroundColor
Debug.Print ("aBackgroundColor:" & aBackgroundColor)
Debug.Print ("bBackgroundColor:" & bBackgroundColor)
End If
previousText = Worksheets("Tape").Range(previousCell).Value ' 開始セルの値
previousBackgroundColor = Worksheets("Tape").Range(previousCell).Interior.color ' 開始セルの背景色
Debug.Print ("previousText :" & previousText)
Debug.Print ("previousBackgroundColor:" & previousBackgroundColor)
For i = 2 To 7
stateText = Worksheets("StateTable").Range("A" & i).Value ' 状態テーブルのState値
readBackgroundColor = Worksheets("StateTable").Range("B" & i).Interior.color ' 状態テーブルのRead列の背景色
Debug.Print ("stateText :" & stateText)
Debug.Print ("readBackgroundColor :" & readBackgroundColor)
' 一致するか?
If previousText = stateText And previousBackgroundColor = readBackgroundColor Then
writeBackgroundColor = Worksheets("StateTable").Range("C" & i).Interior.color ' 状態テーブルのWrite列の背景色
moveText = Worksheets("StateTable").Range("D" & i).Value ' 状態テーブルのMove列の値
transitionText = Worksheets("StateTable").Range("E" & i).Value ' 状態テーブルのTransition列の値
Debug.Print ("writeBackgroundColor:" & writeBackgroundColor)
Debug.Print ("moveText :" & moveText)
Debug.Print ("transitionText :" & transitionText)
' `Tape` シートの A1 セルの下のセルの背景色を Write列のいう色に塗る
Worksheets("Tape").Range(currentCell).Interior.color = writeBackgroundColor
Dim horizontal As Long ' 水平方向
If moveText = ">" Then ' Move 列が `>` だったら その右のセルへ
horizontal = 1
ElseIf moveText = "<" Then ' Move 列が `<` だったら その左のセルへ
horizontal = -1
End If
Debug.Print ("horizontal:" & horizontal)
' Transition 列のいうテキストを入れる
Dim startFileNumber As Integer
Dim nextFileAlphabet As String
startFileNumber = Columns(previousFileAlphabet).Column
nextFileAlphabet = Split(Cells(1, startFileNumber + horizontal).Address, "$")(1)
Debug.Print ("startFileNumber :" & startFileNumber)
Debug.Print ("nextFileAlphabet:" & nextFileAlphabet)
Worksheets("Tape").Range(nextFileAlphabet & currentRank).Value = transitionText
Exit For
End If
Next i
End Sub
「 👆 けっこう 大がかりに 変えることになってしまったぜ」
📅2023-01-26 thu 21:12
「 👆 1クロック目と 2クロック目で違うところは、 スタート地点の列番号と、行番号だけだったということだぜ」
「 このように 2つのサブルーチンの差異が サブルーチンの外に押し出されたものを アーギュメント(Argument;実引数)と呼ぶ」
「 👆 A1
とか B2
というのは、1クロック前に居たセルだぜ。
だから 前の計算結果を もらうといい。
書き直そう」
「 VBA でファンクションは どうやって書いたらいいんだぜ?」
📖 VBA Functionプロシージャについて ~関数の解説と使用例~
Sub ボタン1_Click()
Dim resultCell As String
' 1回目の処理
resultCell = OnClock("A1")
' 同様の2回目の処理
resultCell = OnClock(resultCell)
End Sub
Private Function OnClock(previousCell As String) As String
' 毎クロック(n回目のクロック)
Dim previousText As String
Dim previousBackgroundColor As Long
Dim currentRank As Long
Dim currentCell As String
Dim stateText As String
Dim readBackgroundColor As Long
Dim writeBackgroundColor As Long
Dim moveText As String
Dim transitionText As String
Dim i As Long
previousFileAlphabet = Split(Cells(1, Range(previousCell).Column).Address, "$")(1)
previousRank = Range(previousCell).Row
currentRank = previousRank + 1
currentCell = previousFileAlphabet & currentRank
Debug.Print ("--------")
Debug.Print ("previousCell :" & previousCell)
Debug.Print ("previousFileAlphabet:" & previousFileAlphabet)
Debug.Print ("previousRank :" & previousRank)
Debug.Print ("currentRank :" & currentRank)
Debug.Print ("currentCell :" & currentCell)
' 開始行の背景色は、次行に引き継ぐ
If 2 <= previousRank Then
Dim aBackgroundColor As Long
Dim bBackgroundColor As Long
aBackgroundColor = Worksheets("Tape").Range("A" & previousRank).Interior.color
bBackgroundColor = Worksheets("Tape").Range("B" & previousRank).Interior.color
Worksheets("Tape").Range("A" & currentRank).Interior.color = aBackgroundColor
Worksheets("Tape").Range("B" & currentRank).Interior.color = bBackgroundColor
Debug.Print ("aBackgroundColor:" & aBackgroundColor)
Debug.Print ("bBackgroundColor:" & bBackgroundColor)
End If
previousText = Worksheets("Tape").Range(previousCell).Value ' 開始セルの値
previousBackgroundColor = Worksheets("Tape").Range(previousCell).Interior.color ' 開始セルの背景色
Debug.Print ("previousText :" & previousText)
Debug.Print ("previousBackgroundColor:" & previousBackgroundColor)
For i = 2 To 7
stateText = Worksheets("StateTable").Range("A" & i).Value ' 状態テーブルのState値
readBackgroundColor = Worksheets("StateTable").Range("B" & i).Interior.color ' 状態テーブルのRead列の背景色
Debug.Print ("stateText :" & stateText)
Debug.Print ("readBackgroundColor :" & readBackgroundColor)
' 一致するか?
If previousText = stateText And previousBackgroundColor = readBackgroundColor Then
writeBackgroundColor = Worksheets("StateTable").Range("C" & i).Interior.color ' 状態テーブルのWrite列の背景色
moveText = Worksheets("StateTable").Range("D" & i).Value ' 状態テーブルのMove列の値
transitionText = Worksheets("StateTable").Range("E" & i).Value ' 状態テーブルのTransition列の値
Debug.Print ("writeBackgroundColor:" & writeBackgroundColor)
Debug.Print ("moveText :" & moveText)
Debug.Print ("transitionText :" & transitionText)
' `Tape` シートの A1 セルの下のセルの背景色を Write列のいう色に塗る
Worksheets("Tape").Range(currentCell).Interior.color = writeBackgroundColor
Dim horizontal As Long ' 水平方向
If moveText = ">" Then ' Move 列が `>` だったら その右のセルへ
horizontal = 1
ElseIf moveText = "<" Then ' Move 列が `<` だったら その左のセルへ
horizontal = -1
End If
Debug.Print ("horizontal:" & horizontal)
' Transition 列のいうテキストを入れる
Dim previousFileNumber As Integer
Dim nextFileAlphabet As String
Dim nextCell As String
previousFileNumber = Columns(previousFileAlphabet).Column
nextFileAlphabet = Split(Cells(1, previousFileNumber + horizontal).Address, "$")(1)
nextCell = nextFileAlphabet & currentRank
Debug.Print ("previousFileNumber :" & previousFileNumber)
Debug.Print ("nextFileAlphabet :" & nextFileAlphabet)
Debug.Print ("nextCell :" & nextCell)
Worksheets("Tape").Range(nextCell).Value = transitionText
' 関数から抜ける
OnClock = nextCell
Exit Function
End If
Next i
End Function
📅2023-01-26 thu 21:43
「 👆 このように 前の計算結果を使って また同様に計算するように作るのは よくあるテクニックだぜ。
漸化式(ぜんかしき) とか これだな」
「 👆 3クロック目は、2クロック目と同じコードで いいはずなんだぜ。
動かしてみよう」
「 エラーがあった行をハイライト(Highlight)してくれてるのかもしれないけど 説明がないから分かんないわねぇ」
「 また ショートカットを打鍵すれば ウィンドウが出てくるのかだぜ?」
📖 VBAナメてた
📅2023-01-26 thu 22:01
「 👆 無いシート名や、無いアドレスを指定したら 出てくるエラーかも知らん」
「 👆 A列より 左に進もうとして 0列目は無いので エラーになったんだな」
「 👆 0列にアクセスしようとしたら、
A列の左に 列挿入して、 列番地も左に 1つずらして 1列にアクセスするように変更しよう」
📅2023-01-26 thu 22:18
「 👆 For
文を使えば 100行書かずに済むから楽だよな。
漸化式の形に作っておけば 繰り返しの回数を指定するだけでいいから 手間要らずだぜ」
「 👆 previousCell
変数の中身が空文字列だぜ。」
「 👆 多分、 HALT
(ハルト)が出たら 終了しないといけないんだぜ」
If transitionText = "HALT" Then
' 関数から抜ける
OnClock = "SUCCESS"
Exit Function
End If
「 👆 じゃあ HALT
(ハルト)が出たときは セル番地ではなく SUCCESS
を返すという取り決めにしておこうぜ」
' 正常終了時はループから抜ける
If resultCell = "SUCCESS" Then
Exit For
End If
「 👆 関数の呼び出し元でも 前判定で resultCell
変数の内容が SUCCESS
だったら、ループから抜けるようにすれば コードも短いぜ」
「 VBA で、自由変数の使い方、または 引数の参照渡しのやり方は どう書くんだろうな?」
「 ぜったい そんな記事を ちらっと読んでも 何も分からないけどな」
「 プログラムの組み方は分かってるが VBA での書き方が分からないだけなんで、ちら見で 充分だぜ」
「 あれっ? ByRef tapeWidth As Long
と書いても 参照渡しになって無(ね)。
調べても分からないことはある。
自由変数にするか」
📖 変数の適用範囲
「 でも 書いているうちに tapeWith
というスペルミスを見つけて tapeWidth
直したら動くようになった」
Sub ボタン1_Click()
Dim resultCell As String
Dim tapeWidth As Long
tapeWidth = 1 ' "A1" セル1つ分
' 1回目の処理
resultCell = OnClock("A1", tapeWidth)
' 同様の i 回目の処理
Dim i As Long
For i = 2 To 100
' 正常終了時はループから抜ける
If resultCell = "SUCCESS" Then
Exit For
End If
resultCell = OnClock(resultCell, tapeWidth)
Next i
End Sub
Private Function OnClock(previousCell As String, ByRef tapeWidth) As String
' 毎クロック(n回目のクロック)
Dim previousFileAlphabet As String
Dim previousRank As Long
Dim previousText As String
Dim previousBackgroundColor As Long
Dim currentRank As Long
Dim currentCell As String
Dim stateText As String
Dim readBackgroundColor As Long
Dim writeBackgroundColor As Long
Dim moveText As String
Dim transitionText As String
Dim i As Long
previousFileAlphabet = Split(Cells(1, Range(previousCell).Column).Address, "$")(1)
previousRank = Range(previousCell).Row
currentRank = previousRank + 1
currentCell = previousFileAlphabet & currentRank
Debug.Print ("--------")
Debug.Print ("previousCell :" & previousCell)
Debug.Print ("previousFileAlphabet:" & previousFileAlphabet)
Debug.Print ("previousRank :" & previousRank)
Debug.Print ("currentRank :" & currentRank)
Debug.Print ("currentCell :" & currentCell)
Debug.Print ("tapeWidth :" & tapeWidth)
' 開始行の背景色は、次行に引き継ぐ
If 2 <= previousRank Then
For i = 1 To (tapeWidth + 1)
Dim tempFileAlphabet As String
Dim tempBackgroundColor As Long
tempFileAlphabet = Split(Cells(1, i).Address, "$")(1)
tempBackgroundColor = Worksheets("Tape").Range(tempFileAlphabet & previousRank).Interior.color
Debug.Print ("i :" & i)
Debug.Print ("tempFileAlphabet :" & tempFileAlphabet)
Debug.Print ("tempBackgroundColor:" & tempBackgroundColor)
Worksheets("Tape").Range(tempFileAlphabet & currentRank).Interior.color = tempBackgroundColor
Next i
End If
previousText = Worksheets("Tape").Range(previousCell).Value ' 開始セルの値
previousBackgroundColor = Worksheets("Tape").Range(previousCell).Interior.color ' 開始セルの背景色
Debug.Print ("previousText :" & previousText)
Debug.Print ("previousBackgroundColor:" & previousBackgroundColor)
For i = 2 To 7
stateText = Worksheets("StateTable").Range("A" & i).Value ' 状態テーブルのState値
readBackgroundColor = Worksheets("StateTable").Range("B" & i).Interior.color ' 状態テーブルのRead列の背景色
Debug.Print ("stateText :" & stateText)
Debug.Print ("readBackgroundColor :" & readBackgroundColor)
' 一致するか?
If previousText = stateText And previousBackgroundColor = readBackgroundColor Then
writeBackgroundColor = Worksheets("StateTable").Range("C" & i).Interior.color ' 状態テーブルのWrite列の背景色
moveText = Worksheets("StateTable").Range("D" & i).Value ' 状態テーブルのMove列の値
transitionText = Worksheets("StateTable").Range("E" & i).Value ' 状態テーブルのTransition列の値
Debug.Print ("writeBackgroundColor:" & writeBackgroundColor)
Debug.Print ("moveText :" & moveText)
Debug.Print ("transitionText :" & transitionText)
' `Tape` シートの A1 セルの下のセルの背景色を Write列のいう色に塗る
Worksheets("Tape").Range(currentCell).Interior.color = writeBackgroundColor
Dim horizontal As Long ' 水平方向
If moveText = ">" Then ' Move 列が `>` だったら その右のセルへ
horizontal = 1
ElseIf moveText = "<" Then ' Move 列が `<` だったら その左のセルへ
horizontal = -1
End If
Debug.Print ("horizontal:" & horizontal)
' Transition 列のいうテキストを入れる
Dim previousFileNumber As Integer
Dim nextFileAlphabet As String
Dim nextFileNumber As Integer
Dim nextCell As String
previousFileNumber = Columns(previousFileAlphabet).Column
nextFileNumber = previousFileNumber + horizontal
Debug.Print ("previousFileNumber :" & previousFileNumber)
Debug.Print ("nextFileNumber :" & nextFileNumber)
If nextFileNumber = 0 Then
Worksheets("Tape").Columns("A").Insert ' A 列の左に列挿入
nextFileNumber = nextFileNumber + 1 ' 列番号を 1 つ左へずらす
tapeWidth = tapeWidth + 1 ' Update
ElseIf tapeWidth < nextFileNumber Then
tapeWidth = nextFileNumber ' Update
End If
nextFileAlphabet = Split(Cells(1, nextFileNumber).Address, "$")(1)
nextCell = nextFileAlphabet & currentRank
Debug.Print ("nextFileAlphabet :" & nextFileAlphabet)
Debug.Print ("nextCell :" & nextCell)
Worksheets("Tape").Range(nextCell).Value = transitionText
If transitionText = "HALT" Then
' 関数から抜ける
OnClock = "SUCCESS"
Exit Function
End If
' 関数から抜ける
OnClock = nextCell
Exit Function
End If
Next i
End Function
📅2023-01-27 thu 00:01
「 HALT
は出力しないのが チューリング・マシンみたいよ?」
「 じゃあ StateTable
の Transition
列で HALT
を見つけたところで 止めた方がいいのか」
「 👆 判定部を 上に持っていけば いいんじゃないかだぜ?」
「 👆 背景色のコピーを、判定部の後ろに持っていけば いいんじゃないかだぜ?」
「 👆 変数 i
は、外側のループの ループ・カウンターとして使ってたか」
「 👆 これで チューリング・マシン は完成だぜ。
一般化してないのと、不具合が残っているのが 残っているかも知れないが……」
「 👆 この例だと 長さ6のオレンジ色のテープを作るために使ったんだぜ。
説明しよう」
「 👆 この StateTable
というのが プログラムの命令セットのようなものだぜ。
この6行があると……」
「 👆 最初は A
と書かれているが、
A
にあんまり意味は無くて 長さ1つの白いテープがそこにあると思えだぜ」
「 👆 上の図は テープを伸ばしている過程が描かれたもので、
最後の 13行目が 作られたテープだぜ」
「 長さ6つのオレンジ色のテープ が作られて 動作が止まったわけだぜ」
「 長さ6つのオレンジ色のテープ なんか 作っても 嬉しくないしなあ」
「 今回はサンプルで オレンジ色1色しかなかったが、
それが 26色あって アルファベットの26文字に対応するとか、
最初から色の塗られたテープがあって チューリング・マシンが動いた後には 別の色のテープが残っているとか、
それが 暗号を解読した答え だったりしたら 嬉しいだろ」
「 じゃあ 今回の例題 がシンプルすぎて チューリング・マシン が何たるか 嬉しさが 分からないんだ」
「 プログラミング言語 が誕生する前の プログラミング 方法だぜ」
「 私たちが使うのは プログラミング言語 なのだから、懐古好きでもなければ チューリング・マシン を覚えなくてもいいのでは?」
「 一生のうちに 何回か チューリング・マシン とか チューリング完全 の名前を聞くことはあるだろ。
記事を読んで知識として知ってるより 作って知ってる方が 話しに実感がこもるだろ」
「 実感 要らないから 実用的で 効率的な練習 無いのかなあ」
「 プログラムも コンピューターも無い時代に ヒトが考えたプログラムを 体験 するぐらいね」
参考: 📖 Git Hub / TuringMachineByExcelVBA
<おわり>
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント