Refactored TPointOfIncidence to better unify the algorithm for both parts

This commit is contained in:
Stefan Müller 2023-12-14 00:52:28 +01:00 committed by Stefan Müller
parent 307eb14b55
commit 01267c8f79
1 changed files with 41 additions and 75 deletions

View File

@ -31,7 +31,8 @@ type
TMirrorCandidate = record TMirrorCandidate = record
Position: Integer; Position: Integer;
HasFix: Boolean; IsFixAllowed: Boolean;
Part: Integer;
end; end;
TMirrorCandidates = specialize TList<TMirrorCandidate>; TMirrorCandidates = specialize TList<TMirrorCandidate>;
@ -41,19 +42,17 @@ type
TPointOfIncidence = class(TSolver) TPointOfIncidence = class(TSolver)
private private
FLines: TStringList; FLines: TStringList;
FHorizontalMirrorCandidates, FVerticalMirrorCandidates: specialize TList<Integer>; FHorizontalMirrorCandidates, FVerticalMirrorCandidates: TMirrorCandidates;
FHorizontalFixedMirrorCandidates, FVerticalFixedMirrorCandidates: TMirrorCandidates;
procedure ProcessPatternLine(const ALine: string); procedure ProcessPatternLine(const ALine: string);
procedure VerifyHorizontalCandidates(const ANewLine: string); procedure VerifyHorizontalCandidates(const ANewLine: string);
procedure VerifyHorizontalFixedCandidates(const ANewLine: string);
procedure CheckForNewHorizontalCandidate(const ANewLine: string); procedure CheckForNewHorizontalCandidate(const ANewLine: string);
function HaveSingleDifference(const ALine1, ALine2: string): Boolean; function HaveSingleDifference(const ALine1, ALine2: string): Boolean;
procedure VerifyVerticalCandidates(const ALine: string); procedure VerifyVerticalCandidates(const ALine: string);
procedure VerifyVerticalFixedCandidates(const ALine: string);
procedure InitializeNewVerticalCandidates(const AFirstLine: string); procedure InitializeNewVerticalCandidates(const AFirstLine: string);
function IsVerticalMirrorOfLine(const ALine: string; const AMirror: Integer): TMirrorCompareResult; function IsVerticalMirrorOfLine(const ALine: string; const AMirror: Integer): TMirrorCompareResult;
procedure FinishPattern; procedure FinishPattern;
function GetMirrorCandidate(const APosition: Integer; const AHasFix: Boolean): TMirrorCandidate; function GetMirrorCandidate(const APosition: Integer; const AIsFixAllowed: Boolean; const APart: Integer):
TMirrorCandidate;
procedure SetMirrorCandidateFixed(const AMirrorCandidates: TMirrorCandidates; const AIndex: Integer); procedure SetMirrorCandidateFixed(const AMirrorCandidates: TMirrorCandidates; const AIndex: Integer);
public public
constructor Create; constructor Create;
@ -71,14 +70,10 @@ implementation
procedure TPointOfIncidence.ProcessPatternLine(const ALine: string); procedure TPointOfIncidence.ProcessPatternLine(const ALine: string);
begin begin
VerifyHorizontalCandidates(ALine); VerifyHorizontalCandidates(ALine);
VerifyHorizontalFixedCandidates(ALine);
CheckForNewHorizontalCandidate(ALine); CheckForNewHorizontalCandidate(ALine);
if FLines.Count > 0 then if FLines.Count > 0 then
begin VerifyVerticalCandidates(ALine)
VerifyVerticalCandidates(ALine);
VerifyVerticalFixedCandidates(ALine);
end
else else
InitializeNewVerticalCandidates(ALine); InitializeNewVerticalCandidates(ALine);
@ -94,32 +89,16 @@ begin
while i >= 0 do while i >= 0 do
begin begin
// Calculates the index of the line that the current line would be a duplicate of in regards to the i-th candidate. // Calculates the index of the line that the current line would be a duplicate of in regards to the i-th candidate.
mirroredIndex := 2 * FHorizontalMirrorCandidates[i] - FLines.Count - 1; mirroredIndex := 2 * FHorizontalMirrorCandidates[i].Position - FLines.Count - 1;
if (mirroredIndex >= 0) and (ANewLine <> FLines[mirroredIndex]) then
FHorizontalMirrorCandidates.Delete(i);
Dec(i);
end;
end;
procedure TPointOfIncidence.VerifyHorizontalFixedCandidates(const ANewLine: string);
var
i, mirroredIndex: Integer;
begin
// Checks if the current line fulfills the exisiting horizontal mirror candidates.
i := FHorizontalFixedMirrorCandidates.Count - 1;
while i >= 0 do
begin
// Calculates the index of the line that the current line would be a duplicate of in regards to the i-th candidate.
mirroredIndex := 2 * FHorizontalFixedMirrorCandidates[i].Position - FLines.Count - 1;
if mirroredIndex >= 0 then if mirroredIndex >= 0 then
begin begin
if ANewLine <> FLines[mirroredIndex] then if ANewLine <> FLines[mirroredIndex] then
begin begin
if not FHorizontalFixedMirrorCandidates[i].HasFix if FHorizontalMirrorCandidates[i].IsFixAllowed
and HaveSingleDifference(ANewLine, FLines[mirroredIndex]) then and HaveSingleDifference(ANewLine, FLines[mirroredIndex]) then
SetMirrorCandidateFixed(FHorizontalFixedMirrorCandidates, i) SetMirrorCandidateFixed(FHorizontalMirrorCandidates, i)
else else
FHorizontalFixedMirrorCandidates.Delete(i); FHorizontalMirrorCandidates.Delete(i);
end; end;
end; end;
Dec(i); Dec(i);
@ -133,11 +112,11 @@ begin
begin begin
if ANewLine = FLines[FLines.Count - 1] then if ANewLine = FLines[FLines.Count - 1] then
begin begin
FHorizontalMirrorCandidates.Add(FLines.Count); FHorizontalMirrorCandidates.Add(GetMirrorCandidate(FLines.Count, False, 1));
FHorizontalFixedMirrorCandidates.Add(GetMirrorCandidate(FLines.Count, False)); FHorizontalMirrorCandidates.Add(GetMirrorCandidate(FLines.Count, True, 2));
end end
else if HaveSingleDifference(ANewLine, FLines[FLines.Count - 1]) then else if HaveSingleDifference(ANewLine, FLines[FLines.Count - 1]) then
FHorizontalFixedMirrorCandidates.Add(GetMirrorCandidate(FLines.Count, True)); FHorizontalMirrorCandidates.Add(GetMirrorCandidate(FLines.Count, False, 2));
end; end;
end; end;
@ -171,27 +150,14 @@ begin
i := FVerticalMirrorCandidates.Count - 1; i := FVerticalMirrorCandidates.Count - 1;
while i >= 0 do while i >= 0 do
begin begin
if IsVerticalMirrorOfLine(ALine, FVerticalMirrorCandidates[i]) <> mcSame then case IsVerticalMirrorOfLine(ALine, FVerticalMirrorCandidates[i].Position) of
FVerticalMirrorCandidates.Delete(i);
Dec(i);
end;
end;
procedure TPointOfIncidence.VerifyVerticalFixedCandidates(const ALine: string);
var
i: Integer;
begin
i := FVerticalFixedMirrorCandidates.Count - 1;
while i >= 0 do
begin
case IsVerticalMirrorOfLine(ALine, FVerticalFixedMirrorCandidates[i].Position) of
mcOneDifference: mcOneDifference:
if FVerticalFixedMirrorCandidates[i].HasFix then if FVerticalMirrorCandidates[i].IsFixAllowed then
FVerticalFixedMirrorCandidates.Delete(i) SetMirrorCandidateFixed(FVerticalMirrorCandidates, i)
else else
SetMirrorCandidateFixed(FVerticalFixedMirrorCandidates, i); FVerticalMirrorCandidates.Delete(i);
mcDifferent: mcDifferent:
FVerticalFixedMirrorCandidates.Delete(i); FVerticalMirrorCandidates.Delete(i);
end; end;
Dec(i); Dec(i);
end; end;
@ -205,11 +171,11 @@ begin
for i := 1 to Length(AFirstLine) - 1 do for i := 1 to Length(AFirstLine) - 1 do
case IsVerticalMirrorOfLine(AFirstLine, i) of case IsVerticalMirrorOfLine(AFirstLine, i) of
mcSame: begin mcSame: begin
FVerticalMirrorCandidates.Add(i); FVerticalMirrorCandidates.Add(GetMirrorCandidate(i, False, 1));
FVerticalFixedMirrorCandidates.Add(GetMirrorCandidate(i, False)); FVerticalMirrorCandidates.Add(GetMirrorCandidate(i, True, 2));
end; end;
mcOneDifference: mcOneDifference:
FVerticalFixedMirrorCandidates.Add(GetMirrorCandidate(i, True)); FVerticalMirrorCandidates.Add(GetMirrorCandidate(i, False, 2));
end; end;
end; end;
@ -237,28 +203,32 @@ var
i: Integer; i: Integer;
begin begin
for i := 0 to FHorizontalMirrorCandidates.Count - 1 do for i := 0 to FHorizontalMirrorCandidates.Count - 1 do
Inc(FPart1, FHorizontalMirrorCandidates[i] * 100); begin
for i := 0 to FVerticalMirrorCandidates.Count - 1 do if FHorizontalMirrorCandidates[i].Part = 1 then
Inc(FPart1, FVerticalMirrorCandidates[i]); Inc(FPart1, FHorizontalMirrorCandidates[i].Position * 100)
else if not FHorizontalMirrorCandidates[i].IsFixAllowed then
Inc(FPart2, FHorizontalMirrorCandidates[i].Position * 100);
end;
for i := 0 to FHorizontalFixedMirrorCandidates.Count - 1 do for i := 0 to FVerticalMirrorCandidates.Count - 1 do
if FHorizontalFixedMirrorCandidates[i].HasFix then begin
Inc(FPart2, FHorizontalFixedMirrorCandidates[i].Position * 100); if FVerticalMirrorCandidates[i].Part = 1 then
for i := 0 to FVerticalFixedMirrorCandidates.Count - 1 do Inc(FPart1, FVerticalMirrorCandidates[i].Position)
if FVerticalFixedMirrorCandidates[i].HasFix then else if not FVerticalMirrorCandidates[i].IsFixAllowed then
Inc(FPart2, FVerticalFixedMirrorCandidates[i].Position); Inc(FPart2, FVerticalMirrorCandidates[i].Position);
end;
FLines.Clear; FLines.Clear;
FHorizontalMirrorCandidates.Clear; FHorizontalMirrorCandidates.Clear;
FVerticalMirrorCandidates.Clear; FVerticalMirrorCandidates.Clear;
FHorizontalFixedMirrorCandidates.Clear;
FVerticalFixedMirrorCandidates.Clear;
end; end;
function TPointOfIncidence.GetMirrorCandidate(const APosition: Integer; const AHasFix: Boolean): TMirrorCandidate; function TPointOfIncidence.GetMirrorCandidate(const APosition: Integer; const AIsFixAllowed: Boolean; const APart:
Integer): TMirrorCandidate;
begin begin
Result.Position := APosition; Result.Position := APosition;
Result.HasFix := AHasFix; Result.IsFixAllowed := AIsFixAllowed;
Result.Part := APart;
end; end;
procedure TPointOfIncidence.SetMirrorCandidateFixed(const AMirrorCandidates: TMirrorCandidates; const AIndex: Integer); procedure TPointOfIncidence.SetMirrorCandidateFixed(const AMirrorCandidates: TMirrorCandidates; const AIndex: Integer);
@ -266,17 +236,15 @@ var
mirrorCandidate: TMirrorCandidate; mirrorCandidate: TMirrorCandidate;
begin begin
mirrorCandidate := AMirrorCandidates[AIndex]; mirrorCandidate := AMirrorCandidates[AIndex];
mirrorCandidate.HasFix := True; mirrorCandidate.IsFixAllowed := False;
AMirrorCandidates[AIndex] := mirrorCandidate; AMirrorCandidates[AIndex] := mirrorCandidate;
end; end;
constructor TPointOfIncidence.Create; constructor TPointOfIncidence.Create;
begin begin
FLines := TStringList.Create; FLines := TStringList.Create;
FHorizontalMirrorCandidates := specialize TList<Integer>.Create; FHorizontalMirrorCandidates := TMirrorCandidates.Create;
FVerticalMirrorCandidates := specialize TList<Integer>.Create; FVerticalMirrorCandidates := TMirrorCandidates.Create;
FHorizontalFixedMirrorCandidates := TMirrorCandidates.Create;
FVerticalFixedMirrorCandidates := TMirrorCandidates.Create;
end; end;
destructor TPointOfIncidence.Destroy; destructor TPointOfIncidence.Destroy;
@ -284,8 +252,6 @@ begin
FLines.Free; FLines.Free;
FHorizontalMirrorCandidates.Free; FHorizontalMirrorCandidates.Free;
FVerticalMirrorCandidates.Free; FVerticalMirrorCandidates.Free;
FHorizontalFixedMirrorCandidates.Free;
FVerticalFixedMirrorCandidates.Free;
inherited Destroy; inherited Destroy;
end; end;