Compare commits

...

1 Commits

Author SHA1 Message Date
Stefan Müller 3d5235ad6e Added another WIP solution attempt 2024-02-21 21:04:51 +01:00
4 changed files with 747 additions and 30 deletions

View File

@ -137,6 +137,14 @@
<Filename Value="solvers\UNeverTellMeTheOdds.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="UBigInt.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="UVector.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>

111
UVector.pas Normal file
View File

@ -0,0 +1,111 @@
{
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 UVector;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils;
type
TVector3DataRange = 0..2;
TVector3Int64Data = array[TVector3DataRange] of Int64;
{ TVector3Int64 }
TVector3Int64 = object
private
function GetX: Int64;
function GetY: Int64;
function GetZ: Int64;
procedure SetX(AValue: Int64);
procedure SetY(AValue: Int64);
procedure SetZ(AValue: Int64);
public
Data: TVector3Int64Data;
property X: Int64 read GetX write SetX;
property Y: Int64 read GetY write SetY;
property Z: Int64 read GetZ write SetZ;
constructor Init(const AX, AY, AZ: Int64);
end;
//// Component-wise binary operators.
//operator - (const A, B: TVector3Int64): TVector3Int64;
//operator / (const A, B: TVector3Int64): TVector3Int64;
implementation
//operator - (const A, B: TVector3Int64): TVector3Int64;
//var
// i: TVector3DataRange;
//begin
// for i in TVector3DataRange do
// Result.Data[i] := A.Data[i] - B.Data[i];
//end;
//
//operator / (const A, B: TVector3Int64): TVector3Int64;
//var
// i: TVector3DataRange;
//begin
//for i in TVector3DataRange do
// Result.Data[i] := A.Data[i] / B.Data[i];
//end;
{ TVector3Int64 }
function TVector3Int64.GetX: Int64;
begin
Result := Data[0];
end;
function TVector3Int64.GetY: Int64;
begin
Result := Data[1];
end;
function TVector3Int64.GetZ: Int64;
begin
Result := Data[2];
end;
procedure TVector3Int64.SetX(AValue: Int64);
begin
Data[0] := AValue;
end;
procedure TVector3Int64.SetY(AValue: Int64);
begin
Data[1] := AValue;
end;
procedure TVector3Int64.SetZ(AValue: Int64);
begin
Data[2] := AValue;
end;
constructor TVector3Int64.Init(const AX, AY, AZ: Int64);
begin
X := AX;
Y := AY;
Z := AZ;
end;
end.

View File

@ -1,6 +1,6 @@
{
Solutions to the Advent Of Code.
Copyright (C) 2023 Stefan Müller
Copyright (C) 2023-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
@ -22,26 +22,45 @@ unit UNeverTellMeTheOdds;
interface
uses
Classes, SysUtils, Generics.Collections, Math, USolver;
Classes, SysUtils, Generics.Collections, Math, USolver, UVector;
type
{ THailstone }
THailstone = record
X, Y, Z: Int64;
VX, VY, VZ: Integer;
THailstone = class
public
Position, Velocity: TVector3Int64;
constructor Create(const ALine: string);
constructor Create(const APosition, AVelocity: TVector3Int64);
function GetParameterMinimum(const AMin, AMax: Int64): Int64;
function GetParameterMaximum(const AMin, AMax: Int64): Int64;
end;
THailstones = specialize TList<THailstone>;
THailstones = specialize TObjectList<THailstone>;
//{ TFirstCollisionPolynomial }
//
//TFirstCollisionPolynomial = class
//private
// FA: array[0..10] of TBigInt;
// FH: array[0..6] of TBigInt;
// procedure NormalizeCoefficients;
//public
// procedure Init(constref AHailstone1, AHailstone2, AHailstone3: THailstone; const t_0, t_1, t_2: Int64);
// function EvaluateAt(const AT0: Int64): TBigInt;
// function CalcPositiveIntegerRoot: Int64;
// function CalcT1(const AT0: Int64): Int64;
//end;
{ TNeverTellMeTheOdds }
TNeverTellMeTheOdds = class(TSolver)
private
FMin, FMax: Int64;
FHailStones: THailstones;
FHailstones: THailstones;
function AreIntersecting(constref AHailstone1, AHailstone2: THailstone): Boolean;
procedure FindRockThrow(const AIndex1, AIndex2, AIndex3: Integer);
public
constructor Create(const AMin: Int64 = 200000000000000; const AMax: Int64 = 400000000000000);
destructor Destroy; override;
@ -51,8 +70,492 @@ type
function GetPuzzleName: string; override;
end;
const
CIterationThreshold = 0.00001;
CEpsilon = 0.0000000001;
implementation
{ THailstone }
constructor THailstone.Create(const ALine: string);
var
split: TStringArray;
begin
split := ALine.Split([',', '@']);
Position.Init(
StrToInt64(Trim(split[0])),
StrToInt64(Trim(split[1])),
StrToInt64(Trim(split[2])));
Velocity.Init(
StrToInt64(Trim(split[3])),
StrToInt64(Trim(split[4])),
StrToInt64(Trim(split[5])));
//Position.init(
// StrToFloat(Trim(split[0])),
// StrToFloat(Trim(split[1])),
// StrToFloat(Trim(split[2])));
//Velocity.init(
// StrToFloat(Trim(split[3])),
// StrToFloat(Trim(split[4])),
// StrToFloat(Trim(split[5])));
end;
constructor THailstone.Create(const APosition, AVelocity: TVector3Int64);
begin
Position := APosition;
Velocity := AVelocity;
end;
function THailstone.GetParameterMinimum(const AMin, AMax: Int64): Int64;
var
i: TVector3DataRange;
boundary: Int64;
begin
Result := 0;
for i in TVector3DataRange do
begin
if Velocity.Data[i] > 0 then
boundary := AMin
else
boundary := AMax;
Result := Max(Result, Ceil64((boundary - Position.Data[i]) / Velocity.Data[i]));
end;
end;
function THailstone.GetParameterMaximum(const AMin, AMax: Int64): Int64;
var
i: TVector3DataRange;
boundary: Int64;
begin
Result := Int64.MaxValue;
for i in TVector3DataRange do
begin
if Velocity.Data[i] > 0 then
boundary := AMax
else
boundary := AMin;
Result := Min(Result, Floor64((boundary - Position.Data[i]) / Velocity.Data[i]));
end;
end;
//{ TFirstCollisionPolynomial }
//
//procedure TFirstCollisionPolynomial.NormalizeCoefficients;
//var
// shift: Integer;
// i: Low(FA)..High(FA);
// //gcd: TBigInt;
//begin
// // Eliminates zero constant term.
// shift := 0;
// while (shift <= High(FA)) and (FA[shift] = 0) do
// Inc(shift);
//
// if shift <= High(FA) then
// begin
// if shift > 0 then
// begin
// for i := Low(FA) to High(FA) - shift do
// FA[i] := FA[i + shift];
// for i := High(FA) - shift + 1 to High(FA) do
// FA[i] := 0;
// end;
//
// //// Finds GCD of all coefficients.
// //gcd := FA[Low(FA)];
// //for i := Low(FA) + 1 to High(FA) do
// // if FA[i] <> 0 then
// // gcd := TNumberTheory.GreatestCommonDivisor(gcd, FA[i]);
// //WriteLn('GCD: ', gcd);
// //
// //for i := Low(FA) to High(FA) do
// // FA[i] := FA[i] div gcd;
// end;
//
// //WriteLn('(', FA[10], ') * x^10 + (', FA[9], ') * x^9 + (', FA[8], ') * x^8 + (', FA[7], ') * x^7 + (',
// // FA[6], ') * x^6 + (', FA[5], ') * x^5 + (', FA[4], ') * x^4 + (', FA[3], ') * x^3 + (', FA[2], ') * x^2 + (',
// // FA[1], ') * x + (', FA[0], ')');
//end;
//
//procedure TFirstCollisionPolynomial.Init(constref AHailstone1, AHailstone2, AHailstone3: THailstone; const t_0, t_1,
// t_2: Int64);
//var
// P_00, P_01, P_02, P_10, P_11, P_12, P_20, P_21, P_22,
// V_00, V_01, V_02, V_10, V_11, V_12, V_20, V_21, V_22: Int64;
// k: array[0..139] of TBigInt;
// // For debug calculations
// act, a_1, a_2, b_0, b_1, c_0, c_1, d_0, d_1, e_0, e_1, f_0, f_1, f_2: Int64;
//begin
// // Solving this non-linear equation system, with velocities V_i and start positions P_i:
// // V_0 * t_0 + P_0 = V_x * t_0 + P_x
// // V_1 * t_1 + P_1 = V_x * t_1 + P_x
// // V_2 * t_2 + P_2 = V_x * t_2 + P_x
// // Which gives:
// // P_x = (V_0 - V_x) * t_0 + P_0
// // V_x = (V_0 * t_0 - V_1 * t_1 + P_0 - P_1) / (t_0 - t_1)
// // And with vertex components:
// // 1: 0 = (t_1 - t_0) * (V_00 * t_0 - V_20 * t_2 + P_00 - P_20) - (t_2 - t_0) * (V_00 * t_0 - V_10 * t_1 + P_00 - P_10)
// // 2: t_1 = (((V_01 - V_21) * t_2 + P_11 - P_21) * t_0 + (P_01 - P_11) * t_2)
// // / ((V_01 - V_11) * t_0 + (V_11 - V_21) * t_2 + P_01 - P_21)
// // 3: t_2 = (((V_02 - V_12) * t_1 + P_22 - P_12) * t_0 + (P_02 - P_22) * t_1)
// // / ((V_02 - V_22) * t_0 + (V_22 - V_12) * t_1 + P_02 - P_12)
// // for t_0, t_1, t_2 not pairwise equal.
// // With some substitutions depending only on t_0 this gives
// // 1: 0 = (t_1 - t_0) * (f_2 - V_20 * t_2) - (t_2 - t_0) * (f_1 - V_10 * t_1)
// // 2: t_1 = (b_0 + b_1 * t_2) / (c_0 + c_1 * t_2)
// // 3: t_2 = (d_0 + d_1 * t_1) / (e_0 + e_1 * t_1)
// // And 3 in 2 gives:
// // 4: g_2 * t_1^2 - g_1 * t_1 - g_0 = 0
// // Then, with 4 and 3 in 1 and lengthy calculations with many substitutions (see constants k below, now independent of
// // t_0), the following polynomial can be constructed, with t_0 being a positive integer root of this polynomial.
// // y = a_10 * x^10 + a_9 * x^9 + ... + a_0
//
// P_00 := Round(AHailstone1.Position.data[0]);
// P_01 := Round(AHailstone1.Position.data[1]);
// P_02 := Round(AHailstone1.Position.data[2]);
// P_10 := Round(AHailstone2.Position.data[0]);
// P_11 := Round(AHailstone2.Position.data[1]);
// P_12 := Round(AHailstone2.Position.data[2]);
// P_20 := Round(AHailstone3.Position.data[0]);
// P_21 := Round(AHailstone3.Position.data[1]);
// P_22 := Round(AHailstone3.Position.data[2]);
// V_00 := Round(AHailstone1.Velocity.data[0]);
// V_01 := Round(AHailstone1.Velocity.data[1]);
// V_02 := Round(AHailstone1.Velocity.data[2]);
// V_10 := Round(AHailstone2.Velocity.data[0]);
// V_11 := Round(AHailstone2.Velocity.data[1]);
// V_12 := Round(AHailstone2.Velocity.data[2]);
// V_20 := Round(AHailstone3.Velocity.data[0]);
// V_21 := Round(AHailstone3.Velocity.data[1]);
// V_22 := Round(AHailstone3.Velocity.data[2]);
//
// k[0] := P_00 - P_20;
// k[1] := P_00 - P_10;
// k[2] := P_11 - P_21;
// k[3] := P_01 - P_11;
// k[4] := P_01 - P_21;
// k[5] := P_22 - P_12;
// k[6] := P_02 - P_22;
// k[7] := P_02 - P_12;
// k[8] := V_11 - V_21;
// k[9] := V_22 - V_12;
// k[10] := V_01 - V_21;
// k[11] := V_01 - V_11;
// k[12] := V_02 - V_12;
// k[13] := V_02 - V_22;
//
// FH[0] := k[11] * k[9] + k[8] * k[12];
// FH[1] := k[4] * k[9] + k[8] * k[6];
// FH[2] := k[11] * k[13] - k[10] * k[12];
// FH[3] := k[11] * k[7] + k[4] * k[13] + k[8] * k[5] - k[2] * k[9] - k[10] * k[6] - k[3] * k[12];
// FH[4] := k[4] * k[7] - k[3] * k[6];
// FH[5] := k[10] * k[5] + k[2] * k[13];
// FH[6] := k[3] * k[5] + k[2] * k[7];
//
// k[14] := V_00 * k[9] - V_20 * k[12];
// k[15] := k[0] * k[9] - V_20 * k[6];
// k[16] := V_00 * k[13];
// k[17] := V_00 * k[7] + k[0] * k[13] - V_20 * k[5];
// k[18] := k[0] * k[7];
// k[19] := k[5] - k[7];
// k[20] := 2 * FH[2] * FH[3];
// k[21] := FH[3] * FH[3];
// k[22] := k[21] + 2 * FH[2] * FH[4];
// k[23] := 2 * FH[3] * FH[4];
// k[24] := 2 * FH[0] * FH[1];
// k[25] := FH[0] * FH[0]; // KILL?
// k[26] := FH[5] * k[25]; // KILL?
// k[126] := FH[5] * FH[0];
// k[127] := FH[5] * FH[1] + FH[6] * FH[0];
// k[128] := FH[6] * FH[1];
// k[27] := FH[5] * k[24] + FH[6] * k[25]; // KILL?
// k[28] := FH[1] * FH[1]; // KILL?
// k[29] := FH[5] * k[28] + FH[6] * k[24]; // KILL?
// k[30] := FH[6] * k[28]; // KILL?
// k[31] := FH[2] * FH[2];
// k[132] := k[20] + 4 * k[126];
// k[133] := k[22] + 4 * k[127];
// k[134] := k[23] + 4 * k[128];
// k[32] := k[31] + 4 * k[26]; // KILL?
// k[33] := k[20] + 4 * k[27]; // KILL?
// k[34] := k[22] + 4 * k[29]; // KILL?
// k[35] := k[23] + 4 * k[30]; // KILL?
// k[36] := k[31] + 2 * k[26]; // KILL?
// k[37] := k[20] + 2 * k[27]; // KILL?
// k[38] := k[22] + 2 * k[29]; // KILL?
// k[39] := k[23] + 2 * k[30]; // KILL?
// k[137] := k[20] + 2 * k[126];
// k[138] := k[22] + 2 * k[127];
// k[139] := k[23] + 2 * k[128];
// k[40] := k[14] + V_10 * (k[12] - k[9]);
// k[41] := k[15] + V_10 * k[6];
// k[42] := k[16] - k[14] - V_10 * k[13] - (k[12] - k[9]) * V_00;
// k[43] := k[17] - k[15] + V_10 * k[19] - (k[12] - k[9]) * k[1] - k[6] * V_00;
// k[44] := k[18] - k[6] * k[1];
// k[45] := k[42] * FH[0] - k[40] * FH[2];
// k[46] := k[42] * FH[1] + k[43] * FH[0] - k[41] * FH[2] - k[40] * FH[3];
// k[47] := k[43] * FH[1] + k[44] * FH[0] - k[41] * FH[3] - k[40] * FH[4];
// k[48] := k[44] * FH[1] - k[41] * FH[4];
// k[49] := k[42] * FH[2];
// k[50] := k[40] * k[31] - k[49] * FH[0];
// k[51] := k[42] * FH[3] + k[43] * FH[2];
// k[52] := k[40] * k[137] + k[41] * k[31] - k[51] * FH[0] - k[49] * FH[1];
// k[53] := k[42] * FH[4] + k[43] * FH[3] + k[44] * FH[2];
// k[54] := k[40] * k[138] + k[41] * k[137] - k[53] * FH[0] - k[51] * FH[1];
// k[55] := k[43] * FH[4] + k[44] * FH[3];
// k[56] := k[40] * k[139] + k[41] * k[138] - k[55] * FH[0] - k[53] * FH[1];
// k[57] := k[44] * FH[4];
// k[58] := FH[4] * FH[4];
// k[59] := k[40] * k[58] + k[41] * k[139] - k[57] * FH[0] - k[55] * FH[1];
// k[60] := k[41] * k[58] - k[57] * FH[1];
// k[61] := k[13] * V_00 - k[16];
// k[62] := 2 * k[25] * k[61];
// k[63] := k[13] * k[1] - k[19] * V_00 - k[17];
// k[64] := 2 * (k[24] * k[61] + k[25] * k[63]);
// k[65] := - k[19] * k[1] - k[18];
// k[66] := 2 * (k[28] * k[61] + k[24] * k[63] + k[25] * k[65]);
// k[67] := 2 * (k[28] * k[63] + k[24] * k[65]);
// k[68] := 2 * k[28] * k[65];
// k[69] := k[50] + k[62];
// k[70] := k[52] + k[64];
// k[71] := k[54] + k[66];
// k[72] := k[56] + k[67];
// k[73] := k[59] + k[68];
// k[74] := k[45] * k[45];
// k[75] := 2 * k[45] * k[46];
// k[76] := k[46] * k[46] + 2 * k[45] * k[47];
// k[77] := 2 * (k[45] * k[48] + k[46] * k[47]);
// k[78] := k[47] * k[47] + 2 * k[46] * k[48];
// k[79] := 2 * k[47] * k[48];
// k[80] := k[48] * k[48];
//
// FA[0] := k[58] * k[80] - k[60] * k[60];
// FA[1] := k[134] * k[80] + k[58] * k[79] - 2 * k[73] * k[60];
// FA[2] := k[133] * k[80] + k[134] * k[79] + k[58] * k[78] - k[73] * k[73] - 2 * k[72] * k[60];
// FA[3] := k[133] * k[79] + k[134] * k[78] + k[58] * k[77] + k[132] * k[80]
// - 2 * (k[71] * k[60] + k[72] * k[73]);
// FA[4] := k[31] * k[80] + k[133] * k[78] + k[134] * k[77] + k[58] * k[76] + k[132] * k[79] - k[72] * k[72]
// - 2 * (k[70] * k[60] + k[71] * k[73]);
// FA[5] := k[31] * k[79] + k[133] * k[77] + k[134] * k[76] + k[58] * k[75] + k[132] * k[78]
// - 2 * (k[69] * k[60] + k[70] * k[73] + k[71] * k[72]);
// FA[6] := k[31] * k[78] + k[133] * k[76] + k[134] * k[75] + k[58] * k[74] + k[132] * k[77] - k[71] * k[71]
// - 2 * (k[69] * k[73] + k[70] * k[72]);
// FA[7] := k[31] * k[77] + k[133] * k[75] + k[134] * k[74] + k[132] * k[76] - 2 * (k[69] * k[72] + k[70] * k[71]);
// FA[8] := k[31] * k[76] + k[132] * k[75] + k[133] * k[74] - k[70] * k[70] - 2 * k[69] * k[71];
// FA[9] := k[31] * k[75] + k[132] * k[74] - 2 * k[69] * k[70];
// FA[10] := k[31] * k[74] - k[69] * k[69];
//
// // Debug calculations
// //a_1 := V_00 * t_0 + P_00 - P_20;
// //a_2 := V_00 * t_0 + P_00 - P_10;
// //b_0 := (P_11 - P_21) * t_0;
// //b_1 := (V_01 - V_21) * t_0 + P_01 - P_11;
// //c_0 := (V_01 - V_11) * t_0 + P_01 - P_21;
// //c_1 := V_11 - V_21;
// //d_0 := (P_22 - P_12) * t_0;
// //d_1 := (V_02 - V_12) * t_0 + P_02 - P_22;
// //e_0 := (V_02 - V_22) * t_0 + P_02 - P_12;
// //e_1 := V_22 - V_12;
// //f_2 := c_0 * e_1 + c_1 * d_1;
// //f_1 := c_0 * e_0 + c_1 * d_0 - b_0 * e_1 - b_1 * d_1;
// //f_0 := b_1 * d_0 + b_0 * e_0;
// //
// //act := f_2 * t_1 * t_1 + f_1 * t_1 - f_0;
// //Write('debug10: ', 0 = act, ' ');
// //
// //if f_2 <> 0 then
// //begin
// // act := Round(- f_1 / (2 * f_2) + Sqrt((f_1 / (2 * f_2)) * (f_1 / (2 * f_2)) + f_0 / f_2));
// // Write('debug15: ', t_1 = act);
// // act := Round(- f_1 / (2 * f_2) - Sqrt((f_1 / (2 * f_2)) * (f_1 / (2 * f_2)) + f_0 / f_2));
// // Write(' OR ', t_1 = act, ' ');
// //end;
// //
// //act := (e_0 + e_1 * t_1) * t_2 - (d_0 + d_1 * t_1);
// //Write('debug20: ', 0 = act, ' ');
// //
// //act := (a_1 * e_1 - V_20 * d_1 + V_10 * (d_1 - e_1 * t_0)) * t_1 * t_1
// // + (a_1 * e_0 - V_20 * d_0 - t_0 * (a_1 * e_1 - V_20 * d_1) - (d_1 - e_1 * t_0) * a_2 + V_10 * (d_0 - e_0 * t_0)) * t_1
// // + t_0 * (V_20 * d_0 - a_1 * e_0) + (e_0 * t_0 - d_0) * a_2;
// //Write('debug30: ', 0 = act, ' ');
// //
// //act := Round((a_1 * e_1 - V_20 * d_1 + V_10 * (d_1 - e_1 * t_0)) * (f_1 * f_1 + 2 * f_0 * f_2 - f_1 * Sqrt(f_1 * f_1 + 4 * f_0 * f_2))
// // + (a_1 * e_0 - V_20 * d_0 - t_0 * (a_1 * e_1 - V_20 * d_1) - (d_1 - e_1 * t_0) * a_2 + V_10 * (d_0 - e_0 * t_0)) * (- f_1 * f_2 + f_2 * Sqrt(f_1 * f_1 + 4 * f_0 * f_2))
// // + t_0 * (V_20 * d_0 - a_1 * e_0) * 2 * f_2 * f_2 + (e_0 * t_0 - d_0) * a_2 * 2 * f_2 * f_2);
// //Write('debug40: ', 0 = act, ' ');
// //
// //Write('debug41: ',
// // a_1 * k[9] - V_20 * d_1
// // = k[14] * t_0 + k[15], ' ');
// //Write('debug42: ',
// // d_1 - k[9] * t_0
// // = (k[12] - k[9]) * t_0 + k[6], ' ');
// //Write('debug43: ',
// // a_1 * e_0 - V_20 * d_0
// // = k[16] * t_0 * t_0 + k[17] * t_0 + k[18], ' ');
// //Write('debug44: ',
// // d_0 - e_0 * t_0
// // = - k[13] * t_0 * t_0 + k[19] * t_0, ' ');
// //Write('debug45: ',
// // f_1 * f_1
// // = FH[2] * FH[2] * t_0 * t_0 * t_0 * t_0 + k[20] * t_0 * t_0 * t_0 + k[22] * t_0 * t_0 + k[23] * t_0 + FH[4] * FH[4], ' ');
// //Write('debug46: ',
// // f_2 * f_2
// // = FH[0] * FH[0] * t_0 * t_0 + k[24] * t_0 + FH[1] * FH[1], ' ');
// //Write('debug47: ',
// // f_0 * f_2
// // = k[126] * t_0 * t_0 * t_0 + k[127] * t_0 * t_0 + k[128] * t_0, ' ');
// //Write('debug48: ',
// // f_1 * f_1 + 4 * f_0 * f_2
// // = k[31] * t_0 * t_0 * t_0 * t_0 + k[132] * t_0 * t_0 * t_0 + k[133] * t_0 * t_0 + k[134] * t_0 + k[58], ' ');
// //Write('debug49: ',
// // f_1 * f_1 + 2 * f_0 * f_2
// // = k[31] * t_0 * t_0 * t_0 * t_0 + k[137] * t_0 * t_0 * t_0 + k[138] * t_0 * t_0 + k[139] * t_0 + k[58], ' ');
// //
// //act := Round((k[14] * t_0 + k[15] + V_10 * ((k[12] - k[9]) * t_0 + k[6])) * (k[31] * t_0 * t_0 * t_0 * t_0 + k[137] * t_0 * t_0 * t_0 + k[138] * t_0 * t_0 + k[139] * t_0 + k[58] - f_1 * sqrt(f_1 * f_1 + 4 * f_0 * f_2))
// // + (k[16] * t_0 * t_0 + k[17] * t_0 + k[18] - t_0 * (k[14] * t_0 + k[15]) - ((k[12] - k[9]) * t_0 + k[6]) * a_2 - V_10 * (k[13] * t_0 * t_0 - k[19] * t_0)) * (- f_1 * f_2 + f_2 * sqrt(f_1 * f_1 + 4 * f_0 * f_2))
// // - 2 * t_0 * (k[16] * t_0 * t_0 + k[17] * t_0 + k[18]) * (FH[0] * FH[0] * t_0 * t_0 + k[24] * t_0 + FH[1] * FH[1]) + 2 * (k[13] * t_0 * t_0 - k[19] * t_0) * a_2 * (FH[0] * FH[0] * t_0 * t_0 + k[24] * t_0 + FH[1] * FH[1]));
// //Write('debug50: ', 0 = act, ' ');
// //
// //Write('debug53: ',
// // 0 = Round((k[40] * t_0 + k[41]) * (k[31] * t_0 * t_0 * t_0 * t_0 + k[137] * t_0 * t_0 * t_0 + k[138] * t_0 * t_0 + k[139] * t_0 + k[58] - f_1 * sqrt(f_1 * f_1 + 4 * f_0 * f_2))
// // + ((k[16] - k[14] - V_10 * k[13] - (k[12] - k[9]) * V_00) * t_0 * t_0 + (k[17] - k[15] + V_10 * k[19] - (k[12] - k[9]) * k[1] - k[6] * V_00) * t_0 + k[18] - k[6] * k[1]) * (- f_1 * f_2 + f_2 * sqrt(f_1 * f_1 + 4 * f_0 * f_2))
// // - 2 * t_0 * (k[16] * t_0 * t_0 + k[17] * t_0 + k[18]) * (FH[0] * FH[0] * t_0 * t_0 + k[24] * t_0 + FH[1] * FH[1]) + 2 * (k[13] * t_0 * t_0 - k[19] * t_0) * a_2 * (FH[0] * FH[0] * t_0 * t_0 + k[24] * t_0 + FH[1] * FH[1])),
// // ' ');
// //
// //Write('debug55: ',
// // 0 = Round((k[40] * t_0 + k[41]) * (k[31] * t_0 * t_0 * t_0 * t_0 + k[137] * t_0 * t_0 * t_0 + k[138] * t_0 * t_0 + k[139] * t_0 + k[58])
// // - (k[40] * t_0 + k[41]) * f_1 * sqrt(f_1 * f_1 + 4 * f_0 * f_2)
// // + (k[42] * t_0 * t_0 + k[43] * t_0 + k[44]) * (- f_1 * f_2 + f_2 * sqrt(f_1 * f_1 + 4 * f_0 * f_2))
// // - 2 * t_0 * (k[16] * t_0 * t_0 + k[17] * t_0 + k[18]) * (FH[0] * FH[0] * t_0 * t_0 + k[24] * t_0 + FH[1] * FH[1]) + 2 * (k[13] * t_0 * t_0 - k[19] * t_0) * a_2 * (FH[0] * FH[0] * t_0 * t_0 + k[24] * t_0 + FH[1] * FH[1])),
// // ' ');
// //
// //Write('debug70: ',
// // 0 = Round(((k[42] * t_0 * t_0 + k[43] * t_0 + k[44]) * (FH[0] * t_0 + FH[1]) - (k[40] * t_0 + k[41]) * (FH[2] * t_0 * t_0 + FH[3] * t_0 + FH[4])) * sqrt(f_1 * f_1 + 4 * f_0 * f_2))
// // + (k[40] * t_0 + k[41]) * (k[31] * t_0 * t_0 * t_0 * t_0 + k[137] * t_0 * t_0 * t_0 + k[138] * t_0 * t_0 + k[139] * t_0 + k[58])
// // - (k[42] * t_0 * t_0 + k[43] * t_0 + k[44]) * (FH[2] * t_0 * t_0 + FH[3] * t_0 + FH[4]) * (FH[0] * t_0 + FH[1])
// // - 2 * t_0 * (k[16] * t_0 * t_0 + k[17] * t_0 + k[18]) * (FH[0] * FH[0] * t_0 * t_0 + k[24] * t_0 + FH[1] * FH[1]) + 2 * (k[13] * t_0 * t_0 - k[19] * t_0) * (V_00 * t_0 + k[1]) * (FH[0] * FH[0] * t_0 * t_0 + k[24] * t_0 + FH[1] * FH[1]),
// // ' ');
////
//// Write('debug73: ',
//// 0 = Round((
//// (k[42] * FH[0] - k[40] * FH[2]) * t_0 * t_0 * t_0
//// + (k[42] * FH[1] + k[43] * FH[0] - k[41] * FH[2] - k[40] * FH[3]) * t_0 * t_0
//// + (k[43] * FH[1] + k[44] * FH[0] - k[41] * FH[3] - k[40] * FH[4]) * t_0
//// + k[44] * FH[1] - k[41] * FH[4]
//// ) * sqrt(f_1 * f_1 + 4 * f_0 * f_2))
//// + (k[40] * k[31] - k[42] * FH[2] * FH[0]) * t_0 * t_0 * t_0 * t_0 * t_0
//// + (k[40] * k[137] + k[41] * k[31] - k[42] * FH[3] * FH[0] - k[43] * FH[2] * FH[0] - k[42] * FH[2] * FH[1]) * t_0 * t_0 * t_0 * t_0
//// + (k[40] * k[138] + k[41] * k[137] - k[42] * FH[4] * FH[0] - k[43] * FH[3] * FH[0] - k[44] * FH[2] * FH[0] - k[42] * FH[3] * FH[1] - k[43] * FH[2] * FH[1]) * t_0 * t_0 * t_0
//// + (k[40] * k[139] + k[41] * k[138] - k[43] * FH[4] * FH[0] - k[44] * FH[3] * FH[0] - k[42] * FH[4] * FH[1] - k[43] * FH[3] * FH[1] - k[44] * FH[2] * FH[1]) * t_0 * t_0
//// + (k[40] * k[58] + k[41] * k[139] - k[44] * FH[4] * FH[0] - k[43] * FH[4] * FH[1] - k[44] * FH[3] * FH[1]) * t_0
//// + k[41] * k[58] - k[44] * FH[4] * FH[1]
//// + 2 * (k[13] * V_00 * FH[0] * FH[0] - k[16] * FH[0] * FH[0]) * t_0 * t_0 * t_0 * t_0 * t_0
//// + 2 * (k[13] * V_00 * k[24] + k[13] * k[1] * FH[0] * FH[0] - k[19] * V_00 * FH[0] * FH[0] - k[16] * k[24] - k[17] * FH[0] * FH[0]) * t_0 * t_0 * t_0 * t_0
//// + 2 * (k[13] * V_00 * FH[1] * FH[1] + k[13] * k[1] * k[24] - k[19] * V_00 * k[24] - k[19] * k[1] * FH[0] * FH[0] - k[16] * FH[1] * FH[1] - k[17] * k[24] - k[18] * FH[0] * FH[0]) * t_0 * t_0 * t_0
//// + 2 * (k[13] * k[1] * FH[1] * FH[1] - k[19] * V_00 * FH[1] * FH[1] - k[19] * k[1] * k[24] - k[17] * FH[1] * FH[1] - k[18] * k[24]) * t_0 * t_0
//// + 2 * (- k[19] * k[1] * FH[1] * FH[1] - k[18] * FH[1] * FH[1]) * t_0,
//// ' ');
////
//// Write('debug78: ',
//// 0 = Round((k[45] * t_0 * t_0 * t_0 + k[46] * t_0 * t_0 + k[47] * t_0 + k[48]) * sqrt(f_1 * f_1 + 4 * f_0 * f_2))
//// + (k[50] + k[62]) * t_0 * t_0 * t_0 * t_0 * t_0 + (k[52] + k[64]) * t_0 * t_0 * t_0 * t_0 + (k[54] + k[66]) * t_0 * t_0 * t_0 + (k[56] + k[67]) * t_0 * t_0 + (k[59] + k[68]) * t_0 + k[60],
//// ' ');
////
//// Write('debug80: ',
//// 0 = Round((k[45] * t_0 * t_0 * t_0 + k[46] * t_0 * t_0 + k[47] * t_0 + k[48]) * sqrt(k[31] * t_0 * t_0 * t_0 * t_0 + k[132] * t_0 * t_0 * t_0 + k[133] * t_0 * t_0 + k[134] * t_0 + k[58])
//// + k[69] * t_0 * t_0 * t_0 * t_0 * t_0 + k[70] * t_0 * t_0 * t_0 * t_0 + k[71] * t_0 * t_0 * t_0 + k[72] * t_0 * t_0 + k[73] * t_0 + k[60]),
//// ' ');
//// WriteLn;
//// WriteLn(' 0 = ((', k[45], ') * x^3 + (', k[46], ') * x^2 + (', k[47], ') * x + (', k[48], ')) * sqrt((', k[31], ') * x^4 + (', k[132], ') * x^3 + (', k[133], ') * x^2 + (', k[134], ') * x + (', k[58], ')) + (',
//// k[69], ') * x^5 + (', k[70], ') * x^4 + (', k[71], ') * x^3 + (', k[72], ') * x^2 + (', k[73], ') * x + (', k[60], ')');
//
// Write('debug83: ',
// (k[45] * t_0 * t_0 * t_0 + k[46] * t_0 * t_0 + k[47] * t_0 + k[48]) * (k[45] * t_0 * t_0 * t_0 + k[46] * t_0 * t_0 + k[47] * t_0 + k[48]) * (k[31] * t_0 * t_0 * t_0 * t_0 + k[132] * t_0 * t_0 * t_0 + k[133] * t_0 * t_0 + k[134] * t_0 + k[58]) =
// (k[69] * t_0 * t_0 * t_0 * t_0 * t_0 + k[70] * t_0 * t_0 * t_0 * t_0 + k[71] * t_0 * t_0 * t_0 + k[72] * t_0 * t_0 + k[73] * t_0 + k[60]) * (k[69] * t_0 * t_0 * t_0 * t_0 * t_0 + k[70] * t_0 * t_0 * t_0 * t_0 + k[71] * t_0 * t_0 * t_0 + k[72] * t_0 * t_0 + k[73] * t_0 + k[60]),
// ' ');
// Write('debug85: ',
// 0 =
// (
// k[45] * k[45] * t_0 * t_0 * t_0 * t_0 * t_0 * t_0
// + 2 * k[45] * k[46] * t_0 * t_0 * t_0 * t_0 * t_0
// + k[46] * k[46] * t_0 * t_0 * t_0 * t_0
// + 2 * k[45] * k[47] * t_0 * t_0 * t_0 * t_0
// + 2 * k[45] * k[48] * t_0 * t_0 * t_0
// + 2 * k[46] * k[47] * t_0 * t_0 * t_0
// + k[47] * k[47] * t_0 * t_0
// + 2 * k[46] * k[48] * t_0 * t_0
// + 2 * k[47] * k[48] * t_0
// + k[48] * k[48]
// ) * (k[31] * t_0 * t_0 * t_0 * t_0 + k[132] * t_0 * t_0 * t_0 + k[133] * t_0 * t_0 + k[134] * t_0 + k[58])
// - k[69] * k[69] * t_0 * t_0 * t_0 * t_0 * t_0 * t_0 * t_0 * t_0 * t_0 * t_0
// - 2 * k[69] * k[70] * t_0 * t_0 * t_0 * t_0 * t_0 * t_0 * t_0 * t_0 * t_0
// - (k[70] * k[70] + 2 * k[69] * k[71]) * t_0 * t_0 * t_0 * t_0 * t_0 * t_0 * t_0 * t_0
// - 2 * (k[69] * k[72] + k[70] * k[71]) * t_0 * t_0 * t_0 * t_0 * t_0 * t_0 * t_0
// - (k[71] * k[71] + 2 * k[69] * k[73] + 2 * k[70] * k[72]) * t_0 * t_0 * t_0 * t_0 * t_0 * t_0
// - 2 * (k[69] * k[60] + k[70] * k[73] + k[71] * k[72]) * t_0 * t_0 * t_0 * t_0 * t_0
// - (k[72] * k[72] + 2 * k[70] * k[60] + 2 * k[71] * k[73]) * t_0 * t_0 * t_0 * t_0
// - 2 * (k[71] * k[60] + k[72] * k[73]) * t_0 * t_0 * t_0
// - (k[73] * k[73] + 2 * k[72] * k[60]) * t_0 * t_0
// - 2 * k[73] * k[60] * t_0
// - k[60] * k[60],
// ' ');
//
// WriteLn('debug96: ', EvaluateAt(t_0) = 0);
//
// NormalizeCoefficients;
//
// WriteLn('debug99: ', EvaluateAt(t_0) = 0, ' ');
//end;
//
//function TFirstCollisionPolynomial.EvaluateAt(const AT0: Int64): TBigInt;
//var
// i: Low(FA)..High(FA);
//begin
// Result := TBigInt.Zero;
// for i := High(FA) downto Low(FA) do
// Result := Result * AT0 + FA[i];
//end;
//
//function TFirstCollisionPolynomial.CalcPositiveIntegerRoot: Int64;
//var
// dividers: TDividers;
// factors: TInt64Array;
// divider: Int64;
//begin
// Result := 0;
// //factors := TIntegerFactorization.PollardsRhoAlgorithm(FA[0]);
// //dividers := TDividers.Create(factors);
// //
// //try
// //for divider in dividers do
// //begin
// // //WriteLn('Check if ', divider, ' is a root...');
// // if EvaluateAt(divider) = 0 then
// // begin
// // Result := divider;
// // Break;
// // end;
// //end;
// //
// //finally
// // dividers.Free;
// //end;
//end;
//
//function TFirstCollisionPolynomial.CalcT1(const AT0: Int64): Int64;
//var
// g_0, g_1, g_2: Int64;
// g: Extended;
//begin
// //g_2 := FH[0] * AT0 + FH[1];
// //g_1 := FH[2] * AT0 * AT0 + FH[3] * AT0 + FH[4];
// //g_0 := FH[5] * AT0 * AT0 + FH[6] * AT0;
// //g := - g_1 / (2 * g_2);
// //Result := Round(g + sqrt(g * g + g_0));
//end;
{ TNeverTellMeTheOdds }
function TNeverTellMeTheOdds.AreIntersecting(constref AHailstone1, AHailstone2: THailstone): Boolean;
@ -60,58 +563,141 @@ var
m1, m2, x, y: Double;
begin
Result := False;
m1 := AHailstone1.VY / AHailstone1.VX;
m2 := AHailstone2.VY / AHailstone2.VX;
m1 := AHailstone1.Velocity.Y / AHailstone1.Velocity.X;
//m1 := AHailstone1.Velocity.data[1] / AHailstone1.Velocity.data[0];
m2 := AHailstone2.Velocity.Y / AHailstone2.Velocity.X;
//m2 := AHailstone2.Velocity.data[1] / AHailstone2.Velocity.data[0];
if m1 <> m2 then
begin
x := (AHailstone2.Y - m2 * AHailstone2.X - AHailstone1.Y + m1 * AHailstone1.X) / (m1 - m2);
x := (AHailstone2.Position.Y - m2 * AHailstone2.Position.X
- AHailstone1.Position.Y + m1 * AHailstone1.Position.X)
/ (m1 - m2);
//x := (AHailstone2.Position.data[1] - m2 * AHailstone2.Position.data[0]
// - AHailstone1.Position.data[1] + m1 * AHailstone1.Position.data[0])
// / (m1 - m2);
if (FMin <= x) and (x <= FMax)
and (x * Sign(AHailstone1.VX) >= AHailstone1.X * Sign(AHailstone1.VX))
and (x * Sign(AHailstone2.VX) >= AHailstone2.X * Sign(AHailstone2.VX)) then
and (x * Sign(AHailstone1.Velocity.X) >= AHailstone1.Position.X * Sign(AHailstone1.Velocity.X))
//and (x * Sign(AHailstone1.Velocity.data[0]) >= AHailstone1.Position.data[0] * Sign(AHailstone1.Velocity.data[0]))
and (x * Sign(AHailstone2.Velocity.X) >= AHailstone2.Position.X * Sign(AHailstone2.Velocity.X))
//and (x * Sign(AHailstone2.Velocity.data[0]) >= AHailstone2.Position.data[0] * Sign(AHailstone2.Velocity.data[0]))
then
begin
y := m1 * (x - AHailstone1.X) + AHailstone1.Y;
y := m1 * (x - AHailstone1.Position.X) + AHailstone1.Position.Y;
y := m1 * (x - AHailstone1.Position.X) + AHailstone1.Position.Y;
if (FMin <= y) and (y <= FMax) then
Result := True
end;
end;
end;
// For debug calculations:
Const
T : array[0..4] of Byte = (5, 3, 4, 6, 1);
procedure TNeverTellMeTheOdds.FindRockThrow(const AIndex1, AIndex2, AIndex3: Integer);
var
i: TVector3DataRange;
//i, j, k: Integer;
//x0, x1, x2: Extended;
//f: TFirstCollisionPolynomial;
t0, t1, t2, t0Min, t0Max, t1Min, t1Max, t2Min, t2Max: Int64;
boundary: Int64;
//p, v: Tvector3_extended;
//test: TBigInt;
begin
//WriteLn;
WriteLn(AIndex1, ' ', AIndex2, ' ', AIndex3, ' ');
t0Min := FHailstones[AIndex1].GetParameterMinimum(FMin, FMax);
t0Max := FHailstones[AIndex1].GetParameterMaximum(FMin, FMax);
WriteLn('t0 bounds: ', t0Min, ' ', t0Max);
t1Min := FHailstones[AIndex2].GetParameterMinimum(FMin, FMax);
t1Max := FHailstones[AIndex2].GetParameterMaximum(FMin, FMax);
WriteLn('t1 bounds: ', t1Min, ' ', t1Max);
t2Min := FHailstones[AIndex3].GetParameterMinimum(FMin, FMax);
t2Max := FHailstones[AIndex3].GetParameterMaximum(FMin, FMax);
WriteLn('t2 bounds: ', t2Min, ' ', t2Max);
//t0 := t0Min >> 1 + t0Max >> 1;
//WriteLn('t0: ', t0);
//t1 := t1Min >> 1 + t1Max >> 1;
//WriteLn('t1: ', t1);
//t2 := t2Min >> 1 + t2Max >> 1;
//WriteLn('t2: ', t2);
//f := TFirstCollisionPolynomial.Create;
//f.Init(FHailstones[AIndex1], FHailstones[AIndex2], FHailstones[AIndex3], T[AIndex1], T[AIndex2], T[AIndex3]);
////t0 := f.CalcPositiveIntegerRoot;
////WriteLn('t0: ', t0, ' ', t0 = T[AIndex1]);
////t1 := f.CalcT1(t0);
////WriteLn(', t1: ', t1);
//f.Free;
//// V_x = (V_0 * t_0 - V_1 * t_1 + P_0 - P_1) / (t_0 - t_1)
//v := (FHailstones[AIndex1].Velocity * t0 - FHailstones[AIndex2].Velocity * t1
// + FHailstones[AIndex1].Position - FHailstones[AIndex2].Position) / (t0 - t1);
//// P_x = (V_0 - V_x) * t_0 + P_0
//p := (FHailstones[AIndex1].Velocity - v) * t0 + FHailstones[AIndex1].Position;
//FPart2 := Round(p.data[0]) + Round(p.data[1]) + Round(p.data[2]);
//for i := 0 to FHailstones.Count - 3 do
// for j := i + 1 to FHailstones.Count - 2 do
// for k:= j + 1 to FHailstones.Count - 1 do
// begin
// WriteLn(i, j, k);
// solver := TRockThrowSolver.Create(FHailstones[i], FHailstones[j], FHailstones[k], 0);
// case i of
// 0: x0 := 5;
// 1: x0 := 3;
// 2: x0 := 4;
// end;
// f := solver.CalcValue(x0);
// solver.Free;
// end;
//for i := 80 to 120 do
//begin
// solver := TRockThrowSolver.Create(FHailstones[0], FHailstones[1], FHailstones[2], 0);
// x0 := i / 20;
// f := solver.CalcValue(x0);
// WriteLn(x0, ' ', f.Valid, ' ', f.Value);
// solver.Free;
//end;
end;
constructor TNeverTellMeTheOdds.Create(const AMin: Int64; const AMax: Int64);
begin
FMin := AMin;
FMax := AMax;
FHailStones := THailstones.Create;
FHailstones := THailstones.Create;
end;
destructor TNeverTellMeTheOdds.Destroy;
begin
FHailStones.Free;
FHailstones.Free;
inherited Destroy;
end;
procedure TNeverTellMeTheOdds.ProcessDataLine(const ALine: string);
var
split: TStringArray;
hailstone: THailstone;
begin
split := ALine.Split([',', '@']);
hailstone.X := StrToInt64(Trim(split[0]));
hailstone.Y := StrToInt64(Trim(split[1]));
hailstone.Z := StrToInt64(Trim(split[2]));
hailstone.VX := StrToInt(Trim(split[3]));
hailstone.VY := StrToInt(Trim(split[4]));
hailstone.VZ := StrToInt(Trim(split[5]));
FHailStones.Add(hailstone);
FHailstones.Add(THailstone.Create(ALine));
end;
procedure TNeverTellMeTheOdds.Finish;
var
i, j: Integer;
i, j, k: Integer;
begin
for i := 0 to FHailStones.Count - 2 do
for j := i + 1 to FHailStones.Count - 1 do
if AreIntersecting(FHailStones[i], FHailStones[j]) then
for i := 0 to FHailstones.Count - 2 do
for j := i + 1 to FHailstones.Count - 1 do
if AreIntersecting(FHailstones[i], FHailstones[j]) then
Inc(FPart1);
//for i := 0 to FHailstones.Count - 1 do
// for j := 0 to FHailstones.Count - 1 do
// for k := 0 to FHailstones.Count - 1 do
// if (i <> j) and (i <> k) and (j <> k) then
// FindRockThrow(i, j, k);
FindRockThrow(0, 1, 2);
end;
function TNeverTellMeTheOdds.GetDataFileName: string;

View File

@ -33,6 +33,7 @@ type
function CreateSolver: ISolver; override;
published
procedure TestPart1;
procedure TestPart2;
end;
{ TNeverTellMeTheOddsExampleTestCase }
@ -42,6 +43,7 @@ type
function CreateSolver: ISolver; override;
published
procedure TestPart1;
procedure TestPart2;
end;
{ TNeverTellMeTheOddsTestCase }
@ -77,6 +79,11 @@ begin
AssertEquals(15107, FSolver.GetResultPart1);
end;
procedure TNeverTellMeTheOddsFullDataTestCase.TestPart2;
begin
AssertEquals(-1, FSolver.GetResultPart2);
end;
{ TNeverTellMeTheOddsExampleTestCase }
function TNeverTellMeTheOddsExampleTestCase.CreateSolver: ISolver;
@ -89,6 +96,11 @@ begin
AssertEquals(2, FSolver.GetResultPart1);
end;
procedure TNeverTellMeTheOddsExampleTestCase.TestPart2;
begin
AssertEquals(47, FSolver.GetResultPart2);
end;
{ TNeverTellMeTheOddsTestCase }
function TNeverTellMeTheOddsTestCase.CreateSolver: ISolver;