Friday, April 15, 2011

Project Euler - Problem 13 - Spreadsheet

I've copied the whole given table to a spreadsheet (open office was good enough). Then, I've summed them all and divided by 10^42 to get the first 10 digits.

Here are the first leading 10 digits: 5537376230.

Project Euler - Problem 10 - C#

http://projecteuler.net/project/resources/010_7c4950764b52402fe1d29323af4e6c6f/010_overview.pdf
//The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
//Find the sum of all the primes below two million.
static UInt64 Problem10()
{
 UInt64 sum_of_primes = 0;

 foreach (var prime in primes(2000000))
 {
  sum_of_primes += prime;
  //Console.Write(prime.ToString() + ", ");
 }

 return sum_of_primes;

 // Problem10: 142913828922
}

static IEnumerable<UInt64> primes(UInt64 limit)
{
 List<UInt64> primes_list = new List<UInt64>(); // reset with 0
 bool[] nums_list = new bool[limit]; // reset with 0

 /* Create a list of all candidates. 
  * false    - Marks an invalid candidate.
  * true     - A valid candidate.
  */
 nums_list[2] = true;
 primes_list.Add(2);
 for (UInt64 current_num = 3; current_num <= limit; current_num += 2)
 {
  nums_list[current_num] = true;
 }

 // Sieve of Eratosthenes algorithm
 for (UInt64 current_num = 3; current_num <= limit; current_num += 2)
 {
  if (nums_list[current_num] == true)
  {
   primes_list.Add(current_num);

   for (UInt64 elemenator = 2 * current_num;
    elemenator < limit;
    elemenator += current_num)
   {
    nums_list[elemenator] = false;
   }
  }
 }

 foreach (var prime in primes_list)
 {
  yield return prime;
 }
}

Project Euler - Problem 9 - C#

/*
 A Pythagorean triplet is a set of three natural numbers, a  b  c, for which,

 a^2 + b^2 = c^2
 For example, 3^2 + 4^2 = 9 + 16 = 25 = 5^2.

 There exists exactly one Pythagorean triplet for which a + b + c = 1000.
 Find the product abc.
 */
static int Problem9()
{
 /* HLD:
  * a + b + c = 1000 ==>  c = 1000 - a - b
  * foreach {a, b} in {{1,1}, {1,2} ... {2,2} ... {499,1} ... {499,499}}
  * predicate of pass: a^2 + b^2 = c^2
  */

 var solution_found = false;
 int a = 0, b = 0;
 int c = 1000;

 for (b = 1; b < 499; b++)
 {
  c = 1000;

  for (a = b; a <= c; a++)
  {
   c = 1000 - a - b;

   if ((a * a + b * b) == (c * c))
   {
    solution_found = true;
    break;
   }
  }

  if (solution_found)
  {
   break;
  }
 }

 return a * b * c;

 // Problem9: 31875000
}

Thursday, April 14, 2011

Project Euler - Problem 8 - C#

/*
Find the greatest product of five consecutive digits in the 1000-digit number.
  
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450
 */
static int Problem8()
{
 StringBuilder data = new StringBuilder(1000);
 data.Append("73167176531330624919225119674426574742355349194934");
 data.Append("96983520312774506326239578318016984801869478851843");
 data.Append("85861560789112949495459501737958331952853208805511");
 data.Append("12540698747158523863050715693290963295227443043557");
 data.Append("66896648950445244523161731856403098711121722383113");
 data.Append("62229893423380308135336276614282806444486645238749");
 data.Append("30358907296290491560440772390713810515859307960866");
 data.Append("70172427121883998797908792274921901699720888093776");
 data.Append("65727333001053367881220235421809751254540594752243");
 data.Append("52584907711670556013604839586446706324415722155397");
 data.Append("53697817977846174064955149290862569321978468622482");
 data.Append("83972241375657056057490261407972968652414535100474");
 data.Append("82166370484403199890008895243450658541227588666881");
 data.Append("16427171479924442928230863465674813919123162824586");
 data.Append("17866458359124566529476545682848912883142607690042");
 data.Append("24219022671055626321111109370544217506941658960408");
 data.Append("07198403850962455444362981230987879927244284909188");
 data.Append("84580156166097919133875499200524063689912560717606");
 data.Append("05886116467109405077541002256983155200055935729725");
 data.Append("71636269561882670428252483600823257530420752963450");

 const int aggregation_consecutives = 5;

 // Starting point initialization
 var data_string = data.ToString();
 var global_max_mul = 0;
 var consicutives_so_far = 0;
 var local_max_mul = 1;
 var tail_num = 0;
 var current_num = 0;
  
 for (int current_char_idx = 0; current_char_idx < data.Length; current_char_idx++)
 {
  current_num = (int)data_string[current_char_idx] - '0';

  if (current_num == 0)
  {
   consicutives_so_far = 0;
   local_max_mul = 1;
   continue;
  }

  if (consicutives_so_far < aggregation_consecutives)
  {
   local_max_mul *= current_num;
   global_max_mul = Math.Max(global_max_mul, local_max_mul);

   consicutives_so_far++;

   continue;
  }

  tail_num = data_string[current_char_idx - 5] - '0';
  local_max_mul = (local_max_mul / tail_num) * current_num;
  global_max_mul = Math.Max(global_max_mul, local_max_mul);

  consicutives_so_far++;

  Console.WriteLine(string.Format(
   "current_char_idx:{0}, consicutives_so_far={1}, current_num={2} local_max_mul={3}",
   current_char_idx, consicutives_so_far, current_num, local_max_mul));
 }

 return global_max_mul;

 // Problem8: 40824
}

Wednesday, April 13, 2011

Project Euler - Problem 7 - Tcl

#By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
#What is the 10001st prime number?
proc problem7-v2 {} {
 # Much faster.
 #REMARK: Based on problem-3
 set primes [list 2 3]
 set current_number 5
 set primes_found 2

 set finished FALSE
 while { !$finished } {

  set is_prime TRUE
  foreach prime $primes {
   if { ( $current_number % $prime ) == 0  } {
    set is_prime FALSE
    break
   }

   if { $prime >  ($current_number / 2) } {
    # Can't be bigger than factor 2!
    break
   }
  }

  if { $is_prime } {
   incr primes_found 1
   set last_prime $current_number
   lappend primes $last_prime
  }

  set finished [expr $primes_found == 10001]

  incr current_number 2
 }

 puts "solution-7: [lindex $primes end]"
}

# solution-7: solution-7: 104743

Project Euler - Problem 6 - Tcl

#The sum of the squares of the first ten natural numbers is,
#1^2 + 2^2 + ... + 10^2 = 385
#
#The square of the sum of the first ten natural numbers is,
#(1 + 2 + ... + 10)^2 = 55^2 = 3025
#
#Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 - 385 = 2640.
#
#Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.
proc problem6 {} {
 set sum_of_squares 0
 set squares_of_sum 0

 for { set idx 1 } { $idx <= 100 } {incr idx} {
  set sum_of_squares [expr $sum_of_squares + ($idx * $idx)]
  set squares_of_sum [expr $squares_of_sum + $idx ]
 }

 set squares_of_sum [expr $squares_of_sum*$squares_of_sum]

 puts "Solution-6: [expr $squares_of_sum - $sum_of_squares]"
}

#Solution-6: 25164150

Project Euler - Problem 4 - Tcl

#A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91  99.
#Find the largest palindrome made from the product of two 3-digit numbers.
proc problem4 {} {
 set palindrom_found FALSE
 set current_palindrom [expr 999*999]

 while { $palindrom_found == FALSE } {
  set current_palindrom [next_polindrom $current_palindrom -1]

  for { set idx 999 } { $idx > 900 } {incr idx -1} {
   if { ( $current_palindrom % $idx ) == 0   &&   ($current_palindrom / $idx) < 1000 } {
    puts "$idx*[expr $current_palindrom / $idx]=$current_palindrom"
    set palindrom_found TRUE
    break
   }
  }
 }
}

#****f* math/next_polindrom
# FUNCTION
#  Generates the next polindrom according to a given polindrom.
#
# INPUTS
#  pre_polindrom:
#   * TBD
#  direction:
#   * (+n) - next (n) polindrom up
#   * (-n) - next (n) polindrom down
#
# RESULT
#  * int - The consecutive (n) polinom from the given number/polinom.
#  * {} - error with parameters or none found.
#
# EXAMPLE
#  TBD
#
# NOTES
# * Good for solving problem-4. Jumps from 100000 to 9999 (see BUGS).
#
# BUGS
#  * Wrong sequance: {... 102201 101101 100001 9999 9889 9779 ... }
#
# SYNOPSIS
proc next_polindrom { pre_polindrom direction } {
 # SOURCE
 # E.g. pre_polindrom ==> 123000
 set polindrom_len [expr round( ceil( log10( $pre_polindrom ))) ]
 set polindrom_mid_len [expr ($polindrom_len / 2) + ($polindrom_len % 2)]
 set digits_to_align [expr $polindrom_len - $polindrom_mid_len]

 set polindrom_core $pre_polindrom  ; # E.g. polindrom_core ==> 123000
 while { $digits_to_align > 0} {
  set polindrom_core [expr $polindrom_core / 10]

  incr digits_to_align -1
 }  ; # E.g. polindrom_core ==> 123

 incr polindrom_core $direction  ; # E.g. (of +1): polindrom_core ==> 124

 set splited_polindrom_core [split $polindrom_core {}]  ; # E.g. splited_polindrom_core ==> {1 2 3}

 set splited_reversed_polindrom_core [lreverse $splited_polindrom_core]  ; # E.g. splited_reversed_polindrom_core ==> {3 2 1}
 set splited_reversed_polindrom_core [lrange $splited_reversed_polindrom_core [expr $polindrom_len % 2] end]  ; # E.g. for 123000: {3 2 1} ==> {3 2 1}, for 12300: {3 2 1} ==> {2 1}
 set reversed_polindrom_core [join $splited_reversed_polindrom_core {}]  ; # E.g. splited_reversed_polindrom_core ==> {321}

 set next_polinom "$polindrom_core$reversed_polindrom_core"

 return $next_polinom
 ######
}

#Solution-4: 993*913=906609

Sunday, April 10, 2011

Project Euler - Problem 5 - Tcl

#2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
#What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
proc problem5 {} {
 # REMARK: Runs forever :)
 set dividers [list ]
 for { set idx 20 } { $idx >= 2 } {incr idx -1} {
  lappend dividers $idx
 }
 set largest_divider 20

 set divisible FALSE
 set current_number 20

 while { ! $divisible } {
  incr current_number $largest_divider

  set divisible TRUE
  foreach divider $dividers {
   if {( $current_number % $divider ) != 0} {
    set divisible FALSE
    break
   }
  }
 }

 foreach divider $dividers {
  puts "$current_number / $divider = [expr $current_number / $divider] + [expr $current_number % $divider]/$divider"
 }

 return $current_number
}

#2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
#What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
proc problem5-v2 {} {
 # REMARK: will get me very fast to the wanted number
 set largest_divider 1
 set dividers [list ]

 for { set idx 20 } { $idx >= 2 } {incr idx -1} {
  set largest_divider [expr $largest_divider * $idx]
  lappend dividers $idx
 }
 puts "largest divider=$largest_divider"

 foreach divider $dividers {
  while {( $largest_divider % $divider ) == 0} {
   set largest_divider [expr $largest_divider / $divider]
  }

  set largest_divider [expr $largest_divider * $divider]
 }

 foreach divider $dividers {
  puts "$largest_divider / $divider = [expr $largest_divider / $divider] + [expr $largest_divider % $divider]/$divider"
 }

 return $largest_divider  ;# == 9699690
}

proc problem5-v3 {} {
 # REMARK: Based on v2, all we need is to correct the results manually.
 set largest_divider [expr 9699690*4*3*2]

 set dividers [list ]
 
  for { set idx 20 } { $idx >= 2 } {incr idx -1} {
   lappend dividers $idx
  }
 
 
 foreach divider $dividers {
  puts "$largest_divider / $divider = [expr $largest_divider / $divider] + [expr $largest_divider % $divider]/$divider"
 }

}

# solution-4: 232792560

Project Euler - Problem 3 - Tcl

#The prime factors of 13195 are 5, 7, 13 and 29.
#What is the largest prime factor of the number 600851475143 ?
proc problem3 {} {
 set target_number 600851475143
 set primes [list 2 3]
 set current_number 5

 # let's speed things up a little...
 foreach prime $primes {
  while { ( $target_number % $prime ) == 0  } {
   set target_number [expr ($target_number / $prime) ]
  }
 }

 set finished FALSE
 while { !$finished } {

  set is_prime TRUE
  foreach prime $primes {
   if { ($current_number % $prime) == 0  } {
    set is_prime FALSE
    break
   }
  }

  if { $is_prime } {
   set last_prime $current_number
   lappend primes $last_prime

   while { ( $target_number % $last_prime ) == 0  } {
    set target_number [expr ($target_number / $last_prime) ]
   }
  }

  set finished [expr ($target_number == 1)]

  incr current_number 2
 }

 return [lindex $primes end]
}

# solution-3: 6857

Saturday, April 9, 2011

Project Euler - Problem 2 - Tcl

#Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
#1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
#By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
proc problem2 {} {
 set term  2
 set term-1  1
 set sum  0

 while {$term <= 4000000} {
  if {($term % 2) == 0} {
   incr sum $term
  }

  set tmp  ${term-1}
  set term-1  $term
  set term  [expr $term + $tmp]
 }
 
 return $sum
}
# solution-2: 4613732

Project Euler - Problem 1 - Tcl

# If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
# Find the sum of all the multiples of 3 or 5 below 1000.
proc Problem1 {} {

 set items {}

 for {set idx 3} {$idx<1000} {incr idx 3} {
  lappend items $idx
 }

 for {set idx 5} {$idx<1000} {incr idx 5} {
  if { [lsearch $items $idx] < 0 } {
   lappend items $idx
  }
 }

 set rval 0
 foreach item $items {
  set rval [expr $rval + $item]
 }
  
 return $rval
}
# solution: 233168