Thursday 23 April 2009

PROJECT EULER #66

Link to Project Euler problem 66

Consider quadratic Diophantine equations of the form:
x2 – Dy2 = 1
For example, when D = 13, the minimal solution in x is 6492 – 13 x 1802 = 1.
It can be assumed that there are no solutions in positive integers when D is square.
By finding minimal solutions in x for D = {2, 3, 5, 6, 7}, we obtain the following:
32 – 2 x 22 = 1
22 – 3 x 12 = 1
92 – 5 x 42 = 1
52 – 6 x 22 = 1
82 – 7 x 32 = 1
Hence, by considering minimal solutions in x for D <= 7, the largest x is obtained when D = 5. Find the value of D 1000 in minimal solutions of x for which the largest value of x is obtained.

This was the synthesis of the two previous questions, with a bit of study at wolfram.com (here and here) and some pencil and paper walkthroughs it was do-able. I guess I've used 15 hours to do these three problems. Uncommenting the commented statements prints the [a0;(a1,a2,....ar,ar+1)] series and the pr / qr or p2r+1 / q2r+1 (depending on the parity of the series) convergents for each number.


using System;
using System.Collections.Generic;

namespace ProjectEuler
{
class Program
{
static void Main()
{
//Problem 66
DateTime start = DateTime.Now;
//first the code from problem 64
Dictionary<int, List<int>> numbers = new Dictionary<int, List<int>>();
for (int number = 2; number <= 1000; number++)
{
bool repeat;
int a = (int)Math.Sqrt(number);
List<int> sequence = new List<int> { a };
numbers.Add(number, sequence);
int x = 1;
do
{
if (Math.Sqrt(number) - (int)Math.Sqrt(number) == 0) break;
int b = number - a * a;
int integerPart = x * ((int)Math.Sqrt(number) + a) / b;
numbers[number].Add(integerPart);
a = -(a - integerPart * (b / x));
x = (b / x);
repeat = integerPart == 2 * numbers[number][0] ? true : false;
} while (!repeat);
}
//then the modified code from problem 65
BigInt maxNumerator=0;
int d = 0;
for (int i = 2; i <= 1000; i++)
{
if (Math.Sqrt(i) - (int)Math.Sqrt(i)!=0)
{
int r = numbers[i].Count-1;
BigInt numerator_2 = 0, numerator_1 = 1, numerator = 0;
BigInt denominator_2 = 1, denominator_1 = 0, denominator = 0;
//var sequence = numbers[i];

if ((r) % 2 != 0)//is odd
{
//Console.Write("r is even ");
//Console.Write("Sqrt " + i + ": [");
//Console.Write(sequence[0] + ";(");
//for (int j = 1; j < sequence.Count; j++)
// if (j < sequence.Count - 1)
// Console.Write(sequence[j] + ",");
// else
// Console.WriteLine(sequence[j] + ")]");
//Console.WriteLine();
for (int j = 0; j < numbers[i].Count; j++)
{
numerator = numbers[i][j] * numerator_1 + numerator_2;
numerator_2 = numerator_1;
numerator_1 = numerator;
denominator = numbers[i][j] * denominator_1 + denominator_2;
denominator_2 = denominator_1;
denominator_1 = denominator;
}
for (int j = 1; j < numbers[i].Count-1; j++)
{
numerator = numbers[i][j] * numerator_1 + numerator_2;
numerator_2 = numerator_1;
numerator_1 = numerator;
denominator = numbers[i][j] * denominator_1 + denominator_2;
denominator_2 = denominator_1;
denominator_1 = denominator;
}
}
else//is even
{
//Console.Write("r is odd");
//Console.Write("Sqrt " + i + ": [");
//Console.Write(sequence[0] + ";(");
//for (int j = 1; j < sequence.Count; j++)
// if (j < sequence.Count - 1)
// Console.Write(sequence[j] + ",");
// else
// Console.WriteLine(sequence[j] + ")]");
//Console.WriteLine();
for (int j = 0; j < numbers[i].Count-1; j++)
{
numerator = numbers[i][j] * numerator_1 + numerator_2;
numerator_2 = numerator_1;
numerator_1 = numerator;
denominator = numbers[i][j] * denominator_1 + denominator_2;
denominator_2 = denominator_1;
denominator_1 = denominator;
}
}
if (numerator > maxNumerator)
{
maxNumerator = numerator;
d = i;
}
//Console.WriteLine("x = " + numerator.ToString());
//Console.WriteLine("y = " + denominator.ToString());
//Console.WriteLine("-----------------------------------------");
}
}
Console.WriteLine(d);
TimeSpan time = DateTime.Now - start;
Console.WriteLine("This took {0}", time);
Console.ReadKey();
}
}
}

No comments: