Added TBlock to replace the block strings for day 12
This commit is contained in:
parent
1642c7dcfb
commit
05863842df
|
@ -43,10 +43,25 @@ type
|
||||||
TDamage = record
|
TDamage = record
|
||||||
Start, Length, CharsRemaining: Integer;
|
Start, Length, CharsRemaining: Integer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TDamages = specialize TList<TDamage>;
|
TDamages = specialize TList<TDamage>;
|
||||||
// TODO: Instead of using TDamagesBlocks, "block" should be a record of a string and its associated list TDamages.
|
|
||||||
TDamagesBlocks = specialize TObjectList<TDamages>;
|
{ TBlock }
|
||||||
|
|
||||||
|
TBlock = class
|
||||||
|
private
|
||||||
|
FPattern: string;
|
||||||
|
FDamages: TDamages;
|
||||||
|
procedure ParseDamages;
|
||||||
|
public
|
||||||
|
constructor Create(const APattern: string);
|
||||||
|
destructor Destroy; override;
|
||||||
|
property Pattern: string read FPattern;
|
||||||
|
// List of damages in this block, containing exactly one entry for each sequence of consecutive damage characters in
|
||||||
|
// the block's pattern, ordered such that a damage with lower index is further left.
|
||||||
|
// For example, if Pattern is '??##?#?', then Damages would have 2 entries.
|
||||||
|
property Damages: TDamages read FDamages;
|
||||||
|
end;
|
||||||
|
TBlocks = specialize TObjectList<TBlock>;
|
||||||
|
|
||||||
{ TValidationToDamageAssignments }
|
{ TValidationToDamageAssignments }
|
||||||
|
|
||||||
|
@ -99,7 +114,7 @@ type
|
||||||
FBinomialCoefficients: TBinomialCoefficientCache;
|
FBinomialCoefficients: TBinomialCoefficientCache;
|
||||||
FValidation: TIntegerList;
|
FValidation: TIntegerList;
|
||||||
// List of non-empty, maximum-length parts of the pattern without operational springs ("blocks").
|
// List of non-empty, maximum-length parts of the pattern without operational springs ("blocks").
|
||||||
FBlocks: TStringList;
|
FBlocks: TBlocks;
|
||||||
// Array 'a' of accumulated validation series lengths. 'a[i, j]' denotes the combined length of consecutive
|
// Array 'a' of accumulated validation series lengths. 'a[i, j]' denotes the combined length of consecutive
|
||||||
// validation numbers from 'FValidation[i]' to 'FValidation[j - 1]' with a single space in between each pair of
|
// validation numbers from 'FValidation[i]' to 'FValidation[j - 1]' with a single space in between each pair of
|
||||||
// them.
|
// them.
|
||||||
|
@ -107,32 +122,25 @@ type
|
||||||
// Array 'a' of minimum indices 'a[i]', such that all remaining validation numbers starting at index 'a[i] - 1'
|
// Array 'a' of minimum indices 'a[i]', such that all remaining validation numbers starting at index 'a[i] - 1'
|
||||||
// cannot fit into the remaining blocks starting at 'FBlocks[i]'.
|
// cannot fit into the remaining blocks starting at 'FBlocks[i]'.
|
||||||
FMinIndices: TIntegerArray;
|
FMinIndices: TIntegerArray;
|
||||||
// List 'a' of lists of damages in a block. Each list of damages 'a[i]' contains exactly one entry for each block of
|
|
||||||
// consecutive damages characters in the i-th block.
|
|
||||||
// For example, if the pattern is '?#.??##?#?..??', then 'FDamagesBlocks' would have 3 entries, which are lists of
|
|
||||||
// 1, 2, and 0 damages, respectively.
|
|
||||||
FDamagesBlocks: TDamagesBlocks;
|
|
||||||
procedure InitValidationLengths;
|
procedure InitValidationLengths;
|
||||||
procedure InitMinIndices;
|
procedure InitMinIndices;
|
||||||
function CalcCombinations(constref AIndices: TIntegerArray): Int64;
|
function CalcCombinations(constref AIndices: TIntegerArray): Int64;
|
||||||
function CalcCombinationsBlock(const ABlock: string; constref ADamages: TDamages; const AStartIndex, AStopIndex:
|
function CalcCombinationsBlock(constref ABlock: TBlock; const AStartIndex, AStopIndex: Integer): Int64;
|
||||||
Integer): Int64;
|
function CalcCombinationsBlockSingleValidation(constref ABlock: TBlock; const AIndex: Integer): Int64;
|
||||||
function CalcCombinationsBlockSingleValidation(const ABlockLength: Integer; constref ADamages: TDamages;
|
function CalcCombinationsBlockMultiValidations(constref ABlock: TBlock; constref AIndices: TIndexArray;
|
||||||
const AIndex: Integer): Int64;
|
const AStartIndex, AStopIndex: Integer): Int64;
|
||||||
function CalcCombinationsBlockMultiValidations(const ABlockLength: Integer; constref ADamages: TDamages;
|
|
||||||
constref AIndices: TIndexArray; const AStartIndex, AStopIndex: Integer): Int64;
|
|
||||||
function CalcCombinationsBlockAssignedValidations(const ABlockLength: Integer; constref APositionInfos:
|
function CalcCombinationsBlockAssignedValidations(const ABlockLength: Integer; constref APositionInfos:
|
||||||
TValidationPositionInfos; constref AOffsets: TIndexArray; const AStartIndex, AStopIndex: Integer): Int64;
|
TValidationPositionInfos; constref AOffsets: TIndexArray; const AStartIndex, AStopIndex: Integer): Int64;
|
||||||
function CalcCombinationsWildcardSequence(const ASequenceLength, AStartIndex, AStopIndex: Integer): Int64;
|
function CalcCombinationsWildcardSequence(const ASequenceLength, AStartIndex, AStopIndex: Integer): Int64;
|
||||||
function ParseDamages(const ABlock: string): TDamages;
|
|
||||||
public
|
public
|
||||||
property Blocks: TStringList read FBlocks;
|
|
||||||
property Validation: TIntegerList read FValidation;
|
|
||||||
constructor Create(constref ABinomialCoefficients: TBinomialCoefficientCache);
|
constructor Create(constref ABinomialCoefficients: TBinomialCoefficientCache);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
// Adds all non-empty, maximum-length parts of the pattern without operational springs ("blocks").
|
// Adds all non-empty, maximum-length parts of the pattern without operational springs ("blocks").
|
||||||
procedure AddBlocks(const APattern: string);
|
procedure AddBlocks(const APattern: string);
|
||||||
function GenerateBlockAssignments: Int64;
|
function GenerateBlockAssignments: Int64;
|
||||||
|
// TODO: Blocks is not needed?
|
||||||
|
//property Blocks: TBlocks read FBlocks;
|
||||||
|
property Validation: TIntegerList read FValidation;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ THotSprings }
|
{ THotSprings }
|
||||||
|
@ -154,6 +162,50 @@ type
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
{ TBlock }
|
||||||
|
|
||||||
|
procedure TBlock.ParseDamages;
|
||||||
|
var
|
||||||
|
i, len: Integer;
|
||||||
|
damage: TDamage;
|
||||||
|
begin
|
||||||
|
FDamages := TDamages.Create;
|
||||||
|
damage.Length := 0;
|
||||||
|
len := Length(FPattern);
|
||||||
|
for i := 1 to len do
|
||||||
|
// The pattern must only contain damage and wildcard characters here.
|
||||||
|
if FPattern[i] = CDamagedChar then
|
||||||
|
begin
|
||||||
|
if damage.Length = 0 then
|
||||||
|
damage.Start := i;
|
||||||
|
Inc(damage.Length);
|
||||||
|
end
|
||||||
|
else if damage.Length > 0 then
|
||||||
|
begin
|
||||||
|
damage.CharsRemaining := len - damage.Start - damage.Length + 1;
|
||||||
|
FDamages.Add(damage);
|
||||||
|
damage.Length := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if damage.Length > 0 then
|
||||||
|
begin
|
||||||
|
damage.CharsRemaining := 0;
|
||||||
|
FDamages.Add(damage);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TBlock.Create(const APattern: string);
|
||||||
|
begin
|
||||||
|
FPattern := APattern;
|
||||||
|
ParseDamages;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TBlock.Destroy;
|
||||||
|
begin
|
||||||
|
FDamages.Free;
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TValidationToDamageAssignments }
|
{ TValidationToDamageAssignments }
|
||||||
|
|
||||||
function TValidationToDamageAssignments.CalcValidationSpan(constref ACurrentIndexArray: TIndexArray;
|
function TValidationToDamageAssignments.CalcValidationSpan(constref ACurrentIndexArray: TIndexArray;
|
||||||
|
@ -307,14 +359,14 @@ var
|
||||||
i, j, patternsLength: Integer;
|
i, j, patternsLength: Integer;
|
||||||
begin
|
begin
|
||||||
SetLength(FMinIndices, FBlocks.Count - 1);
|
SetLength(FMinIndices, FBlocks.Count - 1);
|
||||||
patternsLength := Length(FBlocks[FBlocks.Count - 1]);
|
patternsLength := Length(FBlocks[FBlocks.Count - 1].Pattern);
|
||||||
j := FValidation.Count;
|
j := FValidation.Count;
|
||||||
for i := FBlocks.Count - 2 downto 0 do
|
for i := FBlocks.Count - 2 downto 0 do
|
||||||
begin
|
begin
|
||||||
while (j >= 0) and (FValidationLengths[j, FValidation.Count] <= patternsLength) do
|
while (j >= 0) and (FValidationLengths[j, FValidation.Count] <= patternsLength) do
|
||||||
Dec(j);
|
Dec(j);
|
||||||
FMinIndices[i] := j + 1;
|
FMinIndices[i] := j + 1;
|
||||||
patternsLength := patternsLength + 1 + Length(FBlocks[i]);
|
patternsLength := patternsLength + 1 + Length(FBlocks[i].Pattern);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -334,17 +386,17 @@ begin
|
||||||
i := 0;
|
i := 0;
|
||||||
while (Result > 0) and (i < FBlocks.Count) do
|
while (Result > 0) and (i < FBlocks.Count) do
|
||||||
begin
|
begin
|
||||||
if FDamagesBlocks[i].Count > 0 then
|
if FBlocks[i].Damages.Count > 0 then
|
||||||
r := CalcCombinationsBlock(FBlocks[i], FDamagesBlocks[i], AIndices[i], AIndices[i + 1] - 1)
|
r := CalcCombinationsBlock(FBlocks[i], AIndices[i], AIndices[i + 1] - 1)
|
||||||
else begin
|
else begin
|
||||||
{$ifdef debug}
|
{$ifdef debug}
|
||||||
Write(' ', FBlocks[i], ' ');
|
Write(' ', FBlocks[i].Pattern, ' ');
|
||||||
for j := AIndices[i] to AIndices[i + 1] - 1 do
|
for j := AIndices[i] to AIndices[i + 1] - 1 do
|
||||||
Write(FValidation[j], ' ');
|
Write(FValidation[j], ' ');
|
||||||
WriteLn;
|
WriteLn;
|
||||||
Write(' count/space/freedoms: ');
|
Write(' count/space/freedoms: ');
|
||||||
{$endif}
|
{$endif}
|
||||||
r := CalcCombinationsWildcardSequence(Length(FBlocks[i]), AIndices[i], AIndices[i + 1] - 1);
|
r := CalcCombinationsWildcardSequence(Length(FBlocks[i].Pattern), AIndices[i], AIndices[i + 1] - 1);
|
||||||
{$ifdef debug}
|
{$ifdef debug}
|
||||||
WriteLn(' result: ', r);
|
WriteLn(' result: ', r);
|
||||||
{$endif}
|
{$endif}
|
||||||
|
@ -357,15 +409,14 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TConditionRecord.CalcCombinationsBlock(const ABlock: string; constref ADamages: TDamages; const AStartIndex,
|
function TConditionRecord.CalcCombinationsBlock(constref ABlock: TBlock; const AStartIndex, AStopIndex: Integer): Int64;
|
||||||
AStopIndex: Integer): Int64;
|
|
||||||
var
|
var
|
||||||
i, j, k: Integer;
|
i, j, k: Integer;
|
||||||
indices: TIndexArray;
|
indices: TIndexArray;
|
||||||
validationToDamageAssignments: TValidationToDamageAssignments;
|
validationToDamageAssignments: TValidationToDamageAssignments;
|
||||||
begin
|
begin
|
||||||
{$ifdef debug}
|
{$ifdef debug}
|
||||||
Write(' ', ABlock, ' ');
|
Write(' ', ABlock.Pattern, ' ');
|
||||||
for i := AStartIndex to AStopIndex do
|
for i := AStartIndex to AStopIndex do
|
||||||
Write(FValidation[i], ' ');
|
Write(FValidation[i], ' ');
|
||||||
WriteLn;
|
WriteLn;
|
||||||
|
@ -374,14 +425,14 @@ begin
|
||||||
// No validation number assigned to this block.
|
// No validation number assigned to this block.
|
||||||
if AStartIndex > AStopIndex then
|
if AStartIndex > AStopIndex then
|
||||||
begin
|
begin
|
||||||
if ADamages.Count = 0 then
|
if ABlock.Damages.Count = 0 then
|
||||||
Result := 1
|
Result := 1
|
||||||
else
|
else
|
||||||
Result := 0;
|
Result := 0;
|
||||||
end
|
end
|
||||||
// One validation number assigned to this block.
|
// One validation number assigned to this block.
|
||||||
else if AStartIndex = AStopIndex then
|
else if AStartIndex = AStopIndex then
|
||||||
Result := CalcCombinationsBlockSingleValidation(Length(ABlock), ADamages, AStartIndex)
|
Result := CalcCombinationsBlockSingleValidation(ABlock, AStartIndex)
|
||||||
// Multiple validation numbers assigned to this block.
|
// Multiple validation numbers assigned to this block.
|
||||||
else begin
|
else begin
|
||||||
{$ifdef debug}
|
{$ifdef debug}
|
||||||
|
@ -394,17 +445,17 @@ begin
|
||||||
Write(FValidationLengths[i, AStopIndex + 1] - FValidation[i], ' ');
|
Write(FValidationLengths[i, AStopIndex + 1] - FValidation[i], ' ');
|
||||||
WriteLn;
|
WriteLn;
|
||||||
|
|
||||||
for i := 0 to ADamages.Count - 1 do
|
for i := 0 to ABlock.Damages.Count - 1 do
|
||||||
begin
|
begin
|
||||||
WriteLn(' damage: start ',ADamages[i].Start, ', length ', ADamages[i].Length, ', remain ', ADamages[i].CharsRemaining);
|
WriteLn(' damage: start ',ABlock.Damages[i].Start, ', length ', ABlock.Damages[i].Length, ', remain ', ABlock.Damages[i].CharsRemaining);
|
||||||
Write(' ');
|
Write(' ');
|
||||||
for j := AStartIndex to AStopIndex do
|
for j := AStartIndex to AStopIndex do
|
||||||
// Enough space before damage for the other validation numbers?
|
// Enough space before damage for the other validation numbers?
|
||||||
if (FValidationLengths[AStartIndex, j + 1] - FValidation[j] < ADamages[i].Start)
|
if (FValidationLengths[AStartIndex, j + 1] - FValidation[j] < ABlock.Damages[i].Start)
|
||||||
// Enough space after damage for the other validation numbers?
|
// Enough space after damage for the other validation numbers?
|
||||||
and (FValidationLengths[j, AStopIndex + 1] - FValidation[j] <= ADamages[i].CharsRemaining)
|
and (FValidationLengths[j, AStopIndex + 1] - FValidation[j] <= ABlock.Damages[i].CharsRemaining)
|
||||||
// Damage itself small enough for this validation number?
|
// Damage itself small enough for this validation number?
|
||||||
and (FValidation[j] >= ADamages[i].Length) then
|
and (FValidation[j] >= ABlock.Damages[i].Length) then
|
||||||
Write(j - AStartIndex, ' ');
|
Write(j - AStartIndex, ' ');
|
||||||
WriteLn;
|
WriteLn;
|
||||||
end;
|
end;
|
||||||
|
@ -413,7 +464,7 @@ begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
|
|
||||||
// Assigns validation numbers to specific damages.
|
// Assigns validation numbers to specific damages.
|
||||||
validationToDamageAssignments := TValidationToDamageAssignments.Create(FValidation, FValidationLengths, ADamages,
|
validationToDamageAssignments := TValidationToDamageAssignments.Create(FValidation, FValidationLengths, ABlock.Damages,
|
||||||
AStartIndex, AStopIndex);
|
AStartIndex, AStopIndex);
|
||||||
{$ifdef debug}
|
{$ifdef debug}
|
||||||
WriteLn(' validation numbers (indices) per damages:');
|
WriteLn(' validation numbers (indices) per damages:');
|
||||||
|
@ -422,44 +473,44 @@ begin
|
||||||
begin
|
begin
|
||||||
{$ifdef debug}
|
{$ifdef debug}
|
||||||
Write(' ');
|
Write(' ');
|
||||||
for i := 0 to ADamages.Count - 1 do
|
for i := 0 to ABlock.Damages.Count - 1 do
|
||||||
Write(FValidation[indices[i]], ' ');
|
Write(FValidation[indices[i]], ' ');
|
||||||
Write('( ');
|
Write('( ');
|
||||||
for i := 0 to ADamages.Count - 1 do
|
for i := 0 to ABlock.Damages.Count - 1 do
|
||||||
Write(indices[i] - AStartIndex, ' ');
|
Write(indices[i] - AStartIndex, ' ');
|
||||||
WriteLn(')');
|
WriteLn(')');
|
||||||
{$endif}
|
{$endif}
|
||||||
Result := Result + CalcCombinationsBlockMultiValidations(Length(ABlock), ADamages, indices, AStartIndex, AStopIndex);
|
Result := Result + CalcCombinationsBlockMultiValidations(ABlock, indices, AStartIndex, AStopIndex);
|
||||||
end;
|
end;
|
||||||
validationToDamageAssignments.Free;
|
validationToDamageAssignments.Free;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TConditionRecord.CalcCombinationsBlockSingleValidation(const ABlockLength: Integer; constref ADamages:
|
function TConditionRecord.CalcCombinationsBlockSingleValidation(constref ABlock: TBlock; const AIndex: Integer): Int64;
|
||||||
TDamages; const AIndex: Integer): Int64;
|
|
||||||
var
|
var
|
||||||
combinedDamagesLength: Integer;
|
len, combinedDamagesLength: Integer;
|
||||||
begin
|
begin
|
||||||
if ABlockLength < FValidation[AIndex] then
|
len := Length(ABlock.Pattern);
|
||||||
|
if len < FValidation[AIndex] then
|
||||||
Result := 0
|
Result := 0
|
||||||
else if ADamages.Count = 0 then
|
else if ABlock.Damages.Count = 0 then
|
||||||
Result := ABlockLength - FValidation[AIndex] + 1
|
Result := len - FValidation[AIndex] + 1
|
||||||
else begin
|
else begin
|
||||||
combinedDamagesLength := ADamages.Last.Start + ADamages.Last.Length - ADamages.First.Start;
|
combinedDamagesLength := ABlock.Damages.Last.Start + ABlock.Damages.Last.Length - ABlock.Damages.First.Start;
|
||||||
if FValidation[AIndex] < combinedDamagesLength then
|
if FValidation[AIndex] < combinedDamagesLength then
|
||||||
Result := 0
|
Result := 0
|
||||||
else begin
|
else begin
|
||||||
Result := Min(Min(Min(
|
Result := Min(Min(Min(
|
||||||
ADamages.First.Start,
|
ABlock.Damages.First.Start,
|
||||||
FValidation[AIndex] - combinedDamagesLength + 1),
|
FValidation[AIndex] - combinedDamagesLength + 1),
|
||||||
ABlockLength - FValidation[AIndex] + 1),
|
len - FValidation[AIndex] + 1),
|
||||||
ADamages.Last.CharsRemaining + 1);
|
ABlock.Damages.Last.CharsRemaining + 1);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TConditionRecord.CalcCombinationsBlockMultiValidations(const ABlockLength: Integer; constref ADamages:
|
function TConditionRecord.CalcCombinationsBlockMultiValidations(constref ABlock: TBlock; constref AIndices:
|
||||||
TDamages; constref AIndices: TIndexArray; const AStartIndex, AStopIndex: Integer): Int64;
|
TIndexArray; const AStartIndex, AStopIndex: Integer): Int64;
|
||||||
var
|
var
|
||||||
i, high: Integer;
|
i, high: Integer;
|
||||||
position: TValidationPositionInfo;
|
position: TValidationPositionInfo;
|
||||||
|
@ -471,25 +522,25 @@ begin
|
||||||
high := Length(AIndices) - 1;
|
high := Length(AIndices) - 1;
|
||||||
// Initializes first info record.
|
// Initializes first info record.
|
||||||
position.ValidationIndex := AIndices[0];
|
position.ValidationIndex := AIndices[0];
|
||||||
position.MaxStart := ADamages[0].Start;
|
position.MaxStart := ABlock.Damages[0].Start;
|
||||||
position.MinStart := 1;
|
position.MinStart := 1;
|
||||||
for i := 1 to high do
|
for i := 1 to high do
|
||||||
if AIndices[i] <> position.ValidationIndex then
|
if AIndices[i] <> position.ValidationIndex then
|
||||||
begin
|
begin
|
||||||
// Finalizes current info record.
|
// Finalizes current info record.
|
||||||
position.MaxStart := Min(position.MaxStart, ADamages[i].Start - 1 - FValidation[position.ValidationIndex]);
|
position.MaxStart := Min(position.MaxStart, ABlock.Damages[i].Start - 1 - FValidation[position.ValidationIndex]);
|
||||||
position.MinStart := Max(position.MinStart,
|
position.MinStart := Max(position.MinStart,
|
||||||
ADamages[i - 1].Start + ADamages[i - 1].Length - FValidation[position.ValidationIndex]);
|
ABlock.Damages[i - 1].Start + ABlock.Damages[i - 1].Length - FValidation[position.ValidationIndex]);
|
||||||
positions.Add(position);
|
positions.Add(position);
|
||||||
// Initializes next info record.
|
// Initializes next info record.
|
||||||
position.ValidationIndex := AIndices[i];
|
position.ValidationIndex := AIndices[i];
|
||||||
position.MaxStart := ADamages[i].Start;
|
position.MaxStart := ABlock.Damages[i].Start;
|
||||||
position.MinStart := position.MinStart + FValidationLengths[AIndices[i - 1], AIndices[i]] + 1; //FValidation[position.ValidationIndex - 1] + 1;
|
position.MinStart := position.MinStart + FValidationLengths[AIndices[i - 1], AIndices[i]] + 1;
|
||||||
end;
|
end;
|
||||||
// Finalizes last info record.
|
// Finalizes last info record.
|
||||||
position.MaxStart := Min(position.MaxStart, ABlockLength + 1 - FValidation[position.ValidationIndex]);
|
position.MaxStart := Min(position.MaxStart, Length(ABlock.Pattern) + 1 - FValidation[position.ValidationIndex]);
|
||||||
position.MinStart := Max(position.MinStart,
|
position.MinStart := Max(position.MinStart,
|
||||||
ADamages[high].Start + ADamages[high].Length - FValidation[position.ValidationIndex]);
|
ABlock.Damages[high].Start + ABlock.Damages[high].Length - FValidation[position.ValidationIndex]);
|
||||||
positions.Add(position);
|
positions.Add(position);
|
||||||
|
|
||||||
{$ifdef debug}
|
{$ifdef debug}
|
||||||
|
@ -502,7 +553,8 @@ begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
validationPositionOffsets := TValidationPositionOffsets.Create(FValidation, positions);
|
validationPositionOffsets := TValidationPositionOffsets.Create(FValidation, positions);
|
||||||
for offsets in validationPositionOffsets do
|
for offsets in validationPositionOffsets do
|
||||||
Result := Result + CalcCombinationsBlockAssignedValidations(ABlockLength, positions, offsets, AStartIndex, AStopIndex);
|
Result := Result
|
||||||
|
+ CalcCombinationsBlockAssignedValidations(Length(ABlock.Pattern), positions, offsets, AStartIndex, AStopIndex);
|
||||||
validationPositionOffsets.Free;
|
validationPositionOffsets.Free;
|
||||||
|
|
||||||
positions.Free;
|
positions.Free;
|
||||||
|
@ -571,50 +623,18 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TConditionRecord.ParseDamages(const ABlock: string): TDamages;
|
|
||||||
var
|
|
||||||
i, len: Integer;
|
|
||||||
damage: TDamage;
|
|
||||||
begin
|
|
||||||
Result := TDamages.Create;
|
|
||||||
damage.Length := 0;
|
|
||||||
len := Length(ABlock);
|
|
||||||
for i := 1 to len do
|
|
||||||
// The pattern must only contain damage and wildcard characters here.
|
|
||||||
if ABlock[i] = CDamagedChar then
|
|
||||||
begin
|
|
||||||
if damage.Length = 0 then
|
|
||||||
damage.Start := i;
|
|
||||||
Inc(damage.Length);
|
|
||||||
end
|
|
||||||
else if damage.Length > 0 then
|
|
||||||
begin
|
|
||||||
damage.CharsRemaining := len - damage.Start - damage.Length + 1;
|
|
||||||
Result.Add(damage);
|
|
||||||
damage.Length := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if damage.Length > 0 then
|
|
||||||
begin
|
|
||||||
damage.CharsRemaining := 0;
|
|
||||||
Result.Add(damage);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TConditionRecord.Create(constref ABinomialCoefficients: TBinomialCoefficientCache);
|
constructor TConditionRecord.Create(constref ABinomialCoefficients: TBinomialCoefficientCache);
|
||||||
begin
|
begin
|
||||||
FBinomialCoefficients := ABinomialCoefficients;
|
FBinomialCoefficients := ABinomialCoefficients;
|
||||||
|
|
||||||
FBlocks := TStringList.Create;
|
FBlocks := TBlocks.Create;
|
||||||
FValidation := TIntegerList.Create;
|
FValidation := TIntegerList.Create;
|
||||||
FDamagesBlocks := TDamagesBlocks.Create;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TConditionRecord.Destroy;
|
destructor TConditionRecord.Destroy;
|
||||||
begin
|
begin
|
||||||
FBlocks.Free;
|
FBlocks.Free;
|
||||||
FValidation.Free;
|
FValidation.Free;
|
||||||
FDamagesBlocks.Free;
|
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -626,10 +646,7 @@ begin
|
||||||
split := APattern.Split([COperationalChar]);
|
split := APattern.Split([COperationalChar]);
|
||||||
for part in split do
|
for part in split do
|
||||||
if Length(part) > 0 then
|
if Length(part) > 0 then
|
||||||
begin
|
FBlocks.Add(TBlock.Create(part));
|
||||||
FBlocks.Add(part);
|
|
||||||
FDamagesBlocks.Add(ParseDamages(part));
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TConditionRecord.GenerateBlockAssignments: Int64;
|
function TConditionRecord.GenerateBlockAssignments: Int64;
|
||||||
|
@ -668,7 +685,7 @@ begin
|
||||||
while i <= high do
|
while i <= high do
|
||||||
begin
|
begin
|
||||||
indices[i] := Max(indices[i - 1], FMinIndices[i - 1]);
|
indices[i] := Max(indices[i - 1], FMinIndices[i - 1]);
|
||||||
while FValidationLengths[indices[i - 1], indices[i]] > Length(FBlocks[i - 1]) do
|
while FValidationLengths[indices[i - 1], indices[i]] > Length(FBlocks[i - 1].Pattern) do
|
||||||
begin
|
begin
|
||||||
Dec(i);
|
Dec(i);
|
||||||
Inc(indices[i]);
|
Inc(indices[i]);
|
||||||
|
@ -686,7 +703,7 @@ begin
|
||||||
k := high;
|
k := high;
|
||||||
while (k > 0)
|
while (k > 0)
|
||||||
and ((indices[k] = FValidation.Count)
|
and ((indices[k] = FValidation.Count)
|
||||||
or (FValidationLengths[indices[k - 1], indices[k] + 1] > Length(FBlocks[k - 1]))) do
|
or (FValidationLengths[indices[k - 1], indices[k] + 1] > Length(FBlocks[k - 1].Pattern))) do
|
||||||
Dec(k);
|
Dec(k);
|
||||||
Inc(indices[k]);
|
Inc(indices[k]);
|
||||||
until k = 0;
|
until k = 0;
|
||||||
|
|
Loading…
Reference in New Issue