Updated day 12 WIP performance refactor
- Added combinations calculation directly to the multi-index enumerable (TValidationPositionOffsets) and added new intermediate derived class TAccumulatedCombinationsMultiIndexStrategy to make this reusable for the other enumerables - Removed TBinomialCoefficientCache instances and used new global instance instead - Renamed TValidationToDamageAssignments to TDamageToValidationAssignments
This commit is contained in:
parent
3f7fb4a548
commit
ec6928679a
|
@ -41,6 +41,7 @@ const
|
||||||
|
|
||||||
type
|
type
|
||||||
TIntegerList = specialize TList<Integer>;
|
TIntegerList = specialize TList<Integer>;
|
||||||
|
TInt64Array = array of Int64;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
|
|
@ -63,9 +63,9 @@ type
|
||||||
end;
|
end;
|
||||||
TBlocks = specialize TObjectList<TBlock>;
|
TBlocks = specialize TObjectList<TBlock>;
|
||||||
|
|
||||||
{ TValidationToDamageAssignments }
|
{ TDamageToValidationAssignments }
|
||||||
|
|
||||||
TValidationToDamageAssignments = class(TEnumerableMultiIndexStrategy)
|
TDamageToValidationAssignments = class(TEnumerableMultiIndexStrategy)
|
||||||
private
|
private
|
||||||
FValidation: TIntegerList;
|
FValidation: TIntegerList;
|
||||||
FValidationLengths: TValidationLengths;
|
FValidationLengths: TValidationLengths;
|
||||||
|
@ -92,14 +92,34 @@ type
|
||||||
|
|
||||||
TValidationPositionInfos = specialize TList<TValidationPositionInfo>;
|
TValidationPositionInfos = specialize TList<TValidationPositionInfo>;
|
||||||
|
|
||||||
|
TConditionRecord = class;
|
||||||
|
|
||||||
|
{ TAccumulatedCombinationsMultiIndexStrategy }
|
||||||
|
|
||||||
|
TAccumulatedCombinationsMultiIndexStrategy = class(TEnumerableMultiIndexStrategy)
|
||||||
|
private
|
||||||
|
FAccumulatedCombinations: TInt64Array;
|
||||||
|
protected
|
||||||
|
function CalcCombinations(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer): Int64; virtual;
|
||||||
|
abstract;
|
||||||
|
function UpdateCombinations(const AValidationResult: TIndexValidationResult; constref ACurrentIndexArray:
|
||||||
|
TIndexArray; const ACurrentIndex: Integer): TIndexValidationResult;
|
||||||
|
public
|
||||||
|
function GetCombinations: Int64;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TValidationPositionOffsets }
|
{ TValidationPositionOffsets }
|
||||||
|
|
||||||
TValidationPositionOffsets = class(TEnumerableMultiIndexStrategy)
|
TValidationPositionOffsets = class(TAccumulatedCombinationsMultiIndexStrategy)
|
||||||
private
|
private
|
||||||
FValidation: TIntegerList;
|
FConditionRecord: TConditionRecord;
|
||||||
FPositionInfos: TValidationPositionInfos;
|
FPositionInfos: TValidationPositionInfos;
|
||||||
|
FBlockLength, FStartIndex, FStopIndex: Integer;
|
||||||
|
protected
|
||||||
|
function CalcCombinations(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer): Int64; override;
|
||||||
public
|
public
|
||||||
constructor Create(constref AValidation: TIntegerList; constref APositionInfos: TValidationPositionInfos);
|
constructor Create(constref AConditionRecord: TConditionRecord; constref APositionInfos: TValidationPositionInfos;
|
||||||
|
const ABlockLength, AStartIndex, AStopIndex: Integer);
|
||||||
function GetCardinality: Integer; override;
|
function GetCardinality: Integer; override;
|
||||||
function TryGetStartIndexValue(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer;
|
function TryGetStartIndexValue(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer;
|
||||||
out AStartIndexValue: Integer): Boolean; override;
|
out AStartIndexValue: Integer): Boolean; override;
|
||||||
|
@ -111,7 +131,6 @@ type
|
||||||
|
|
||||||
TConditionRecord = class
|
TConditionRecord = class
|
||||||
private
|
private
|
||||||
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: TBlocks;
|
FBlocks: TBlocks;
|
||||||
|
@ -129,17 +148,13 @@ type
|
||||||
function CalcCombinationsBlockSingleValidation(constref ABlock: TBlock; const AIndex: Integer): Int64;
|
function CalcCombinationsBlockSingleValidation(constref ABlock: TBlock; const AIndex: Integer): Int64;
|
||||||
function CalcCombinationsBlockMultiValidations(constref ABlock: TBlock; constref AIndices: TIndexArray;
|
function CalcCombinationsBlockMultiValidations(constref ABlock: TBlock; constref AIndices: TIndexArray;
|
||||||
const AStartIndex, AStopIndex: Integer): Int64;
|
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;
|
|
||||||
public
|
public
|
||||||
constructor Create(constref ABinomialCoefficients: TBinomialCoefficientCache);
|
constructor Create;
|
||||||
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?
|
function CalcCombinationsWildcardSequence(const ASequenceLength, AStartIndex, AStopIndex: Integer): Int64;
|
||||||
//property Blocks: TBlocks read FBlocks;
|
|
||||||
property Validation: TIntegerList read FValidation;
|
property Validation: TIntegerList read FValidation;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -147,8 +162,6 @@ type
|
||||||
|
|
||||||
THotSprings = class(TSolver)
|
THotSprings = class(TSolver)
|
||||||
private
|
private
|
||||||
// Keeping the binomial coefficients calculator here so it can be shared for all lines.
|
|
||||||
FBinomialCoefficients: TBinomialCoefficientCache;
|
|
||||||
// TODO: Remove FDebugIndex.
|
// TODO: Remove FDebugIndex.
|
||||||
FDebugIndex: Integer;
|
FDebugIndex: Integer;
|
||||||
public
|
public
|
||||||
|
@ -206,9 +219,9 @@ begin
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TValidationToDamageAssignments }
|
{ TDamageToValidationAssignments }
|
||||||
|
|
||||||
function TValidationToDamageAssignments.CalcValidationSpan(constref ACurrentIndexArray: TIndexArray;
|
function TDamageToValidationAssignments.CalcValidationSpan(constref ACurrentIndexArray: TIndexArray;
|
||||||
const ALastDamageIndex, AValidationNumber: Integer): Integer;
|
const ALastDamageIndex, AValidationNumber: Integer): Integer;
|
||||||
var
|
var
|
||||||
spanStart: Integer;
|
spanStart: Integer;
|
||||||
|
@ -221,7 +234,7 @@ begin
|
||||||
Inc(Result, FDamages[ALastDamageIndex].Start - FDamages[spanStart].Start);
|
Inc(Result, FDamages[ALastDamageIndex].Start - FDamages[spanStart].Start);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TValidationToDamageAssignments.Create(constref AValidation: TIntegerList; constref AValidationLengths:
|
constructor TDamageToValidationAssignments.Create(constref AValidation: TIntegerList; constref AValidationLengths:
|
||||||
TValidationLengths; constref ADamages: TDamages; const AStartIndex, AStopIndex: Integer);
|
TValidationLengths; constref ADamages: TDamages; const AStartIndex, AStopIndex: Integer);
|
||||||
begin
|
begin
|
||||||
FValidation := AValidation;
|
FValidation := AValidation;
|
||||||
|
@ -231,12 +244,12 @@ begin
|
||||||
FValidationStopIndex := AStopIndex;
|
FValidationStopIndex := AStopIndex;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TValidationToDamageAssignments.GetCardinality: Integer;
|
function TDamageToValidationAssignments.GetCardinality: Integer;
|
||||||
begin
|
begin
|
||||||
Result := FDamages.Count;
|
Result := FDamages.Count;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TValidationToDamageAssignments.TryGetStartIndexValue(constref ACurrentIndexArray: TIndexArray;
|
function TDamageToValidationAssignments.TryGetStartIndexValue(constref ACurrentIndexArray: TIndexArray;
|
||||||
const ACurrentIndex: Integer; out AStartIndexValue: Integer): Boolean;
|
const ACurrentIndex: Integer; out AStartIndexValue: Integer): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Result := True;
|
||||||
|
@ -246,7 +259,7 @@ begin
|
||||||
AStartIndexValue := FValidationStartIndex;
|
AStartIndexValue := FValidationStartIndex;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TValidationToDamageAssignments.ValidateIndexValue(constref ACurrentIndexArray: TIndexArray;
|
function TDamageToValidationAssignments.ValidateIndexValue(constref ACurrentIndexArray: TIndexArray;
|
||||||
const ACurrentIndex: Integer): TIndexValidationResult;
|
const ACurrentIndex: Integer): TIndexValidationResult;
|
||||||
var
|
var
|
||||||
i, prev, firstSkip: Integer;
|
i, prev, firstSkip: Integer;
|
||||||
|
@ -296,13 +309,71 @@ begin
|
||||||
Result := ivrValid;
|
Result := ivrValid;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TAccumulatedCombinationsMultiIndexStrategy }
|
||||||
|
|
||||||
|
function TAccumulatedCombinationsMultiIndexStrategy.UpdateCombinations(const AValidationResult: TIndexValidationResult;
|
||||||
|
constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer): TIndexValidationResult;
|
||||||
|
var
|
||||||
|
combinations: Int64;
|
||||||
|
begin
|
||||||
|
Result := AValidationResult;
|
||||||
|
if Result = ivrValid then
|
||||||
|
begin
|
||||||
|
combinations := CalcCombinations(ACurrentIndexArray, ACurrentIndex);
|
||||||
|
if combinations = 0 then
|
||||||
|
Result := ivrBacktrack
|
||||||
|
else if ACurrentIndex > 0 then
|
||||||
|
FAccumulatedCombinations[ACurrentIndex] := combinations * FAccumulatedCombinations[ACurrentIndex - 1]
|
||||||
|
else begin
|
||||||
|
SetLength(FAccumulatedCombinations, GetCardinality);
|
||||||
|
FAccumulatedCombinations[ACurrentIndex] := combinations;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAccumulatedCombinationsMultiIndexStrategy.GetCombinations: Int64;
|
||||||
|
begin
|
||||||
|
Result := FAccumulatedCombinations[GetCardinality - 1];
|
||||||
|
end;
|
||||||
|
|
||||||
{ TValidationPositionOffsets }
|
{ TValidationPositionOffsets }
|
||||||
|
|
||||||
constructor TValidationPositionOffsets.Create(constref AValidation: TIntegerList; constref APositionInfos:
|
function TValidationPositionOffsets.CalcCombinations(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex:
|
||||||
TValidationPositionInfos);
|
Integer): Int64;
|
||||||
|
var
|
||||||
|
space, start, stop: Integer;
|
||||||
begin
|
begin
|
||||||
FValidation := AValidation;
|
stop := FPositionInfos[ACurrentIndex].ValidationIndex - 1;
|
||||||
|
if ACurrentIndex > 0 then
|
||||||
|
begin
|
||||||
|
space := ACurrentIndexArray[ACurrentIndex] - ACurrentIndexArray[ACurrentIndex - 1]
|
||||||
|
- FConditionRecord.Validation[FPositionInfos[ACurrentIndex - 1].ValidationIndex] - 2;
|
||||||
|
start := FPositionInfos[ACurrentIndex - 1].ValidationIndex + 1;
|
||||||
|
Result := FConditionRecord.CalcCombinationsWildcardSequence(space, start, stop);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
// Handles first calculated offset.
|
||||||
|
space := ACurrentIndexArray[0] - 2;
|
||||||
|
Result := FConditionRecord.CalcCombinationsWildcardSequence(space, FStartIndex, stop);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (Result > 0) and (ACurrentIndex + 1 = GetCardinality) then
|
||||||
|
begin
|
||||||
|
// Handles last calculated offset.
|
||||||
|
space := FBlockLength - ACurrentIndexArray[ACurrentIndex] - FConditionRecord.Validation[FPositionInfos.Last.ValidationIndex];
|
||||||
|
Result := Result * FConditionRecord.CalcCombinationsWildcardSequence(space, FPositionInfos.Last.ValidationIndex + 1, FStopIndex);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TValidationPositionOffsets.Create(constref AConditionRecord: TConditionRecord; constref APositionInfos:
|
||||||
|
TValidationPositionInfos; const ABlockLength, AStartIndex, AStopIndex: Integer);
|
||||||
|
begin
|
||||||
|
FConditionRecord := AConditionRecord;
|
||||||
FPositionInfos := APositionInfos;
|
FPositionInfos := APositionInfos;
|
||||||
|
FBlockLength := ABlockLength;
|
||||||
|
FStartIndex := AStartIndex;
|
||||||
|
FStopIndex := AStopIndex;
|
||||||
|
inherited Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TValidationPositionOffsets.GetCardinality: Integer;
|
function TValidationPositionOffsets.GetCardinality: Integer;
|
||||||
|
@ -317,13 +388,12 @@ var
|
||||||
begin
|
begin
|
||||||
info := FPositionInfos[ACurrentIndex];
|
info := FPositionInfos[ACurrentIndex];
|
||||||
// Calculates start value such that the validation number just includes MinEnd.
|
// Calculates start value such that the validation number just includes MinEnd.
|
||||||
//AStartIndexValue := info.MinEnd - FValidation[info.ValidationIndex] + 1;
|
|
||||||
AStartIndexValue := info.MinStart;
|
AStartIndexValue := info.MinStart;
|
||||||
// Adjusts start value to avoid overlap of this validation number with the previous one (the one from previous
|
// Adjusts start value to avoid overlap of this validation number with the previous one (the one from previous
|
||||||
// position info).
|
// position info).
|
||||||
if ACurrentIndex > 0 then
|
if ACurrentIndex > 0 then
|
||||||
AStartIndexValue := Max(AStartIndexValue,
|
AStartIndexValue := Max(AStartIndexValue,
|
||||||
ACurrentIndexArray[ACurrentIndex - 1] + FValidation[FPositionInfos[ACurrentIndex - 1].ValidationIndex] + 1);
|
ACurrentIndexArray[ACurrentIndex - 1] + FConditionRecord.Validation[FPositionInfos[ACurrentIndex - 1].ValidationIndex] + 1);
|
||||||
Result := True;
|
Result := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -334,6 +404,8 @@ begin
|
||||||
Result := ivrValid
|
Result := ivrValid
|
||||||
else
|
else
|
||||||
Result := ivrBacktrack;
|
Result := ivrBacktrack;
|
||||||
|
|
||||||
|
Result := UpdateCombinations(Result, ACurrentIndexArray, ACurrentIndex);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TConditionRecord }
|
{ TConditionRecord }
|
||||||
|
@ -413,7 +485,7 @@ function TConditionRecord.CalcCombinationsBlock(constref ABlock: TBlock; const A
|
||||||
var
|
var
|
||||||
i, j, k: Integer;
|
i, j, k: Integer;
|
||||||
indices: TIndexArray;
|
indices: TIndexArray;
|
||||||
validationToDamageAssignments: TValidationToDamageAssignments;
|
validationToDamageAssignments: TDamageToValidationAssignments;
|
||||||
begin
|
begin
|
||||||
{$ifdef debug}
|
{$ifdef debug}
|
||||||
Write(' ', ABlock.Pattern, ' ');
|
Write(' ', ABlock.Pattern, ' ');
|
||||||
|
@ -464,7 +536,7 @@ begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
|
|
||||||
// Assigns validation numbers to specific damages.
|
// Assigns validation numbers to specific damages.
|
||||||
validationToDamageAssignments := TValidationToDamageAssignments.Create(FValidation, FValidationLengths, ABlock.Damages,
|
validationToDamageAssignments := TDamageToValidationAssignments.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:');
|
||||||
|
@ -551,82 +623,17 @@ begin
|
||||||
WriteLn(' offsets');
|
WriteLn(' offsets');
|
||||||
{$endif}
|
{$endif}
|
||||||
Result := 0;
|
Result := 0;
|
||||||
validationPositionOffsets := TValidationPositionOffsets.Create(FValidation, positions);
|
validationPositionOffsets := TValidationPositionOffsets.Create(Self, positions, Length(ABlock.Pattern),
|
||||||
|
AStartIndex, AStopIndex);
|
||||||
for offsets in validationPositionOffsets do
|
for offsets in validationPositionOffsets do
|
||||||
Result := Result
|
Result := Result + validationPositionOffsets.GetCombinations;
|
||||||
+ CalcCombinationsBlockAssignedValidations(Length(ABlock.Pattern), positions, offsets, AStartIndex, AStopIndex);
|
|
||||||
validationPositionOffsets.Free;
|
validationPositionOffsets.Free;
|
||||||
|
|
||||||
positions.Free;
|
positions.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TConditionRecord.CalcCombinationsBlockAssignedValidations(const ABlockLength: Integer; constref APositionInfos:
|
constructor TConditionRecord.Create;
|
||||||
TValidationPositionInfos; constref AOffsets: TIndexArray; const AStartIndex, AStopIndex: Integer): Int64;
|
|
||||||
var
|
|
||||||
i, space: Integer;
|
|
||||||
begin
|
begin
|
||||||
{$ifdef debug}
|
|
||||||
Write(' ');
|
|
||||||
for i in AOffsets do
|
|
||||||
Write(i, ' ');
|
|
||||||
|
|
||||||
Write(' count/space/freedoms: ');
|
|
||||||
{$endif}
|
|
||||||
space := AOffsets[0] - 2;
|
|
||||||
Result := CalcCombinationsWildcardSequence(space, AStartIndex, APositionInfos[0].ValidationIndex - 1);
|
|
||||||
if Result = 0 then begin
|
|
||||||
{$ifdef debug}
|
|
||||||
WriteLn(' result: ', Result);
|
|
||||||
{$endif}
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
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 - 1);
|
|
||||||
if Result = 0 then begin
|
|
||||||
{$ifdef debug}
|
|
||||||
WriteLn(' result: ', Result);
|
|
||||||
{$endif}
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
space := ABlockLength - AOffsets[APositionInfos.Count - 1] - FValidation[APositionInfos.Last.ValidationIndex];
|
|
||||||
Result := Result * CalcCombinationsWildcardSequence(space, APositionInfos.Last.ValidationIndex + 1, AStopIndex);
|
|
||||||
{$ifdef debug}
|
|
||||||
WriteLn(' result: ', Result);
|
|
||||||
{$endif}
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TConditionRecord.CalcCombinationsWildcardSequence(const ASequenceLength, AStartIndex, AStopIndex: Integer):
|
|
||||||
Int64;
|
|
||||||
var
|
|
||||||
count, freedoms: Integer;
|
|
||||||
begin
|
|
||||||
if AStartIndex < AStopIndex + 1 then
|
|
||||||
begin
|
|
||||||
count := AStopIndex + 1 - AStartIndex;
|
|
||||||
freedoms := ASequenceLength - FValidationLengths[AStartIndex, AStopIndex + 1];
|
|
||||||
{$ifdef debug}
|
|
||||||
Write(count, '/', ASequenceLength, '/', freedoms, ' ');
|
|
||||||
{$endif}
|
|
||||||
if freedoms >= 0 then
|
|
||||||
Result := FBinomialCoefficients.Get(count + freedoms, freedoms)
|
|
||||||
else
|
|
||||||
Result := 0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
Result := 1;
|
|
||||||
{$ifdef debug}
|
|
||||||
Write('X ');
|
|
||||||
{$endif}
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TConditionRecord.Create(constref ABinomialCoefficients: TBinomialCoefficientCache);
|
|
||||||
begin
|
|
||||||
FBinomialCoefficients := ABinomialCoefficients;
|
|
||||||
|
|
||||||
FBlocks := TBlocks.Create;
|
FBlocks := TBlocks.Create;
|
||||||
FValidation := TIntegerList.Create;
|
FValidation := TIntegerList.Create;
|
||||||
end;
|
end;
|
||||||
|
@ -710,17 +717,40 @@ begin
|
||||||
WriteLn(' missed: ', misses, '/', count);
|
WriteLn(' missed: ', misses, '/', count);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TConditionRecord.CalcCombinationsWildcardSequence(const ASequenceLength, AStartIndex, AStopIndex: Integer):
|
||||||
|
Int64;
|
||||||
|
var
|
||||||
|
count, freedoms: Integer;
|
||||||
|
begin
|
||||||
|
if AStartIndex < AStopIndex + 1 then
|
||||||
|
begin
|
||||||
|
count := AStopIndex + 1 - AStartIndex;
|
||||||
|
freedoms := ASequenceLength - FValidationLengths[AStartIndex, AStopIndex + 1];
|
||||||
|
{$ifdef debug}
|
||||||
|
Write(count, '/', ASequenceLength, '/', freedoms, ' ');
|
||||||
|
{$endif}
|
||||||
|
if freedoms >= 0 then
|
||||||
|
Result := BinomialCoefficients.Get(count + freedoms, freedoms)
|
||||||
|
else
|
||||||
|
Result := 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
Result := 1;
|
||||||
|
{$ifdef debug}
|
||||||
|
Write('X ');
|
||||||
|
{$endif}
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ THotSprings }
|
{ THotSprings }
|
||||||
|
|
||||||
constructor THotSprings.Create;
|
constructor THotSprings.Create;
|
||||||
begin
|
begin
|
||||||
FDebugIndex := 0;
|
FDebugIndex := 0;
|
||||||
FBinomialCoefficients := TBinomialCoefficientCache.Create;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor THotSprings.Destroy;
|
destructor THotSprings.Destroy;
|
||||||
begin
|
begin
|
||||||
FBinomialCoefficients.Free;
|
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -736,8 +766,8 @@ begin
|
||||||
WriteLn;
|
WriteLn;
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
conditionRecord1 := TConditionRecord.Create(FBinomialCoefficients);
|
conditionRecord1 := TConditionRecord.Create;
|
||||||
conditionRecord2 := TConditionRecord.Create(FBinomialCoefficients);
|
conditionRecord2 := TConditionRecord.Create;
|
||||||
|
|
||||||
mainSplit := ALine.Split([' ']);
|
mainSplit := ALine.Split([' ']);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue