From 5808ec24f2dc4963d96e0175a68894d029cacb76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20M=C3=BCller?= Date: Thu, 14 Mar 2024 11:42:09 +0100 Subject: [PATCH] Added polynomials --- AdventOfCode.lpi | 4 ++ UPolynomial.pas | 106 +++++++++++++++++++++++++++++++++ tests/AdventOfCodeFPCUnit.lpi | 4 ++ tests/AdventOfCodeFPCUnit.lpr | 2 +- tests/UPolynomialTestCases.pas | 94 +++++++++++++++++++++++++++++ 5 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 UPolynomial.pas create mode 100644 tests/UPolynomialTestCases.pas diff --git a/AdventOfCode.lpi b/AdventOfCode.lpi index ca33018..5174e60 100644 --- a/AdventOfCode.lpi +++ b/AdventOfCode.lpi @@ -141,6 +141,10 @@ + + + + diff --git a/UPolynomial.pas b/UPolynomial.pas new file mode 100644 index 0000000..141c838 --- /dev/null +++ b/UPolynomial.pas @@ -0,0 +1,106 @@ +{ + Solutions to the Advent Of Code. + Copyright (C) 2024 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 UPolynomial; + +{$mode ObjFPC}{$H+} + +interface + +uses + Classes, SysUtils, UBigInt; + +type + TInt64Array = array of Int64; + + { TBigIntPolynomial } + + TBigIntPolynomial = object + private + FCoefficients: array of TBigInt; + public + function CalcValueAt(const AX: Int64): TBigInt; + function IsEqualTo(const AOther: TBigIntPolynomial): Boolean; + class function Create(const ACoefficients: array of TBigInt): TBigIntPolynomial; static; + end; + + { Operators } + + operator = (const A, B: TBigIntPolynomial): Boolean; + operator <> (const A, B: TBigIntPolynomial): Boolean; + +implementation + +{ TBigIntPolynomial } + +function TBigIntPolynomial.CalcValueAt(const AX: Int64): TBigInt; +var + i: Integer; +begin + Result := TBigInt.Zero; + for i := High(FCoefficients) downto 0 do + Result := Result * AX + FCoefficients[i]; +end; + +function TBigIntPolynomial.IsEqualTo(const AOther: TBigIntPolynomial): Boolean; +var + i: Integer; +begin + if Length(FCoefficients) = Length(AOther.FCoefficients) then + begin + Result := True; + for i := 0 to Length(FCoefficients) - 1 do + if FCoefficients[i] <> AOther.FCoefficients[i] then + begin + Result := False; + Break; + end; + end + else + Result := False; +end; + +class function TBigIntPolynomial.Create(const ACoefficients: array of TBigInt): TBigIntPolynomial; +var + high, i: integer; +begin + high := 1; + for i := Length(ACoefficients) - 1 downto 1 do + if ACoefficients[i] <> 0 then + begin + high := i; + Break; + end; + SetLength(Result.FCoefficients, high + 1); + for i := 0 to high do + Result.FCoefficients[i] := ACoefficients[i]; +end; + +{ Operators } + +operator = (const A, B: TBigIntPolynomial): Boolean; +begin + Result := A.IsEqualTo(B); +end; + +operator <> (const A, B: TBigIntPolynomial): Boolean; +begin + Result := not A.IsEqualTo(B); +end; + +end. + diff --git a/tests/AdventOfCodeFPCUnit.lpi b/tests/AdventOfCodeFPCUnit.lpi index 0c232ac..dcef8d9 100644 --- a/tests/AdventOfCodeFPCUnit.lpi +++ b/tests/AdventOfCodeFPCUnit.lpi @@ -140,6 +140,10 @@ + + + + diff --git a/tests/AdventOfCodeFPCUnit.lpr b/tests/AdventOfCodeFPCUnit.lpr index 1da4c13..eba70d8 100644 --- a/tests/AdventOfCodeFPCUnit.lpr +++ b/tests/AdventOfCodeFPCUnit.lpr @@ -9,7 +9,7 @@ uses UHotSpringsTestCases, UPointOfIncidenceTestCases, UParabolicReflectorDishTestCases, ULensLibraryTestCases, UFloorWillBeLavaTestCases, UClumsyCrucibleTestCases, ULavaductLagoonTestCases, UAplentyTestCases, UPulsePropagationTestCases, UStepCounterTestCases, USandSlabsTestCases, ULongWalkTestCases, - UNeverTellMeTheOddsTestCases; + UNeverTellMeTheOddsTestCases, UPolynomialTestCases; {$R *.res} diff --git a/tests/UPolynomialTestCases.pas b/tests/UPolynomialTestCases.pas new file mode 100644 index 0000000..703f538 --- /dev/null +++ b/tests/UPolynomialTestCases.pas @@ -0,0 +1,94 @@ +{ + Solutions to the Advent Of Code. + Copyright (C) 2024 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 UPolynomialTestCases; + +{$mode ObjFPC}{$H+} + +interface + +uses + Classes, SysUtils, fpcunit, testregistry, UPolynomial, UBigInt; + +type + + { TBigIntPolynomialTestCase } + + TBigIntPolynomialTestCase = class(TTestCase) + published + procedure TestEqual; + procedure TestUnequalSameLength; + procedure TestUnequalDifferentLength; + procedure TestTrimLeadingZeros; + procedure TestBisectionRootIsolation; + end; + +implementation + +{ TBigIntPolynomialTestCase } + +procedure TBigIntPolynomialTestCase.TestEqual; +var + a, b: TBigIntPolynomial; +begin + a := TBigIntPolynomial.Create([10, 7, 5, 1034]); + b := TBigIntPolynomial.Create([10, 7, 5, 1034]); + AssertTrue('Polynomials are not equal.', a = b); +end; + +procedure TBigIntPolynomialTestCase.TestUnequalSameLength; +var + a, b: TBigIntPolynomial; +begin + a := TBigIntPolynomial.Create([103, 7, 5, 10]); + b := TBigIntPolynomial.Create([1034, 7, 5, 10]); + AssertTrue('Polynomials are equal.', a <> b); +end; + +procedure TBigIntPolynomialTestCase.TestUnequalDifferentLength; +var + a, b: TBigIntPolynomial; +begin + a := TBigIntPolynomial.Create([40000, 10, 7, 5, 1034]); + b := TBigIntPolynomial.Create([10, 7, 5, 1034]); + AssertTrue('Polynomials are equal.', a <> b); +end; + +procedure TBigIntPolynomialTestCase.TestTrimLeadingZeros; +var + a, b: TBigIntPolynomial; +begin + a := TBigIntPolynomial.Create([10, 7, 5, 1034, 0, 0]); + b := TBigIntPolynomial.Create([10, 7, 5, 1034]); + AssertTrue('Polynomials are not equal.', a = b); +end; + +procedure TBigIntPolynomialTestCase.TestBisectionRootIsolation; +var + a: TBigIntPolynomial; +begin + // y = 3 * (x - 34000) * (x - 23017) * (x - 5) * (x^2 - 19) * (x + 112) + // = 3 * x^6 - 170730 * x^5 + 2329429920 * x^4 + 251300082690 * x^3 - 1270471872603 * x^2 + 4774763204640 * x - 24979889760000 + a := TBigIntPolynomial.Create([-24979889760000, 4774763204640, -1270471872603, 251300082690, 2329429920, -170730, 3]); + Fail('Not implemented'); +end; + +initialization + + RegisterTest(TBigIntPolynomialTestCase); +end. +