LoginSignup
4
1

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-07-05

はじめに

@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:

4
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1