Edited at

ホクホクのイモを Delphi で書いてみる


はじめに

@mattn さんの ホクホクのイモ という記事を読んで、これを Dephi で書いてみようと思いました。


コードを書いてみる


hokuimo.dpr

uses

System.SysUtils, uPermutations;

begin
Randomize;
var s := '';
var rs := 'ホイクモ';
for var i in Perm(4, 2) do
s := s + rs.Chars[i];
s := s + s + 'の';
for var i in Perm(4, 2) do
s := s + rs.Chars[i];
Writeln(s);
end.


Delphi だとこんな感じで書け...たらよかったのですが、Perm() というコレクションは標準では存在しません。


uPermutations の実装

ランダムな整数のコレクションを返す Perm() を実装してみました。


uPermutations.pas

unit uPermutations;

interface

uses
SysUtils, Types, Math;

type
TPermEnumerator = class;

TPerm = record
private
Fcount: Integer;
FIntArr: TIntegerDynArray;
public
constructor Create(range: Integer; count: Integer);
function GetEnumerator: TPermEnumerator;
end;

TPermEnumerator = class
Container: TPerm;
Index: Integer;
public
constructor Create(AContainer : TPerm);
function GetCurrent: Integer;
function MoveNext: Boolean;
property Current: Integer read GetCurrent;
end;

function Perm(range: Integer; count: Integer): TPerm; overload;
function Perm(range: Integer): TPerm; overload;

implementation

function Perm(range: Integer; count: Integer): TPerm;
begin
Result := TPerm.Create(range, count);
end;

function Perm(range: Integer): TPerm;
begin
Result := TPerm.Create(range, range);
end;

{ TPerm }

constructor TPerm.Create(range: Integer; count: Integer);
var
i, v1, v2: Integer;
begin
Fcount := Min(count, range);
SetLength(FIntArr, range);
for i:=0 to Pred(range) do
FIntArr[i] := i;
for i:=Pred(range) downto 0 do
begin
v1 := Random(Succ(i));
v2 := FIntArr[i];
FIntArr[i] := FIntArr[v1];
if v1 <> i then
FIntArr[v1] := v2;
end;
end;

function TPerm.GetEnumerator: TPermEnumerator;
begin
Result := TPermEnumerator.Create(Self);
end;

{ TPermEnumerator }

constructor TPermEnumerator.Create(AContainer: TPerm);
begin
inherited Create;
Container := AContainer;
Index := -1;
end;

function TPermEnumerator.GetCurrent: Integer;
begin
Result := Container.FIntArr[Index];
end;

function TPermEnumerator.MoveNext: Boolean;
begin
result := Index < Pred(Container.Fcount);
Inc(Index);
end;

end.


これを使えばホクイモ (ホイクモ?) がシンプルに書けます。

Perm(10) は 0 から 9 までを使った重複しないランダムな整数のコレクションです。

  for var l := 1 to 10 do

begin
for var i in Perm(10) do
Write(i);
Writeln;
end;

1964072358

4869207135
2179046853
1865493207
6481953270
0261834957
7354620981
7463251980
6514293087
3498071562

Perm(10, 3) は 0 から 9 までを使ったコレクションのうちの最初の 3 つです。

  for var l := 1 to 10 do

begin
for var i in Perm(10, 3) do
Write(i);
Writeln;
end;

437

605
139
570
739
941
042
513
574
982

See also:


おわりに

Delphi のコレクション集として Delphi Collection Library (Delphi-Coll) (GitHub) があります。