{ Solutions to the Advent Of Code. Copyright (C) 2023 Stefan Müller This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . } unit UMirageMaintenance; {$mode ObjFPC}{$H+} interface uses Classes, SysUtils, Generics.Collections, USolver; type { TMirageMaintenance } TMirageMaintenance = class(TSolver) private FN: Integer; FLagrangePolynomialsInN, FLagrangePolynomialsInMinusOne: specialize TList; procedure CalcLagrangePolynomials; public constructor Create; destructor Destroy; override; procedure ProcessDataLine(const ALine: string); override; procedure Finish; override; function GetDataFileName: string; override; function GetPuzzleName: string; override; end; implementation { TMirageMaintenance } procedure TMirageMaintenance.CalcLagrangePolynomials; var sign1, sign2, i, j: Integer; begin FLagrangePolynomialsInN.Clear; FLagrangePolynomialsInMinusOne.Clear; if FN mod 2 = 0 then sign1 := -1 else sign1 := 1; sign2 := 1; // Calculates the polynomials in N and -1. for i := 0 to FN - 1 do begin FLagrangePolynomialsInN.Add(sign1); sign1 := -sign1; FLagrangePolynomialsInMinusOne.Add(sign2); sign2 := -sign2; if i < FN - FN div 2 then begin // Multiplies by the non-cancelled numerator terms. for j := FN - i + 1 to FN do FLagrangePolynomialsInN[i] := FLagrangePolynomialsInN[i] * j; // Divides by the non-cancelled denominator terms. for j := 2 to i do FLagrangePolynomialsInN[i] := FLagrangePolynomialsInN[i] div j; end else begin // Multiplies by the non-cancelled numerator terms. for j := i + 1 to FN do FLagrangePolynomialsInN[i] := FLagrangePolynomialsInN[i] * j; // Divides by the non-cancelled over-counted numerator term. FLagrangePolynomialsInN[i] := FLagrangePolynomialsInN[i] div (FN - i); // Divides by the non-cancelled denominator terms. for j := 2 to FN - i - 1 do FLagrangePolynomialsInN[i] := FLagrangePolynomialsInN[i] div j; end; if i < FN div 2 then begin // Multiplies by the non-cancelled numerator terms. for j := FN - i to FN do FLagrangePolynomialsInMinusOne[i] := FLagrangePolynomialsInMinusOne[i] * j; // Divides by the non-cancelled denominator terms. for j := 2 to i + 1 do FLagrangePolynomialsInMinusOne[i] := FLagrangePolynomialsInMinusOne[i] div j; end else begin // Multiplies by the non-cancelled numerator terms. for j := i + 2 to FN do FLagrangePolynomialsInMinusOne[i] := FLagrangePolynomialsInMinusOne[i] * j; // Divides by the non-cancelled denominator terms. for j := 2 to FN - i - 1 do FLagrangePolynomialsInMinusOne[i] := FLagrangePolynomialsInMinusOne[i] div j; end; end; end; constructor TMirageMaintenance.Create; begin FLagrangePolynomialsInN := specialize TList.Create; FLagrangePolynomialsInMinusOne := specialize TList.Create; FN := 0; end; destructor TMirageMaintenance.Destroy; begin FLagrangePolynomialsInN.Free; FLagrangePolynomialsInMinusOne.Free; inherited Destroy; end; procedure TMirageMaintenance.ProcessDataLine(const ALine: string); var split: TStringArray; i, y: Integer; p: Int64; begin split := ALine.Split(' '); if Length(split) <> FN then begin FN := Length(split); CalcLagrangePolynomials; end; for i := 0 to FN - 1 do begin y := StrToInt(split[i]); p := y * FLagrangePolynomialsInN[i]; Inc(FPart1, p); p := y * FLagrangePolynomialsInMinusOne[i]; Inc(FPart2, p); end; end; procedure TMirageMaintenance.Finish; begin end; function TMirageMaintenance.GetDataFileName: string; begin Result := 'mirage_maintenance.txt'; end; function TMirageMaintenance.GetPuzzleName: string; begin Result := 'Day 9: Mirage Maintenance'; end; end.