Snippets

Stefan Glienke Lotto example

Created by Stefan Glienke last modified
program Lotto;

{$APPTYPE CONSOLE}

uses
  Spring,
  Spring.Collections,
  Spring.Collections.Base,
  spring.Collections.Extensions,
  SysUtils, TypInfo;

type
  TShuffleIterator<T> = class(TSourceIterator<T>)
  private
    fItems: TArray<T>;
    fIndex: Integer;
  protected
    function Clone: TIterator<T>; override;
  public
    constructor Create(const source: IEnumerable<T>);
    function MoveNext: Boolean; override;
  end;

type
  Enumerable<T> = record
  private
    this: IEnumerable<T>;
  public
    class operator Implicit(const value: Enumerable<T>): IEnumerable<T>;
    function GetEnumerator: IEnumerator<T>;

    function First: T;
    function Last: T;

    function Ordered: Enumerable<T>;

    function Select<TResult>: Enumerable<TResult>; overload;
    function Select<TResult>(const selector: TFunc<T,TResult>): Enumerable<TResult>; overload;

    function Shuffle: Enumerable<T>;

    function Take(const count: Integer): Enumerable<T>;
  end;

  Enumerable = record
    class function Range(start, count: Integer): Enumerable<Integer>; static;
  end;

function StringJoin(const separator: string; const values: IEnumerable<string>): string;
var
  e: IEnumerator<string>;
begin
  e := values.GetEnumerator;
  if not e.MoveNext then
    Exit('');
  Result := e.Current;
  while e.MoveNext do
    Result := Result + separator + e.Current;
end;

procedure Main;
var
  numbers: Enumerable<Integer>;
begin
  numbers := Enumerable.Range(1, 49).Shuffle.Take(7);

  Writeln('Gewinnzahlen: ',
    StringJoin(', ', numbers.Take(6).Ordered.Select<string>),
    ' Zusatzzahl: ',
    numbers.Last);
end;

procedure Powerball;
begin
  Writeln(
    'Winning numbers: ',
    StringJoin(', ', Enumerable.Range(1, 69).Shuffle.Take(5).Ordered.Select<string>),
    ' Powerball: ',
    Enumerable.Range(1, 26).Shuffle.First);
end;

{ TShuffleIterator<T> }

constructor TShuffleIterator<T>.Create(const source: IEnumerable<T>);
begin
  inherited Create;
  fSource := source;
end;

function TShuffleIterator<T>.Clone: TIterator<T>;
begin
  Result := TShuffleIterator<T>.Create(fSource);
end;

function TShuffleIterator<T>.MoveNext: Boolean;
var
  i: Integer;
begin
  Result := False;

  if fState = STATE_ENUMERATOR then
  begin
    fItems := fSource.ToArray;
    fIndex := Length(fItems) - 1;
    fState := STATE_RUNNING;
  end;

  if fState = STATE_RUNNING then
  begin
    if fIndex >= 0 then
    begin
      i := Random(fIndex + 1);
      fCurrent := fItems[i];
      fItems[i] := fItems[fIndex];
      Dec(fIndex);
      Exit(True);
    end;
    fState := STATE_FINISHED;
  end;
end;

{ Enumerable }

class function Enumerable.Range(start, count: Integer): Enumerable<Integer>;
begin
  Result.this := TRangeIterator.Create(start, count);
end;

{ Enumerable<T> }

function Enumerable<T>.GetEnumerator: IEnumerator<T>;
begin
  Result := this.GetEnumerator;
end;

class operator Enumerable<T>.Implicit(
  const value: Enumerable<T>): IEnumerable<T>;
begin
  Result := value.this;
end;

function Enumerable<T>.First: T;
begin
  Result := this.First;
end;

function Enumerable<T>.Last: T;
begin
  Result := this.Last;
end;

function Enumerable<T>.Ordered: Enumerable<T>;
begin
  Result.this := TOrderedIterator<T>.Create(this, nil);
end;

function Enumerable<T>.Select<TResult>: Enumerable<TResult>;
var
  selector: TFunc<T,TResult>;
begin
  case TType.Kind<T> of
    tkInteger:
      case TType.Kind<TResult> of
        tkUString: TFunc<Integer,string>(selector) := IntToStr;
      end;
  end;

  Result.this := TSelectIterator<T,TResult>.Create(this, selector);
end;

function Enumerable<T>.Select<TResult>(const selector: TFunc<T,TResult>): Enumerable<TResult>;
begin
  Result.this := TSelectIterator<T,TResult>.Create(this, selector);
end;

function Enumerable<T>.Shuffle: Enumerable<T>;
begin
  Result.this := TShuffleIterator<T>.Create(this);
end;

function Enumerable<T>.Take(const count: Integer): Enumerable<T>;
begin
  Result.this := TTakeIterator<T>.Create(this, count);
end;

begin
  if RandSeed = 0 then
    Randomize;
  try
    Main;
    Powerball;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.