はじめに
@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 1 do
begin
v1 := Random(Succ(i));
v2 := FIntArr[i]; FIntArr[i] := FIntArr[v1]; 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) があります。
See also: