diff --git a/solvers/UHotSprings.pas b/solvers/UHotSprings.pas index e155e57..601823f 100644 --- a/solvers/UHotSprings.pas +++ b/solvers/UHotSprings.pas @@ -22,7 +22,7 @@ unit UHotSprings; interface uses - Classes, SysUtils, Math, Generics.Collections, USolver, UCommon; + Classes, SysUtils, Math, Generics.Collections, USolver, UCommon, UMultiIndexEnumerator; const COperationalChar = '.'; @@ -30,7 +30,7 @@ const CWildcardChar = '?'; //COperationalPatternChars = [COperationalChar, CWildcardChar]; //CDamagedPatternChars = [CDamagedChar, CWildcardChar]; - CPart2Repetition = 2; + CPart2Repetition = 1; type @@ -52,6 +52,7 @@ type TValidationLengths = array of array of Integer; //TPatternLengths = array of Integer; + // TODO: TIntegerArray probably not needed. TIntegerArray = array of Integer; { TDamage } @@ -61,16 +62,62 @@ type end; TDamages = specialize TList; + // TODO: Instead of using TDamagesBlocks, "block" should be a record of a string and its associated list TDamages. TDamagesBlocks = specialize TObjectList; + { TValidationToDamageAssignments } + + TValidationToDamageAssignments = class(TEnumerableMultiIndexStrategy) + private + FValidation: TIntegerList; + FValidationLengths: TValidationLengths; + FDamages: TDamages; + FValidationStartIndex, FValidationStopIndex: Integer; + // Calculates "span", the length of all damages for this validation number combined. + function CalcValidationSpan(constref ACurrentIndexArray: TIndexArray; const ALastDamageIndex, AValidationNumber: + Integer): Integer; + public + constructor Create(constref AValidation: TIntegerList; constref AValidationLengths: TValidationLengths; + constref ADamages: TDamages; const AStartIndex, AStopIndex: Integer); + function GetCardinality: Integer; override; + function TryGetStartIndexValue(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer; + out AStartIndexValue: Integer): Boolean; override; + function ValidateIndexValue(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer): + TIndexValidationResult; override; + end; + + { TValidationPositionInfo } + + TValidationPositionInfo = record + ValidationIndex: Integer; + MinStart, MaxStart: Byte; + end; + + TValidationPositionInfos = specialize TList; + + { TValidationPositionOffsets } + + TValidationPositionOffsets = class(TEnumerableMultiIndexStrategy) + private + FValidation: TIntegerList; + FPositionInfos: TValidationPositionInfos; + public + constructor Create(constref AValidation: TIntegerList; constref APositionInfos: TValidationPositionInfos); + function GetCardinality: Integer; override; + function TryGetStartIndexValue(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer; + out AStartIndexValue: Integer): Boolean; override; + function ValidateIndexValue(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: Integer): + TIndexValidationResult; override; + end; + { TConditionRecord } TConditionRecord = class private FValidation: TIntegerList; - // List of non-empty, maximum-length parts of the pattern without operational springs. - FBlockPatterns: TStringList; - // Array 'a' of accumulated validation block lengths. 'a[i, j]' denotes the combined length of consecutive + // List of non-empty, maximum-length parts of the pattern without operational springs ("blocks"). + FBlocks: TStringList; + // 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 // them. FValidationLengths: TValidationLengths; @@ -78,34 +125,39 @@ type //FPatternLengths: TPatternLengths; // Array 'a' of minimum indices 'a[i]', such that all remaining validation numbers starting at index 'a[i] - 1' - // cannot fit into the remaining block patterns starting at 'FBlockPatterns[i]'. + // cannot fit into the remaining blocks starting at 'FBlocks[i]'. FMinIndices: TIntegerArray; - // List 'a' of lists of damages in a block pattern. Each list of damages 'a[i]' contains exactly one entry for each - // block of consecutive damages characters in the i-th block pattern. + // 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; - //// Returns an array 'a' of accumulated pattern block lengths. 'a[i]' denotes the combined length of consecutive - //// pattern blocks starting with 'FBlockPatterns[i]' and all following with a single space in between each pair of + //// Returns an array 'a' of accumulated block lengths. 'a[i]' denotes the combined length of consecutive + //// blocks starting with 'FBlocks[i]' and all following with a single space in between each pair of //// them. + //// Should be "function CalcBlockLengths: TBlockLengths; //function CalcPatternLengths: TPatternLengths; procedure InitMinIndices; function CalcCombinations(constref AIndices: TIntegerArray): Int64; - function CalcCombinationsSingleBlock(const APattern: string; constref ADamages: TDamages; const AStartIndex, - AStopIndex: Integer): Int64; - function CalcCombinationsSingleBlockSingleValidation(const APattern: string; constref ADamages: TDamages; + function CalcCombinationsBlock(const ABlock: string; constref ADamages: TDamages; const AStartIndex, AStopIndex: + Integer): Int64; + function CalcCombinationsBlockSingleValidation(const ABlockLength: Integer; constref ADamages: TDamages; const AIndex: Integer): Int64; - function ParseDamages(const APattern: string): TDamages; + function CalcCombinationsBlockMultiValidations(const ABlockLength: Integer; constref ADamages: TDamages; + 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 ParseDamages(const ABlock: string): TDamages; public - property BlockPatterns: TStringList read FBlockPatterns; + property Blocks: TStringList read FBlocks; property Validation: TIntegerList read FValidation; constructor Create; destructor Destroy; override; - // Adds all non-empty, maximum-length parts of the pattern without operational springs. - procedure AddBlockPatterns(const APattern: string); + // Adds all non-empty, maximum-length parts of the pattern without operational springs ("blocks"). + procedure AddBlocks(const APattern: string); function GenerateBlockAssignments: Int64; end; @@ -146,6 +198,137 @@ implementation // Write(' |'); //end; +{ TValidationToDamageAssignments } + +function TValidationToDamageAssignments.CalcValidationSpan(constref ACurrentIndexArray: TIndexArray; + const ALastDamageIndex, AValidationNumber: Integer): Integer; +var + spanStart: Integer; +begin + spanStart := ALastDamageIndex; + while (spanStart > 0) and (ACurrentIndexArray[spanStart - 1] = AValidationNumber) do + Dec(spanStart); + Result := FDamages[ALastDamageIndex].Length; + if spanStart < ALastDamageIndex then + Inc(Result, FDamages[ALastDamageIndex].Start - FDamages[spanStart].Start); +end; + +constructor TValidationToDamageAssignments.Create(constref AValidation: TIntegerList; constref AValidationLengths: + TValidationLengths; constref ADamages: TDamages; const AStartIndex, AStopIndex: Integer); +begin + FValidation := AValidation; + FValidationLengths := AValidationLengths; + FDamages := ADamages; + FValidationStartIndex := AStartIndex; + FValidationStopIndex := AStopIndex; +end; + +function TValidationToDamageAssignments.GetCardinality: Integer; +begin + Result := FDamages.Count; +end; + +function TValidationToDamageAssignments.TryGetStartIndexValue(constref ACurrentIndexArray: TIndexArray; + const ACurrentIndex: Integer; out AStartIndexValue: Integer): Boolean; +begin + Result := True; + if ACurrentIndex > 0 then + AStartIndexValue := ACurrentIndexArray[ACurrentIndex - 1] + else + AStartIndexValue := FValidationStartIndex; +end; + +function TValidationToDamageAssignments.ValidateIndexValue(constref ACurrentIndexArray: TIndexArray; + const ACurrentIndex: Integer): TIndexValidationResult; +var + i, prev, firstSkip: Integer; +begin + i := ACurrentIndexArray[ACurrentIndex]; + if i > FValidationStopIndex then + begin + Result := ivrBacktrack; + Exit; + end; + + // Checks if there is enough space after this damage for remaining validation numbers. + if FValidationLengths[i + 1, FValidationStopIndex + 1] + 1 > FDamages[ACurrentIndex].CharsRemaining then + begin + Result := ivrSkip; + Exit; + end; + + // Checks if there is enough space before this damage for previous validation numbers. + if (FValidationStartIndex < i) and (FValidationLengths[FValidationStartIndex, i] + 1 >= FDamages[ACurrentIndex].Start) then + begin + Result := ivrBacktrack; + Exit; + end; + + // Checks if there is enough space between previous and this damage for skipped validation numbers. + if ACurrentIndex > 0 then + begin + prev := ACurrentIndex - 1; + firstSkip := ACurrentIndexArray[prev] + 1; + if (firstSkip < i) and (FValidationLengths[firstSkip, i] + 2 > FDamages[ACurrentIndex].Start - FDamages[prev].Start - FDamages[prev].Length) then + begin + Result := ivrBacktrack; + Exit; + end; + end; + + // Checks if span is small enough to fit within this validation number. + if FValidation[i] < CalcValidationSpan(ACurrentIndexArray, ACurrentIndex, i) then + begin + Result := ivrSkip; + Exit; + end; + + Result := ivrValid; +end; + +{ TValidationPositionOffsets } + +constructor TValidationPositionOffsets.Create(constref AValidation: TIntegerList; constref APositionInfos: + TValidationPositionInfos); +begin + FValidation := AValidation; + FPositionInfos := APositionInfos; +end; + +function TValidationPositionOffsets.GetCardinality: Integer; +begin + Result := FPositionInfos.Count; +end; + +function TValidationPositionOffsets.TryGetStartIndexValue(constref ACurrentIndexArray: TIndexArray; + const ACurrentIndex: Integer; out AStartIndexValue: Integer): Boolean; +var + info: TValidationPositionInfo; +begin + info := FPositionInfos[ACurrentIndex]; + // Calculates start value such that the validation number just includes MinEnd. + //AStartIndexValue := info.MinEnd - FValidation[info.ValidationIndex] + 1; + AStartIndexValue := info.MinStart; + //////////////////////////////////////////// + Assert(AStartIndexValue > 0, 'start value '); + //////////////////////////////////////////// + // Adjusts start value to avoid overlap of this validation number with the previous one (the one from previous + // position info). + if ACurrentIndex > 0 then + AStartIndexValue := Max(AStartIndexValue, + ACurrentIndexArray[ACurrentIndex - 1] + FValidation[FPositionInfos[ACurrentIndex - 1].ValidationIndex] + 1); + Result := True; +end; + +function TValidationPositionOffsets.ValidateIndexValue(constref ACurrentIndexArray: TIndexArray; const ACurrentIndex: + Integer): TIndexValidationResult; +begin + if ACurrentIndexArray[ACurrentIndex] <= FPositionInfos[ACurrentIndex].MaxStart then + Result := ivrValid + else + Result := ivrBacktrack; +end; + { TConditionRecord } procedure TConditionRecord.InitValidationLengths; @@ -179,15 +362,15 @@ procedure TConditionRecord.InitMinIndices; var i, j, patternsLength: Integer; begin - SetLength(FMinIndices, FBlockPatterns.Count - 1); - patternsLength := Length(FBlockPatterns[FBlockPatterns.Count - 1]); + SetLength(FMinIndices, FBlocks.Count - 1); + patternsLength := Length(FBlocks[FBlocks.Count - 1]); j := FValidation.Count; - for i := FBlockPatterns.Count - 2 downto 0 do + for i := FBlocks.Count - 2 downto 0 do begin while (j >= 0) and (FValidationLengths[j, FValidation.Count] <= patternsLength) do Dec(j); FMinIndices[i] := j + 1; - patternsLength := patternsLength + 1 + Length(FBlockPatterns[i]); + patternsLength := patternsLength + 1 + Length(FBlocks[i]); end; end; @@ -201,20 +384,21 @@ begin Result := 1; i := 0; - while (Result > 0) and (i < FBlockPatterns.Count) do + while (Result > 0) and (i < FBlocks.Count) do begin - Result := Result * CalcCombinationsSingleBlock(FBlockPatterns[i], FDamagesBlocks[i], AIndices[i], AIndices[i + 1] - 1); + Result := Result * CalcCombinationsBlock(FBlocks[i], FDamagesBlocks[i], AIndices[i], AIndices[i + 1] - 1); Inc(i); end; end; -function TConditionRecord.CalcCombinationsSingleBlock(const APattern: string; constref ADamages: TDamages; - const AStartIndex, AStopIndex: Integer): Int64; +function TConditionRecord.CalcCombinationsBlock(const ABlock: string; constref ADamages: TDamages; const AStartIndex, + AStopIndex: Integer): Int64; var i, j, k: Integer; - indices: TIntegerArray; + indices: TIndexArray; + validationToDamageAssignments: TValidationToDamageAssignments; begin - Write(' ', APattern, ' '); + Write(' ', ABlock, ' '); for i := AStartIndex to AStopIndex do Write(FValidation[i], ' '); WriteLn; @@ -229,11 +413,10 @@ begin end // One validation number assigned to this block. else if AStartIndex = AStopIndex then - Result := CalcCombinationsSingleBlockSingleValidation(APattern, ADamages, AStartIndex) + Result := CalcCombinationsBlockSingleValidation(Length(ABlock), ADamages, AStartIndex) // Multiple validation numbers assigned to this block. else begin - SetLength(indices, ADamages.Count); - + /////////////////////////////// Write(' min before: '); for i := AStartIndex to AStopIndex do Write(FValidationLengths[AStartIndex, i + 1] - FValidation[i], ' '); @@ -243,7 +426,6 @@ begin Write(FValidationLengths[i, AStopIndex + 1] - FValidation[i], ' '); WriteLn; - /////////////////////////////// for i := 0 to ADamages.Count - 1 do begin WriteLn(' damage: start ',ADamages[i].Start, ', length ', ADamages[i].Length, ', remain ', ADamages[i].CharsRemaining); @@ -263,51 +445,34 @@ begin Result := 9999; // Assigns validation numbers to specific damages. - j := AStartIndex; - for i := 0 to ADamages.Count - 1 do + validationToDamageAssignments := TValidationToDamageAssignments.Create(FValidation, FValidationLengths, ADamages, + AStartIndex, AStopIndex); + WriteLn(' validation numbers (indices) per damages:'); + for indices in validationToDamageAssignments do begin - while (j <= AStopIndex) - // Enough space before damage for the other validation numbers? - and ((FValidationLengths[AStartIndex, j + 1] - FValidation[j] >= ADamages[i].Start) - // Enough space after damage for the other validation numbers? - // TODO: Is this true? Once the following check is true for given j, increasing j will not make it false, so set Result := 0 and break. - or (FValidationLengths[j, AStopIndex + 1] - FValidation[j] > ADamages[i].CharsRemaining) - // Damage itself small enough for this validation number? - or (FValidation[j] < ADamages[i].Length)) do - Inc(j); - - if (j > AStopIndex) then - begin - Result := 0; - Break; - end; - - indices[i] := j; + Write(' '); + for i := 0 to ADamages.Count - 1 do + Write(FValidation[indices[i]], ' '); + Write('( '); + for i := 0 to ADamages.Count - 1 do + Write(indices[i] - AStartIndex, ' '); + WriteLn(')'); + CalcCombinationsBlockMultiValidations(Length(ABlock), ADamages, indices, AStartIndex, AStopIndex); end; - - WriteLn(' validation number indices per damages:'); - Write(' '); - for i := 0 to ADamages.Count - 1 do - Write(indices[i], ' '); - Write('( '); - for i := 0 to ADamages.Count - 1 do - Write(indices[i] - AStartIndex, ' '); - WriteLn(')'); - - // TODO: Iterate over all possible assignments of validation numbers to specific damages. + validationToDamageAssignments.Free; end; WriteLn(' Result: ', Result); end; -function TConditionRecord.CalcCombinationsSingleBlockSingleValidation(const APattern: string; constref ADamages: +function TConditionRecord.CalcCombinationsBlockSingleValidation(const ABlockLength: Integer; constref ADamages: TDamages; const AIndex: Integer): Int64; var combinedDamagesLength: Integer; begin - if Length(APattern) < FValidation[AIndex] then + if ABlockLength < FValidation[AIndex] then Result := 0 else if ADamages.Count = 0 then - Result := Length(APattern) - FValidation[AIndex] + 1 + Result := ABlockLength - FValidation[AIndex] + 1 else begin combinedDamagesLength := ADamages.Last.Start + ADamages.Last.Length - ADamages.First.Start; if FValidation[AIndex] < combinedDamagesLength then @@ -316,23 +481,113 @@ begin Result := Min(Min(Min( ADamages.First.Start, FValidation[AIndex] - combinedDamagesLength + 1), - Length(APattern) - FValidation[AIndex] + 1), + ABlockLength - FValidation[AIndex] + 1), ADamages.Last.CharsRemaining + 1); end; end; end; -function TConditionRecord.ParseDamages(const APattern: string): TDamages; +function TConditionRecord.CalcCombinationsBlockMultiValidations(const ABlockLength: Integer; constref ADamages: + TDamages; constref AIndices: TIndexArray; const AStartIndex, AStopIndex: Integer): Int64; +var + i, high: Integer; + position: TValidationPositionInfo; + positions: TValidationPositionInfos; + validationPositionOffsets: TValidationPositionOffsets; + offsets: TIndexArray; +begin + positions := TValidationPositionInfos.Create; + high := Length(AIndices) - 1; + // Initializes first info record. + position.ValidationIndex := AIndices[0]; + position.MaxStart := ADamages[0].Start; + position.MinStart := 1; + for i := 1 to high do + if AIndices[i] <> position.ValidationIndex then + begin + // Finalizes current info record. + position.MaxStart := Min(position.MaxStart, ADamages[i].Start - 1 - FValidation[position.ValidationIndex]); + position.MinStart := Max(position.MinStart, + ADamages[i - 1].Start + ADamages[i - 1].Length - 1 - FValidation[position.ValidationIndex] + 1); + positions.Add(position); + // Initializes next info record. + position.ValidationIndex := AIndices[i]; + position.MaxStart := ADamages[i].Start; + position.MinStart := position.MinStart + FValidation[position.ValidationIndex] + 1; + end; + // Finalizes last info record. + position.MaxStart := Min(position.MaxStart, ABlockLength + 1 - FValidation[position.ValidationIndex]); + position.MinStart := Max(position.MinStart, + ADamages[high].Start + ADamages[high].Length - FValidation[position.ValidationIndex]); + positions.Add(position); + + WriteLn(' validation position infos'); + for position in positions do + WriteLn(' ', position.ValidationIndex, ' ', position.MinStart, ' ', position.MaxStart); + + WriteLn(' offsets'); + validationPositionOffsets := TValidationPositionOffsets.Create(FValidation, positions); + for offsets in validationPositionOffsets do + CalcCombinationsBlockAssignedValidations(ABlockLength, positions, offsets, AStartIndex, AStopIndex); + validationPositionOffsets.Free; + + positions.Free; +end; + +function TConditionRecord.CalcCombinationsBlockAssignedValidations(const ABlockLength: Integer; constref APositionInfos: + TValidationPositionInfos; constref AOffsets: TIndexArray; const AStartIndex, AStopIndex: Integer): Int64; +var + i, space, freedom, count: 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 '); + + WriteLn; +end; + +function TConditionRecord.ParseDamages(const ABlock: string): TDamages; var i, len: Integer; damage: TDamage; begin Result := TDamages.Create; damage.Length := 0; - len := Length(APattern); + len := Length(ABlock); for i := 1 to len do // The pattern must only contain damage and wildcard characters here. - if APattern[i] = CDamagedChar then + if ABlock[i] = CDamagedChar then begin if damage.Length = 0 then damage.Start := i; @@ -354,20 +609,20 @@ end; constructor TConditionRecord.Create; begin - FBlockPatterns := TStringList.Create; + FBlocks := TStringList.Create; FValidation := TIntegerList.Create; FDamagesBlocks := TDamagesBlocks.Create; end; destructor TConditionRecord.Destroy; begin - FBlockPatterns.Free; + FBlocks.Free; FValidation.Free; FDamagesBlocks.Free; inherited Destroy; end; -procedure TConditionRecord.AddBlockPatterns(const APattern: string); +procedure TConditionRecord.AddBlocks(const APattern: string); var split: TStringArray; part: string; @@ -376,7 +631,7 @@ begin for part in split do if Length(part) > 0 then begin - FBlockPatterns.Add(part); + FBlocks.Add(part); FDamagesBlocks.Add(ParseDamages(part)); end; end; @@ -399,11 +654,12 @@ begin //FPatternLengths := CalcPatternLengths; InitMinIndices; - SetLength(indices, FBlockPatterns.Count + 1); + SetLength(indices, FBlocks.Count + 1); high := Length(indices) - 2; indices[0] := 0; indices[high + 1] := FValidation.Count; + // TODO: Use TMultiIndexEnumerator for this. Result := 0; k := 0; repeat @@ -419,7 +675,7 @@ begin //WriteLn(j, ' ', FMinIndices[i - 1]); indices[i] := Max(indices[i - 1], FMinIndices[i - 1]); - while FValidationLengths[indices[i - 1], indices[i]] > Length(FBlockPatterns[i - 1]) do + while FValidationLengths[indices[i - 1], indices[i]] > Length(FBlocks[i - 1]) do begin Dec(i); Inc(indices[i]); @@ -428,7 +684,7 @@ begin Inc(i); end; - //if FValidationLengths[indices[0], indices[1]] > Length(FBlockPatterns[0]) then + //if FValidationLengths[indices[0], indices[1]] > Length(FBlocks[0]) then // Break; Result := Result + CalcCombinations(indices); @@ -436,7 +692,7 @@ begin k := high; while (k > 0) and ((indices[k] = FValidation.Count) - or (FValidationLengths[indices[k - 1], indices[k] + 1] > Length(FBlockPatterns[k - 1]))) do + or (FValidationLengths[indices[k - 1], indices[k] + 1] > Length(FBlocks[k - 1]))) do Dec(k); Inc(indices[k]); until k = 0; @@ -460,13 +716,13 @@ begin mainSplit := ALine.Split([' ']); // Adds blocks for part 1. - conditionRecord1.AddBlockPatterns(mainSplit[0]); + conditionRecord1.AddBlocks(mainSplit[0]); // Adds blocks for part 2. unfolded := mainSplit[0]; for i := 2 to CPart2Repetition do unfolded := unfolded + CWildcardChar + mainSplit[0]; - conditionRecord2.AddBlockPatterns(unfolded); + conditionRecord2.AddBlocks(unfolded); // Adds validation numbers. split := mainSplit[1].Split([',']); @@ -475,14 +731,14 @@ begin for i := 1 to CPart2Repetition do conditionRecord2.Validation.AddRange(conditionRecord1.Validation); - //for part in conditionRecord1.BlockPatterns do + //for part in conditionRecord1.Blocks do // WriteLn(part); //for i in conditionRecord1.Validation do // WriteLn(i); // //WriteLn; // -// for part in conditionRecord2.BlockPatterns do +// for part in conditionRecord2.Blocks do // WriteLn(part); // for i in conditionRecord2.Validation do // WriteLn(i); @@ -498,7 +754,7 @@ end; procedure THotSprings.Finish; begin - + ProcessDataLine('?????#??##??????#??????? 5,3,1,2,1'); end; function THotSprings.GetDataFileName: string;