Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What are the problem?

posted at

updated at

Delphi でズンドコキヨシを書いてみる

はじめに

なんだかズンドコキヨシてのがあるみたいで。

Delphi で書かれたものもあるのですが、

僕なりに書いてみたいと思います 1

コード

こんな感じ。Delphi 10.4 Sydney で書いたコンソールアプリケーションです。

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.

ちょっと短く書くとこう。

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. 変数 lMAXINT で初期化。0xFFFFFFFF (0b11111111111111111111111111111111) になっている。
  2. 変数 l を左シフトしてズンドコの結果 (ランダム) を最下位ビットに格納。
  3. 最下位ビットを見て ズン (0), ドコ (1) を表示。
  4. 変数 l と 0x1F (0b11111) の and (5 ワード分) を取って、結果が 0x01 (0b00001 = ズン(0)ズン(0)ズン(0)ズン(0)ドコ(1)) ならループを抜ける。
  5. キ・ヨ・シ! を表示してプログラム終了。

もうひとつ

System.Typesuses してもいいのなら、次のような記述も可能です。

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.SysUtilsuses してもいいのなら、次のような記述も可能です。

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 文字にできます。

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.

さらにさらにもうひとつ

動的配列をインライン変数宣言する記述も可能です。

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() を抜く)

様々なインチキを施せば、

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:

短いコードの変遷

パクりパクられ...いえいえ、インスパイアの歴史です (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 さんの記事、双方のコメント欄にコードがあります。
※ 他言語持ってきて「こんなに短く書けるぜ~」って言うのは野暮なのでやめておきましょう。

おわりに

元々は自作関数の課題だったみたいで、僕が書いたコードは関数でない時点で論外なのかもしれません。

そもそも、Delphi (Pascal) だと結果を返さないルーチンは手続きであり関数ではないのですが、課題のズンドコは何を返したのでしょうね。

See also:


  1. この記事を書いている時点では、Delphi で書かれたコード (記事) しか見ていません。 

  2. いわゆる 全角文字 は 2 バイト換算です。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
3
Help us understand the problem. What are the problem?