Added binomial coefficient calculation
This commit is contained in:
parent
1d399cc5b6
commit
be0357befd
|
@ -161,6 +161,10 @@
|
||||||
<Filename Value="UMultiIndexEnumerator.pas"/>
|
<Filename Value="UMultiIndexEnumerator.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
</Unit>
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="UBinomialCoefficients.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit>
|
||||||
</Units>
|
</Units>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
{
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
}
|
||||||
|
|
||||||
|
unit UBinomialCoefficients;
|
||||||
|
|
||||||
|
{$mode ObjFPC}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, Generics.Collections;
|
||||||
|
|
||||||
|
type
|
||||||
|
TCardinalArray = array of Cardinal;
|
||||||
|
TCardinalArrays = specialize TList<TCardinalArray>;
|
||||||
|
|
||||||
|
{ TBinomialCoefficientCache }
|
||||||
|
|
||||||
|
TBinomialCoefficientCache = class
|
||||||
|
private
|
||||||
|
FCache: TCardinalArrays;
|
||||||
|
procedure AddRow;
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
|
destructor Destroy; override;
|
||||||
|
function Get(const AN, AK: Cardinal): Cardinal;
|
||||||
|
function GetCachedRowsCount: Cardinal;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ TBinomialCoefficientCache }
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientCache.AddRow;
|
||||||
|
var
|
||||||
|
row: TCardinalArray;
|
||||||
|
i: Cardinal;
|
||||||
|
begin
|
||||||
|
SetLength(row, FCache.Count + 1);
|
||||||
|
row[0] := 1;
|
||||||
|
if FCache.Count > 0 then
|
||||||
|
begin
|
||||||
|
row[FCache.Count] := 1;
|
||||||
|
for i := 1 to FCache.Count - 1 do
|
||||||
|
row[i] := FCache.Last[i - 1] + FCache.Last[i];
|
||||||
|
end;
|
||||||
|
FCache.Add(row);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TBinomialCoefficientCache.Create;
|
||||||
|
begin
|
||||||
|
FCache := TCardinalArrays.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TBinomialCoefficientCache.Destroy;
|
||||||
|
begin
|
||||||
|
FCache.Free;
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBinomialCoefficientCache.Get(const AN, AK: Cardinal): Cardinal;
|
||||||
|
var
|
||||||
|
i: Cardinal;
|
||||||
|
begin
|
||||||
|
if AN < AK then
|
||||||
|
raise ERangeError.Create('Cannot calculate binomial coefficient "n choose k" with k larger than n.');
|
||||||
|
|
||||||
|
for i := FCache.Count to AN do
|
||||||
|
AddRow;
|
||||||
|
Result := FCache[AN][AK];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBinomialCoefficientCache.GetCachedRowsCount: Cardinal;
|
||||||
|
begin
|
||||||
|
Result := FCache.Count;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
|
@ -152,6 +152,10 @@
|
||||||
<Filename Value="USnowverloadTestCases.pas"/>
|
<Filename Value="USnowverloadTestCases.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
</Unit>
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="UBinomialCoefficientsTestCases.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit>
|
||||||
</Units>
|
</Units>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
|
|
|
@ -10,7 +10,7 @@ uses
|
||||||
UFloorWillBeLavaTestCases, UClumsyCrucibleTestCases, ULavaductLagoonTestCases, UAplentyTestCases,
|
UFloorWillBeLavaTestCases, UClumsyCrucibleTestCases, ULavaductLagoonTestCases, UAplentyTestCases,
|
||||||
UPulsePropagationTestCases, UStepCounterTestCases, USandSlabsTestCases, ULongWalkTestCases,
|
UPulsePropagationTestCases, UStepCounterTestCases, USandSlabsTestCases, ULongWalkTestCases,
|
||||||
UNeverTellMeTheOddsTestCases, USnowverloadTestCases, UBigIntTestCases, UPolynomialTestCases,
|
UNeverTellMeTheOddsTestCases, USnowverloadTestCases, UBigIntTestCases, UPolynomialTestCases,
|
||||||
UPolynomialRootsTestCases;
|
UPolynomialRootsTestCases, UBinomialCoefficientsTestCases;
|
||||||
|
|
||||||
{$R *.res}
|
{$R *.res}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
{
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
}
|
||||||
|
|
||||||
|
unit UBinomialCoefficientsTestCases;
|
||||||
|
|
||||||
|
{$mode ObjFPC}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, fpcunit, testregistry, UBinomialCoefficients;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TBinomialCoefficientsTestCase }
|
||||||
|
|
||||||
|
TBinomialCoefficientsTestCase = class(TTestCase)
|
||||||
|
private
|
||||||
|
FBinomialCoefficientCache: TBinomialCoefficientCache;
|
||||||
|
procedure RunRangeError;
|
||||||
|
procedure AssertEqualsCalculation(const AN, AK, AExpected: Cardinal);
|
||||||
|
procedure AssertEqualsCachedRowsCount(const AExpected: Cardinal);
|
||||||
|
protected
|
||||||
|
procedure SetUp; override;
|
||||||
|
procedure TearDown; override;
|
||||||
|
published
|
||||||
|
procedure TestZeroChooseZero;
|
||||||
|
procedure TestNChooseZero;
|
||||||
|
procedure TestNChooseN;
|
||||||
|
procedure TestNChooseK;
|
||||||
|
procedure TestCombined;
|
||||||
|
procedure TestFullRow;
|
||||||
|
procedure TestRangeError;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ TBinomialCoefficientsTestCase }
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.RunRangeError;
|
||||||
|
begin
|
||||||
|
FBinomialCoefficientCache.Get(1, 5);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.AssertEqualsCalculation(const AN, AK, AExpected: Cardinal);
|
||||||
|
begin
|
||||||
|
AssertEquals('Unexpected calculation result', AExpected, FBinomialCoefficientCache.Get(AN, AK));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.AssertEqualsCachedRowsCount(const AExpected: Cardinal);
|
||||||
|
begin
|
||||||
|
AssertEquals('Unexpected cached rows count', AExpected, FBinomialCoefficientCache.GetCachedRowsCount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.SetUp;
|
||||||
|
begin
|
||||||
|
FBinomialCoefficientCache := TBinomialCoefficientCache.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.TearDown;
|
||||||
|
begin
|
||||||
|
FBinomialCoefficientCache.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.TestZeroChooseZero;
|
||||||
|
begin
|
||||||
|
AssertEqualsCalculation(0, 0, 1);
|
||||||
|
AssertEqualsCachedRowsCount(1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.TestNChooseZero;
|
||||||
|
begin
|
||||||
|
AssertEqualsCalculation(15, 0, 1);
|
||||||
|
AssertEqualsCachedRowsCount(16);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.TestNChooseN;
|
||||||
|
begin
|
||||||
|
AssertEqualsCalculation(11, 11, 1);
|
||||||
|
AssertEqualsCachedRowsCount(12);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.TestNChooseK;
|
||||||
|
begin
|
||||||
|
AssertEqualsCalculation(8, 3, 56);
|
||||||
|
AssertEqualsCachedRowsCount(9);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.TestCombined;
|
||||||
|
begin
|
||||||
|
AssertEqualsCalculation(5, 1, 5);
|
||||||
|
AssertEqualsCachedRowsCount(6);
|
||||||
|
AssertEqualsCalculation(8, 4, 70);
|
||||||
|
AssertEqualsCachedRowsCount(9);
|
||||||
|
AssertEqualsCalculation(3, 1, 3);
|
||||||
|
AssertEqualsCachedRowsCount(9);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.TestFullRow;
|
||||||
|
begin
|
||||||
|
AssertEqualsCalculation(5, 0, 1);
|
||||||
|
AssertEqualsCachedRowsCount(6);
|
||||||
|
AssertEqualsCalculation(5, 1, 5);
|
||||||
|
AssertEqualsCachedRowsCount(6);
|
||||||
|
AssertEqualsCalculation(5, 2, 10);
|
||||||
|
AssertEqualsCachedRowsCount(6);
|
||||||
|
AssertEqualsCalculation(5, 3, 10);
|
||||||
|
AssertEqualsCachedRowsCount(6);
|
||||||
|
AssertEqualsCalculation(5, 4, 5);
|
||||||
|
AssertEqualsCachedRowsCount(6);
|
||||||
|
AssertEqualsCalculation(5, 5, 1);
|
||||||
|
AssertEqualsCachedRowsCount(6);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBinomialCoefficientsTestCase.TestRangeError;
|
||||||
|
begin
|
||||||
|
AssertException(ERangeError, @RunRangeError);
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
|
||||||
|
RegisterTest('Helper', TBinomialCoefficientsTestCase);
|
||||||
|
end.
|
||||||
|
|
Loading…
Reference in New Issue