Sunday 19 April 2009

PROJECT EULER #61

Link to Project Euler problem 61

Triangle, square, pentagonal, hexagonal, heptagonal, and octagonal numbers are all figurate (polygonal) numbers and are generated by the following formulae:

Triangle
P_(3,n)=n(n+1)/2
1, 3, 6, 10, 15, ...
Square
P_(4,n)=n^(2)
1, 4, 9, 16, 25, ...
Pentagonal
P_(5,n)=n(3n-1)/2
1, 5, 12, 22, 35, ...
Hexagonal
P_(6,n)=n(2n-1)
1, 6, 15, 28, 45, ...
Heptagonal
P_(7,n)=n(5n-3)/2
1, 7, 18, 34, 55, ...
Octagonal
P_(8,n)=n(3n-2)
1, 8, 21, 40, 65, ...

The ordered set of three 4-digit numbers: 8128, 2882, 8281, has three interesting properties.

  1. The set is cyclic, in that the last two digits of each number is the first two digits of the next number (including the last number with the first).
  2. Each polygonal type: triangle (P_(3,127)=8128), square (P_(4,91)=8281), and pentagonal (P_(5,44)=2882), is represented by a different number in the set.
  3. This is the only set of 4-digit numbers with this property.

Find the sum of the only ordered set of six cyclic 4-digit numbers for which each polygonal type: triangle, square, pentagonal, hexagonal, heptagonal, and octagonal, is represented by a different number in the set.

This has to be the ugliest thing I've written, but at 375 ms what the heck! I worked out the smallest number in the set for each figurate type which would result in a 4 digit number, then I create them and add them all to a dictionary with a key specifying the type and the number from the set, then I do 6 nested foreaches (yes it smells!) with conditions. The program finds 6 identical solutions (of course) so I stop it when 1 is found. The keys and values are printed to make sure I got it right!

using System;
using System.Collections.Generic;

namespace project_euler
{
class Program
{
static void Main()
{
//Problem 61
DateTime start = DateTime.Now;
bool finished = false;
var numbers = new Dictionary<string, string>();
for (int i = 45; i * (i + 1) / 2 < 10000; i++)
numbers.Add("tri" + i, (i * (i + 1) / 2).ToString());
for (int j = 32; j * j < 10000; j++)
numbers.Add("squ" + j, (j * j).ToString());
for (int k = 26; k * (3 * k - 1) < 10000; k++)
numbers.Add("pen" + k, (k * (3 * k - 1) / 2).ToString());
for (int l = 23; l * (2 * l - 1) < 10000; l++)
numbers.Add("hex" + l, (l * (2 * l - 1)).ToString());
for (int m = 21; m * (5 * m - 3) / 2 < 10000; m++)
numbers.Add("hep" + m, (m * (5 * m - 3) / 2).ToString());
for (int n = 19; n * (3 * n - 2) < 10000; n++)
numbers.Add("oct" + n, (n * (3 * n - 2)).ToString());
//pick a number, find its type and original int,
foreach (KeyValuePair<string, string> pair1 in numbers)
{
string s = pair1.Value;
string sk = pair1.Key;
string sn = sk.Substring(3, sk.Length - 3);
string sm = sk.Substring(0, 3);
foreach (KeyValuePair<string, string> pair2 in numbers)
if (!pair2.Key.StartsWith(sm) &&
pair2.Key.Substring(3, pair2.Key.Length - 3) != sn)
if (pair2.Value.StartsWith(s.Substring(2, 2)))
{
string t = pair2.Value;
string tk = pair2.Key;
string tn = tk.Substring(3, tk.Length - 3);
string tm = tk.Substring(0, 3);
foreach (KeyValuePair<string, string> pair3 in numbers)
if (!pair3.Key.StartsWith(sm) &&
!pair3.Key.StartsWith(tm) &&
pair3.Key.Substring(3, pair3.Key.Length - 3) != sn &&
pair3.Key.Substring(3, pair3.Key.Length - 3) != tn)
if (pair3.Value.StartsWith(t.Substring(2, 2)))
{
string u = pair3.Value;
string uk = pair3.Key;
string un = uk.Substring(3, uk.Length - 3);
string um = uk.Substring(0, 3);
foreach (KeyValuePair<string, string> pair4 in numbers)
if (!pair4.Key.StartsWith(sm) &&
!pair4.Key.StartsWith(tm) &&
!pair4.Key.StartsWith(um) &&
pair4.Key.Substring(3, pair4.Key.Length - 3) != sn &&
pair4.Key.Substring(3, pair4.Key.Length - 3) != tn &&
pair4.Key.Substring(3, pair4.Key.Length - 3) != un)
if (pair4.Value.StartsWith(u.Substring(2, 2)))
{
string v = pair4.Value;
string vk = pair4.Key;
string vn = vk.Substring(3, vk.Length - 3);
string vm = vk.Substring(0, 3);
foreach (KeyValuePair<string, string> pair5 in numbers)
if (!pair5.Key.StartsWith(sm) &&
!pair5.Key.StartsWith(tm) &&
!pair5.Key.StartsWith(um) &&
!pair5.Key.StartsWith(vm) &&
pair5.Key.Substring(3, pair5.Key.Length - 3) != sn &&
pair5.Key.Substring(3, pair5.Key.Length - 3) != tn &&
pair5.Key.Substring(3, pair5.Key.Length - 3) != un &&
pair5.Key.Substring(3, pair5.Key.Length - 3) != vn)
if (pair5.Value.StartsWith(v.Substring(2, 2)))
{
string w = pair5.Value;
string wk = pair5.Key;
string wn = wk.Substring(3, wk.Length - 3);
string wm = wk.Substring(0, 3);
foreach (KeyValuePair<string, string> pair6 in numbers)
if (!pair6.Key.StartsWith(sm) &&
!pair6.Key.StartsWith(tm) &&
!pair6.Key.StartsWith(um) &&
!pair6.Key.StartsWith(vm) &&
!pair6.Key.StartsWith(wm) &&
pair6.Key.Substring(3, pair6.Key.Length - 3) != sn &&
pair6.Key.Substring(3, pair6.Key.Length - 3) != tn &&
pair6.Key.Substring(3, pair6.Key.Length - 3) != un &&
pair6.Key.Substring(3, pair6.Key.Length - 3) != vn &&
pair6.Key.Substring(3, pair6.Key.Length - 3) != wn)
if (pair6.Value.StartsWith(w.Substring(2, 2)) &&
pair6.Value.Substring(2, 2) == s.Substring(0, 2))
{
string x = pair6.Value;
string xk = pair6.Key;
int sum = int.Parse(s) +
int.Parse(t) +
int.Parse(u) +
int.Parse(v) +
int.Parse(w) +
int.Parse(x);
Console.WriteLine(sum);
Console.WriteLine(sk + " " + tk + " " + uk + " " + vk + " " + wk + " " + xk);
Console.WriteLine(s + " " + t + " " + u + " " + v + " " + w + " " + x);
finished = true;
break;
}
if (finished) break;
}
if (finished) break;
}
if (finished) break;
}
if (finished) break;
}
if (finished) break;
}
TimeSpan time = DateTime.Now - start;
Console.WriteLine("This took {0}", time);
Console.ReadKey();
}
}
}
Triple-click for answer: 28684

No comments: