[今日のPiet]九九表を出力するPietコード

前記事を書いてから1ヶ月経ちました。

週2回更新するというモチベーションは、現在長期旅行中で不在です。

しかし、「そろそろ新記事を書きませんか?」 と、はてなさんにすすめられてしまいました。

すみません。書きます。

九九表を出力するPietソースコードを作るよ

以前紹介した 「GridPietGenerator」を使って、 Pietソースコードを出力させます。

今回は、「九九の表を出力するプログラム」、作ってみます。

動作

2つの正数M、Nを入力として与えると、 横M、縦Nの「九九表」を出力するプログラムを作ります。

(M、Nが任意なので、厳密には「九九」ではないけど。)

「処理フローファイル」

出力したいPietソースコードの挙動を記述する「処理フローファイル」は以下のようになります。

行末コメントに、その行の終了時点でのスタックの状態をメモしています。

一応、解読できるようにはしましたが、説明がないとわからないと思います。

今度1記事使って読み方は解説します。(定期的に更新しないとなあ・・・。)

# kuku
push1 dup sub       #[0
inn dup inn         #[0|n,n,m
:mloop              #[...|n(=>n'),n,m
push2 push1 roll    #[...|n',m,n
:nloop              #[...|n',m,n
dup                 #[...|n',m,n,n
push3 push2 roll    #[...|n',n,n,m
dup                 #[...|n',n,n,m,m
push4 push1 roll    #[...|n',m,n,n,m
mul                 #[...|n',m,n,n*m
push4 push1 roll    #[...|n*m:n',m,n
push2 dup dup mul dup mul mul #[...:n*m|n',m,n,32(<=>' ')
push1 push2 sub mul #[...|n',m,n,-32
push4 push1 roll    #[...|-32:n',m,n
push1 sub           #[...:-32|n',m,n-1(=>n)
dup if:nloop:       #[...|n',m,n
pop                 #[...|n',m
push1 sub           #[...|n',m-1(=>m)
dup if::print       #[...|n',m
push2 push1 roll    #[...|m,n'
dup                 #[...|m,n',n'
push3 push1 roll    #[...|n',m,n'(=>n)
push1 push3 push4 mul add #[...|n',m,n,13(<=>'\0x0D')
push1 push2 sub mul #[...|n',m,n,-13
push2 push5 mul     #[...|n',m,n,-13,10(<=>'\0x0A')
push1 push2 sub mul #[...|n',m,n,-13,-10
push5 push2 roll    #[...|-13,-10:n',m,n
goto:nloop

:print              #[...:v|n',m
pop pop             #[...|v:
:print_loop         #[...|v
dup if::end         #[...|v
dup push1 push1 sub #[...|v,v,0
gt if:loutn:loutc   #[...|v
:loutn              #[...:nv|v
outn                #[...|nv(=>v):
goto:print_loop     #[...|v
:loutc              #[...:nv|v
push1 push2 sub mul #[...|nv,-v
outc                #[...|nv(=>v):
goto:print_loop     #[...|v
:end
end

詳細な解説はしませんが、ざっとだけ。

入力した値を使って二重ループを作り、

掛け算の積を計算して、スタックに積んでいきます。

(途中、スペースやら改行文字やらも積んでいきます。)

ループが終了したら、スタックの中身を全て出力します。

出力する値が数値なのか文字なのかを値の正負で区別したり、

スタックの中身をすべて出力したかを判定するために、

初めにスタックにゼロを積んだりしています。

Pietではこういう些細な工夫が 色々と必要なので大変です。

変換結果

こちらをPietソースコードに変換すると、次のようになります。

f:id:y-mos:20210715235149p:plain
「九九表」

出力結果

早速動かしてみます。

./npiet out.ppm -tpic
? 9
? 9
 1 2 3 4 5 6 7 8 9
 2 4 6 8 10 12 14 16 18
 3 6 9 12 15 18 21 24 27
 4 8 12 16 20 24 28 32 36
 5 10 15 20 25 30 35 40 45
 6 12 18 24 30 36 42 48 54
 7 14 21 28 35 42 49 56 63
 8 16 24 32 40 48 56 64 72
 9 18 27 36 45 54 63 72 81

とりあえず動いているみたいです。

トレース画像は次のようになります。

f:id:y-mos:20210715235241p:plain
「九九表」のトレース画像

いい感じにPietインタプリタが迷走してくれてますね。

最後に

半分以上自己満足ですが、 Pietソースコードをたくさん作っていく。

そんなことを日課にするのもいいかもしれないですね。

結構いい頭の体操になりますし。

そんなことを思う今日この頃です。

それではまた。