# Delphi でズンドコキヨシを書いてみる --- tags: Delphi programming ネタ Pascal objectpascal created_at: 2021-02-21 updated_at: 2021-02-25 --- # はじめに なんだか**ズンドコキヨシ**てのがあるみたいで。 - [ズンドコキヨシまとめ (Qiita: @shunsugai@github)](https://qiita.com/shunsugai@github/items/971a15461de29563bf90) **Delphi** で書かれたものもあるのですが、 - [平成から令和を跨ぐズンドコキヨシのせいだよwith Delphi (Qiita: @e99h2121 )](https://qiita.com/e99h2121/items/b67c03b3b53477e9847d) - [[Delphi][ネタ]ズンドコキヨシ・コードゴルフ (Qiita: @pik)](https://qiita.com/pik/items/9ddb684967a5bec4d970) 僕なりに書いてみたいと思います [^1]。 # コード こんな感じ。**Delphi 10.4 Sydney** で書いたコンソールアプリケーションです。 ```pascal:ZunDoko.dpr {$APPTYPE CONSOLE} const a: array [0..1] of string = ('ズン', 'ドコ'); begin Randomize; var l := MaxInt; repeat var v := Random(2); Write(a[v]); l := (l shl 1) or v; until (l and $1F) = $01; Writeln('キ・ヨ・シ!'); end. ``` ちょっと短く書くとこう。 ```pascal:ZunDoko.dpr {$APPTYPE CONSOLE} const a: array [0..1] of string = ('ズン', 'ドコ'); begin Randomize; var l := MaxInt; repeat l := (l shl 1) or Random(2); Write(a[l and 1]); until (l and $1F) = $01; Writeln('キ・ヨ・シ!'); end. ``` ## 説明 特に難しい事はやっていません。 1. 変数 `l` を **MAXINT** で初期化。0xFFFFFFFF (0b11111111111111111111111111111111) になっている。 2. 変数 `l` を左シフトしてズンドコの結果 (ランダム) を最下位ビットに格納。 3. 最下位ビットを見て `ズン (0)`, `ドコ (1)` を表示。 4. 変数 `l` と 0x1F (0b11111) の **and** (5 ワード分) を取って、結果が `0x01 (0b00001 = ズン(0)ズン(0)ズン(0)ズン(0)ドコ(1))` ならループを抜ける。 5. `キ・ヨ・シ!` を表示してプログラム終了。 ## もうひとつ `System.Types` を **uses** してもいいのなら、次のような記述も可能です。 ```pascal:ZunDoko.dpr {$APPTYPE CONSOLE} uses System.Types; begin Randomize; var l := MaxInt; repeat l := (l shl 1) or Random(2); Write(TStringDynArray.Create('ズン', 'ドコ')[l and 1]); until (l and $1F) = $01; Writeln('キ・ヨ・シ!'); end. ``` ## さらにもうひとつ `System.SysUtils` を **uses** してもいいのなら、次のような記述も可能です。 ```pascal:ZunDoko.dpr {$APPTYPE CONSOLE} uses System.SysUtils; begin Randomize; var l := MaxInt; repeat l := (l shl 1) or Random(2); Write('ズン,ドコ'.Split([','])[l and 1]); until (l and $1F) = $01; Writeln('キ・ヨ・シ!'); end. ``` 一行だと 160 文字にできます。 ```pascal:ZunDoko.dpr uses SysUtils;begin Randomize;var l:=MaxInt;repeat l:=(l shl 1)or Random(2);Write('ズン,ドコ'.Split([','])[l and 1]);until(l and 31)=1;Write('キ・ヨ・シ!')end. ``` ## さらにさらにもうひとつ 動的配列をインライン変数宣言する記述も可能です。 ```pascal:ZunDoko.dpr {$APPTYPE CONSOLE} begin Randomize; var a := ['ズン', 'ドコ']; var l := MaxInt; repeat l := (l shl 1) or Random(2); Write(a[l and 1]); until (l and $1F) = $01; Writeln('キ・ヨ・シ!'); end. ``` 上記コードを - 改行を含めた不要なホワイトスペースを抜く - 16進値は短くなるのであれば 10進値に変更 - 演算子の優先順位により不要な `()` を除去 - **end.** 前のセミコロンを抜く あれやこれやで一行にし、 - `{$APPTYPE CONSOLE}` を抜く - `Writeln()` を `Write()` にする - (`Randomize()` を抜く) 様々なインチキを施せば、 ```pascal:ZunDoko.dpr begin Randomize;var l:=1;var a:=['ズン','ドコ'];repeat l:=l shl 1 or Random(2);Write(a[l and 1]);until l and 31=1;Write('キ・ヨ・シ!')end. ``` 140 文字で納まるようです (Randomize を抜いて 130 文字)。僕が単独で思いついた短いコードはここまでです。 **See also:** - [演算子の優先順位 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%BC%8F%EF%BC%88Delphi%EF%BC%89#.E6.BC.94.E7.AE.97.E5.AD.90.E3.81.AE.E5.84.AA.E5.85.88.E9.A0.86.E4.BD.8D) ## 短いコードの変遷 パクりパクられ...いえいえ、インスパイアの歴史です (w | 作者 | 長さ [^2]| 説明 | |:---|:---:|:---| | @pik | 167 | 初版 | | @ht_deko | 160 | Split() を使った手法 | | @fujitanozomu | 147 | 160文字版のズンドコ逆転、シフト演算を乗算に | | @ht_deko | 140 | 動的配列をインライン変数で定義 | | @ht_deko | 133 | 140文字版に147文字版のロジックを適用 | | @ht_deko | 132 | 133文字版のビットフラグを見直し | | @pik | 130 | 演算順序の変更による空白の除去、
空文のセミコロン除去 | | @ht_deko | 129 | 132文字版に130文字版のロジックを適用 | | @fujitanozomu | 125 | ビットフラグの見直し | | @pik | 122 | 125文字版の動的配列を Copy() で置き換え | | @fujitanozomu | 120 | 122文字版の Copy() の引数を変更、
Index=1 と Index=0 が同じ事を利用 | ※ この記事と [@pik さんの記事](https://qiita.com/pik/items/9ddb684967a5bec4d970)、双方のコメント欄にコードがあります。 ※ 他言語持ってきて「こんなに短く書けるぜ~」って言うのは野暮なのでやめておきましょう。 # おわりに 元々は自作関数の課題だったみたいで、僕が書いたコードは関数でない時点で論外なのかもしれません。 そもそも、**Delphi (Pascal)** だと結果を返さないルーチンは**手続き**であり関数ではないのですが、課題のズンドコは何を返したのでしょうね。 **See also:** - [<11> 手続きと関数 (標準 Pascal 範囲内での Delphi 入門) (Qiita)](./b93ac03bfee002f17137.md) [^1]: この記事を書いている時点では、Delphi で書かれたコード (記事) しか見ていません。 [^2]: いわゆる `全角文字` は 2 バイト換算です。