Updated day 12 WIP solver

This commit is contained in:
Stefan Müller 2024-11-09 23:17:47 +01:00
parent 21ef4c08f1
commit 60ef49c1ee
1 changed files with 69 additions and 40 deletions

View File

@ -22,7 +22,7 @@ unit UHotSprings;
interface
uses
Classes, SysUtils, Math, Generics.Collections, USolver, UCommon, UMultiIndexEnumerator;
Classes, SysUtils, Math, Generics.Collections, USolver, UCommon, UMultiIndexEnumerator, UBinomialCoefficients;
const
COperationalChar = '.';
@ -114,6 +114,7 @@ type
TConditionRecord = class
private
FBinomialCoefficients: TBinomialCoefficientCache;
FValidation: TIntegerList;
// List of non-empty, maximum-length parts of the pattern without operational springs ("blocks").
FBlocks: TStringList;
@ -150,11 +151,12 @@ type
constref AIndices: TIndexArray; const AStartIndex, AStopIndex: Integer): Int64;
function CalcCombinationsBlockAssignedValidations(const ABlockLength: Integer; constref APositionInfos:
TValidationPositionInfos; constref AOffsets: TIndexArray; const AStartIndex, AStopIndex: Integer): Int64;
function CalcCombinationsWildcardSequence(const ASequenceLength, AStartIndex, AStopIndex: Integer): Int64;
function ParseDamages(const ABlock: string): TDamages;
public
property Blocks: TStringList read FBlocks;
property Validation: TIntegerList read FValidation;
constructor Create;
constructor Create(constref ABinomialCoefficients: TBinomialCoefficientCache);
destructor Destroy; override;
// Adds all non-empty, maximum-length parts of the pattern without operational springs ("blocks").
procedure AddBlocks(const APattern: string);
@ -164,7 +166,12 @@ type
{ THotSprings }
THotSprings = class(TSolver)
private
// Keeping the binomial coefficients calculator here so it can be shared for all lines.
FBinomialCoefficients: TBinomialCoefficientCache;
public
constructor Create;
destructor Destroy; override;
procedure ProcessDataLine(const ALine: string); override;
procedure Finish; override;
function GetDataFileName: string; override;
@ -442,7 +449,7 @@ begin
end;
///////////////////////////////
Result := 9999;
Result := 0;
// Assigns validation numbers to specific damages.
validationToDamageAssignments := TValidationToDamageAssignments.Create(FValidation, FValidationLengths, ADamages,
@ -457,7 +464,7 @@ begin
for i := 0 to ADamages.Count - 1 do
Write(indices[i] - AStartIndex, ' ');
WriteLn(')');
CalcCombinationsBlockMultiValidations(Length(ABlock), ADamages, indices, AStartIndex, AStopIndex);
Result := Result + CalcCombinationsBlockMultiValidations(Length(ABlock), ADamages, indices, AStartIndex, AStopIndex);
end;
validationToDamageAssignments.Free;
end;
@ -526,9 +533,10 @@ begin
WriteLn(' ', position.ValidationIndex, ' ', position.MinStart, ' ', position.MaxStart);
WriteLn(' offsets');
Result := 0;
validationPositionOffsets := TValidationPositionOffsets.Create(FValidation, positions);
for offsets in validationPositionOffsets do
CalcCombinationsBlockAssignedValidations(ABlockLength, positions, offsets, AStartIndex, AStopIndex);
Result := Result + CalcCombinationsBlockAssignedValidations(ABlockLength, positions, offsets, AStartIndex, AStopIndex);
validationPositionOffsets.Free;
positions.Free;
@ -537,44 +545,52 @@ end;
function TConditionRecord.CalcCombinationsBlockAssignedValidations(const ABlockLength: Integer; constref APositionInfos:
TValidationPositionInfos; constref AOffsets: TIndexArray; const AStartIndex, AStopIndex: Integer): Int64;
var
i, space, freedom, count: Integer;
i, space: Integer;
begin
Write(' ');
for i in AOffsets do
Write(i, ' ');
Write(' count/space/freedom: ');
// TODO: Number of combinations is binom(count + freedom, freedom).
if AStartIndex < APositionInfos[0].ValidationIndex then
begin
count := APositionInfos[0].ValidationIndex - AStartIndex;
space := AOffsets[0] - 2;
freedom := space - FValidationLengths[AStartIndex, APositionInfos[0].ValidationIndex];
Write(count, '/', space, '/', freedom, ' ');
end
else
Write('X ');
for i := 0 to APositionInfos.Count - 2 do
if APositionInfos[i].ValidationIndex + 1 < APositionInfos[i + 1].ValidationIndex then
begin
count := APositionInfos[i + 1].ValidationIndex - APositionInfos[i].ValidationIndex - 1;
space := AOffsets[i + 1] - AOffsets[i] - FValidation[APositionInfos[i].ValidationIndex] - 2;
freedom := space - FValidationLengths[APositionInfos[i].ValidationIndex + 1, APositionInfos[i + 1].ValidationIndex];
Write(count, '/', space, '/', freedom, ' ');
end
else
Write('X ');
if APositionInfos.Last.ValidationIndex < AStopIndex then
begin
count := AStopIndex - APositionInfos.Last.ValidationIndex;
space := ABlockLength - AOffsets[APositionInfos.Count - 1] - FValidation[APositionInfos.Last.ValidationIndex];
freedom := space - FValidationLengths[APositionInfos.Last.ValidationIndex + 1, AStopIndex + 1];
Write(count, '/', space, '/', freedom, ' ');
end
else
Write('X ');
Write(' count/space/freedoms: ');
space := AOffsets[0] - 2;
Result := CalcCombinationsWildcardSequence(space, AStartIndex, APositionInfos[0].ValidationIndex);
if Result = 0 then begin
WriteLn(' result: ', Result);
Exit;
end;
WriteLn;
for i := 0 to APositionInfos.Count - 2 do begin
space := AOffsets[i + 1] - AOffsets[i] - FValidation[APositionInfos[i].ValidationIndex] - 2;
Result := Result * CalcCombinationsWildcardSequence(space, APositionInfos[i].ValidationIndex + 1, APositionInfos[i + 1].ValidationIndex);
if Result = 0 then begin
WriteLn(' result: ', Result);
Exit;
end;
end;
space := ABlockLength - AOffsets[APositionInfos.Count - 1] - FValidation[APositionInfos.Last.ValidationIndex];
Result := Result * CalcCombinationsWildcardSequence(space, APositionInfos.Last.ValidationIndex + 1, AStopIndex + 1);
WriteLn(' result: ', Result);
end;
function TConditionRecord.CalcCombinationsWildcardSequence(const ASequenceLength, AStartIndex, AStopIndex: Integer):
Int64;
var
count, freedoms: Integer;
begin
if AStartIndex < AStopIndex then
begin
count := AStopIndex - AStartIndex;
freedoms := ASequenceLength - FValidationLengths[AStartIndex, AStopIndex];
Write(count, '/', ASequenceLength, '/', freedoms, ' ');
if freedoms >= 0 then
Result := FBinomialCoefficients.Get(count + freedoms, freedoms)
else
Result := 0;
end
else begin
Result := 1;
Write('X ');
end;
end;
function TConditionRecord.ParseDamages(const ABlock: string): TDamages;
@ -607,8 +623,10 @@ begin
end;
end;
constructor TConditionRecord.Create;
constructor TConditionRecord.Create(constref ABinomialCoefficients: TBinomialCoefficientCache);
begin
FBinomialCoefficients := ABinomialCoefficients;
FBlocks := TStringList.Create;
FValidation := TIntegerList.Create;
FDamagesBlocks := TDamagesBlocks.Create;
@ -700,6 +718,17 @@ end;
{ THotSprings }
constructor THotSprings.Create;
begin
FBinomialCoefficients := TBinomialCoefficientCache.Create;
end;
destructor THotSprings.Destroy;
begin
FBinomialCoefficients.Free;
inherited Destroy;
end;
procedure THotSprings.ProcessDataLine(const ALine: string);
var
conditionRecord1, conditionRecord2: TConditionRecord;
@ -710,8 +739,8 @@ begin
WriteLn(ALine);
WriteLn;
conditionRecord1 := TConditionRecord.Create;
conditionRecord2 := TConditionRecord.Create;
conditionRecord1 := TConditionRecord.Create(FBinomialCoefficients);
conditionRecord2 := TConditionRecord.Create(FBinomialCoefficients);
mainSplit := ALine.Split([' ']);