diff --git a/AdventOfCode.lpi b/AdventOfCode.lpi
index 2a9af4b..71cbad7 100644
--- a/AdventOfCode.lpi
+++ b/AdventOfCode.lpi
@@ -157,6 +157,10 @@
+
+
+
+
diff --git a/UMultiIndexEnumerator.pas b/UMultiIndexEnumerator.pas
new file mode 100644
index 0000000..ca02c55
--- /dev/null
+++ b/UMultiIndexEnumerator.pas
@@ -0,0 +1,160 @@
+{
+ Solutions to the Advent Of Code.
+ Copyright (C) 2024 Stefan Müller
+
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see .
+}
+
+unit UMultiIndexEnumerator;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils;
+
+type
+ TIndexArray = array of Integer;
+
+ TIndexValidationResult = (ivrValid, ivrSkip, ivrBacktrack);
+
+ TEnumerableMultiIndexStrategy = class;
+
+ { TMultiIndexEnumerator }
+
+ TMultiIndexEnumerator = class(TInterfacedObject, specialize IEnumerator)
+ private
+ FStrategy: TEnumerableMultiIndexStrategy;
+ FCurrent: TIndexArray;
+ FMustInit: Boolean;
+ function UpdateArray(const AInit: Boolean): Boolean;
+ public
+ constructor Create(const AStrategy: TEnumerableMultiIndexStrategy);
+ function GetCurrent: TIndexArray;
+ function MoveNext: Boolean;
+ procedure Reset;
+ property Current: TIndexArray read GetCurrent;
+ end;
+
+ { TEnumerableMultiIndexStrategy }
+
+ TEnumerableMultiIndexStrategy = class(TInterfacedObject, specialize IEnumerable)
+ public
+ function GetEnumerator: specialize IEnumerator;
+ function GetCardinality: Integer; virtual; abstract;
+ function TryGetStartIndexValue(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer;
+ out AStartIndexValue: Integer): Boolean; virtual; abstract;
+ function ValidateIndexValue(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer):
+ TIndexValidationResult; virtual; abstract;
+ end;
+
+implementation
+
+{ TMultiIndexEnumerator }
+
+function TMultiIndexEnumerator.UpdateArray(const AInit: Boolean): Boolean;
+var
+ i, initialized: Integer;
+ r: TIndexValidationResult;
+begin
+ if AInit then
+ begin
+ i := 0;
+ initialized := -1;
+ end
+ else begin
+ i := Length(FCurrent) - 1;
+ initialized := i;
+ end;
+
+ while i < Length(FCurrent) do
+ begin
+ if initialized < i then
+ begin
+ // Checks whether start index value can be set, and backtracks or aborts if not.
+ if not FStrategy.TryGetStartIndexValue(FCurrent, i, FCurrent[i]) then
+ if i > 0 then
+ begin
+ Dec(i);
+ Continue;
+ end
+ else begin
+ Result := False;
+ Exit;
+ end
+ end
+ else
+ // Sets next candidate for current index value.
+ Inc(FCurrent[i]);
+
+ // Checks if current index value is valid, and increases it until it is, or backtracks or aborts if so indicated.
+ while True do
+ begin
+ r := FStrategy.ValidateIndexValue(FCurrent, i);
+ case r of
+ ivrValid: begin
+ initialized := i;
+ Inc(i);
+ Break;
+ end;
+ ivrSkip:
+ Inc(FCurrent[i]);
+ ivrBacktrack:
+ if i > 0 then
+ begin
+ Dec(i);
+ Break;
+ end
+ else begin
+ Result := False;
+ Exit;
+ end;
+ end;
+ end;
+ end;
+ Result := True;
+end;
+
+constructor TMultiIndexEnumerator.Create(const AStrategy: TEnumerableMultiIndexStrategy);
+begin
+ FStrategy := AStrategy;
+ SetLength(FCurrent, FStrategy.GetCardinality);
+ Reset;
+end;
+
+function TMultiIndexEnumerator.GetCurrent: TIndexArray;
+begin
+ Result := FCurrent;
+end;
+
+function TMultiIndexEnumerator.MoveNext: Boolean;
+begin
+ Result := UpdateArray(FMustInit);
+ FMustInit := False;
+end;
+
+procedure TMultiIndexEnumerator.Reset;
+begin
+ FMustInit := True;
+end;
+
+{ TEnumerableMultiIndexStrategy }
+
+function TEnumerableMultiIndexStrategy.GetEnumerator: specialize IEnumerator;
+begin
+ Result := TMultiIndexEnumerator.Create(Self);
+end;
+
+end.
+