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

# はじめに
@mattn さんの [ホクホクのイモ](https://qiita.com/mattn/items/d447a43ad12fada71663) という記事を読んで、これを Dephi で書いてみようと思いました。

# コードを書いてみる

```pascal: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() を実装してみました。

```pascal: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 までを使った重複しないランダムな整数のコレクションです。

```pascal
  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 つです。

```pascal
  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:**

 - [for 文を使用したコンテナの反復処理 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%AE%A3%E8%A8%80%E3%81%A8%E6%96%87%EF%BC%88Delphi%EF%BC%89#for_.E6.96.87.E3.82.92.E4.BD.BF.E7.94.A8.E3.81.97.E3.81.9F.E3.82.B3.E3.83.B3.E3.83.86.E3.83.8A.E3.81.AE.E5.8F.8D.E5.BE.A9.E5.87.A6.E7.90.86)
 - [フィッシャー–イェーツのシャッフル (Wikipedia)](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%83%E3%82%B7%E3%83%A3%E3%83%BC%E2%80%93%E3%82%A4%E3%82%A7%E3%83%BC%E3%83%84%E3%81%AE%E3%82%B7%E3%83%A3%E3%83%83%E3%83%95%E3%83%AB)

# おわりに

Delphi のコレクション集として [Delphi Collection Library (Delphi-Coll) (GitHub)](https://github.com/pavkam/delphi-coll) があります。

**See also:**

 - [Generic collections library (delphi-coll) (Owl's perspective)](http://owlsperspective.blogspot.com/2011/11/generic-collections-library.html) - [delphi-collを使ってみる(1) (山本隆の開発日誌)](https://www.gesource.jp/weblog/?p=5265)
 - [delphi-collを使ってみる(2) (山本隆の開発日誌)](https://www.gesource.jp/weblog/?p=5289)
 - [delphi-collを使ってみる(3) (山本隆の開発日誌)](https://www.gesource.jp/weblog/?p=5290)
 - [delphi-collを使ってみる(4) (山本隆の開発日誌)](https://www.gesource.jp/weblog/?p=5670)
 - [delphi-collを使ってみる(5) (山本隆の開発日誌)](https://www.gesource.jp/weblog/?p=6446)