Showing posts with label Continued Fractions. Show all posts
Showing posts with label Continued Fractions. Show all posts

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();
}
}
}

Tuesday, 21 April 2009

PROJECT EULER #65

Link to Project Euler problem 65

The square root of 2 can be written as an infinite continued fraction.

√2 = 1 +
1


2 +
1



2 +
1




2 +
1





2 + ...

The infinite continued fraction can be written, √2 = [1;(2)], (2) indicates that 2 repeats ad infinitum. In a similar way, √23 = [4;(1,3,1,8)].

It turns out that the sequence of partial values of continued fractions for square roots provide the best rational approximations. Let us consider the convergents for √2.

1 +
1

= 3/2

2

1 +
1

= 7/5

2 +
1



2

1 +
1

= 17/12

2 +
1




2 +
1





2

1 +
1

= 41/29

2 +
1



2 +
1





2 +
1






2

Hence the sequence of the first ten convergents for √2 are:

1, 3/2, 7/5, 17/12, 41/29, 99/70, 239/169, 577/408, 1393/985, 3363/2378, ...

What is most surprising is that the important mathematical constant,
e = [2; 1,2,1, 1,4,1, 1,6,1 , ... , 1,2k,1, ...].

The first ten terms in the sequence of convergents for e are:

2, 3, 8/3, 11/4, 19/7, 87/32, 106/39, 193/71, 1264/465, 1457/536, ...

The sum of digits in the numerator of the 10^(th) convergent is 1+4+5+7=17.

Find the sum of digits in the numerator of the 100^(th) convergent of the continued fraction for e.


using System;

namespace project_euler
{
class Program
{
static void Main()
{
//Problem 65
DateTime start = DateTime.Now;
//e = [2;1,2,1,1,4,1,1,6,1,....,1,2k,1,...]
//numerator_n = a_n * numerator_n-1 + numerator_n-2
//denominator_n = a_n * denominator_n-1 + denominator_n-2
BigInt numerator_2 = 2, numerator_1 = 3, numerator=0;
//BigInt denominator_1 = 1,denominator_2 = 1, denominator;
int sum = 0;
for (int i = 2; i < 100; i++)
{
int a = (i + 1) % 3 == 0 ? 2 * ((i + 1) / 3) : 1;
numerator = numerator_1 * a + numerator_2;
numerator_2 = numerator_1;
numerator_1 = numerator;
//denominator = a * denominator_1 + denominator_2;
//denominator_2 = denominator_1;
//denominator_1 = denominator;
//Console.WriteLine(numerator);
//Console.WriteLine("-----------------------------------------");
//Console.WriteLine(denominator);
}
char[] c = numerator.ToString().ToCharArray();
foreach (char c1 in c)
sum += int.Parse(c1.ToString());
Console.WriteLine(sum);
TimeSpan time = DateTime.Now - start;
Console.WriteLine("This took {0}", time);
Console.ReadKey();
}
}
}

PROJECT EULER #64

Link to Project Euler problem 64

All square roots are periodic when written as continued fractions and can be written in the form:

√N = a_(0) +
1


a_(1) +
1



a_(2) +
1




a_(3) + ...

For example, let us consider √23:

√23 = 4 + √23 — 4 = 4 +
1

= 4 +
1


1

√23—4

1 +
√23 – 3

7

If we continue we would get the following expansion:

√23 = 4 +
1


1 +
1



3 +
1




1 +
1





8 + ...

The process can be summarised as follows:

a_(0) = 4,
1

√23—4
=
√23+4

7
= 1 +
√23—3

7
a_(1) = 1,
7

√23—3
=
7(√23+3)

14
= 3 +
√23—3

2
a_(2) = 3,
2

√23—3
=
2(√23+3)

14
= 1 +
√23—4

7
a_(3) = 1,
7

√23—4
=
7(√23+4)

7
= 8 + √23—4
a_(4) = 8,
1

√23—4
=
√23+4

7
= 1 +
√23—3

7
a_(5) = 1,
7

√23—3
=
7(√23+3)

14
= 3 +
√23—3

2
a_(6) = 3,
2

√23—3
=
2(√23+3)

14
= 1 +
√23—4

7
a_(7) = 1,
7

√23—4
=
7(√23+4)

7
= 8 + √23—4

It can be seen that the sequence is repeating. For conciseness, we use the notation √23 = [4;(1,3,1,8)], to indicate that the block (1,3,1,8) repeats indefinitely.

The first ten continued fraction representations of (irrational) square roots are:

√2=[1;(2)], period=1
√3=[1;(1,2)], period=2
√5=[2;(4)], period=1
√6=[2;(2,4)], period=2
√7=[2;(1,1,1,4)], period=4
√8=[2;(1,4)], period=2
√10=[3;(6)], period=1
√11=[3;(3,6)], period=2
√12= [3;(2,6)], period=2
√13=[3;(1,1,1,1,6)], period=5

Exactly four continued fractions, for N ≤ 13, have an odd period.

How many continued fractions for N ≤ 10000 have an odd period?

This was certainly an education in continued fractions. Having understood them the trick is to find a way to calculate the salient numbers for the next iteration. 62.5 ms. Uncomment the foreach loop to print the series.


using System;
using System.Collections.Generic;

namespace project_euler
{
class Program
{
static void Main()
{
//Problem 64
DateTime start = DateTime.Now;
Dictionary<int, List<int>> numbers = new Dictionary<int, List<int>>();
for (int number = 2; number <= 10000; number++)
{
bool repeat = false;
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);
if (integerPart == 2 * numbers[number][0]) repeat = true;
} while (!repeat);
}
int oddSequence=0;
foreach (KeyValuePair<int, List<int>> pair in numbers)
{
if ((pair.Value.Count - 1)%2 != 0)
oddSequence++;
//Console.Write(pair.Key + ": ");
//foreach (int sequence in pair.Value)
// Console.Write(sequence + ", ");
//Console.WriteLine();
}
Console.WriteLine(oddSequence);
TimeSpan time = DateTime.Now - start;
Console.WriteLine("This took {0}", time);
Console.ReadKey();
}
}
}