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