Sunday, August 8, 2010

Project Euler Problem 4 (Java)

Let's switch back to Java to solve the fourth problem of Project Euler.

Problem 4:

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.

--

This problem is also simple enough to be solved using an intuitive brute force method.  A solution can be found by completing three easy steps.
Step 1: Compute all the products of three-digit numbers.
Step 2: Examine each of these products and remove those that are not palindromes.
Step 3: Find the biggest number of the remaining products.

Note: There are probably much faster ways of solving this problem, but at this point we don't really need to worry about optimization.  This is a quick solution that gets us the correct answer without having to spend too much time planning or programming.

Now that we have broken the program down into three steps, let's look at how these steps can be put into a Java program.

Step 1: We'll use two simple loops to generate these products.  We use two variables, and call them "number1" and "number2".  Each number starts at the largest three-digit number (999) and loops down to the smallest three-digit number (100).  On each time through the outer loop we have an inner loop that decrements number2 until it reaches 100.  We keep number1 at 999 until we have multiplied it by every three-digit number and then we decrement it to 998.  We then reset number2 to equal the current value of number1 and go through the inner loop again.  In this way, we multiply every three-digit number by every other three-digit number.

Step 2: This step actually happens in the midst of the loop used for Step 1 in the code, but it is easiest to think of them as two different steps.  This step simply checks if the current product is a palindrome.  I have abstracted this step into a method called "checkForPalindrome."  It basically starts at the outside numbers (first and last) and checks that they are the same.  It them moves one digit towards the middle of the number and checks that they are again the same.  As soon as it reaches the middle it's done.  If all the checks have been equal, then it is a palindrome.  If any of the checks have not been equal, then it is not a palindrome.

Step 3: This step is actually very easy in our program.  Programmers often want to sort collections of numbers and find the largest one, which is exactly what we want to do.  Fortunately for us, the Java language has a library function to sort a collection.  We simply call this sort function and then get the first item in the collection since it is now the largest number in the collection.  We then print out this number since it is the correct answer.

Again, take a look at the source code even if this doesn't all make sense.  In many ways, it's easier to understand something by reading the code than it is to understand it by reading an English explanation.  Feel free to ask any questions in the comments!

Source code:


/**
 * 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.
 * 
 * Answer: "906609"
 */

package problem_004;

import java.util.ArrayList;
import java.util.Collections;

public class Problem_004_Solver 
{
 
 
 public static void main(String[] args)
 {
  ArrayList<Integer> answers = 
     new ArrayList<Integer>();
  
  int number1 = 999;
  int number2 = 999;
  int product = 0;
  while(number1>100)
  {
   
   
   product = number1*number2;
   if(checkForPalindrome(product))
   {
    answers.add(product);
   }
   
   if(number2==100)
   {
    number1--;
    number2 = number1;
   }
   else
   {
    number2--;
   }
   
  }
  
  Collections.sort(answers);
  for(int i=0; i<answers.size(); i++)
  {
   System.out.println(answers.get(i));
  }
 }
 
 /**
  * Checks if the provided number is a palindrome.
  * A number is a palindrome if it reads the same 
  * forwards and backwards.  Example: 101
  * 
  * @param number - The number to be checked for 
  *                 palindromic characteristics.
  * @return - True if the number is a palindrome, 
  *           false if it is not.
  */
 public static boolean checkForPalindrome(int number)
 {
  String numString = ""+number;
  boolean retVal = true;
  int firstIndex = 0;
  int secondIndex = numString.length()-1;
  while(firstIndex<secondIndex)
  {
   if(numString.charAt(firstIndex)!=
                      numString.charAt(secondIndex))
   {
    retVal = false;
    break;
   }
   firstIndex++;
   secondIndex--;
  }
  
  return retVal;
 }
}

Sunday, September 20, 2009

Project Euler Problem 3 (Python)

Problem 3:

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

---

This problem is a little more difficult than the previous problem, but it still isn't overly complex. The first thing to notice is that this problem can be broken down into two pieces. First, we know that somehow we need to be able to generate prime numbers, or at the very least we must know how to determine if a number is prime or not. Secondly, we need to be able to factor a number and store it's factors.

I chose to create a class to hold the list of prime numbers. There are various ways you can go about listing/generating prime numbers, but I use with a simple sieve method. Basically, you start with a list of a few prime numbers, and then to generate a new one you start counting up from the last prime until you find a number that isn't divisible by any of the primes currently in the list. I'm sure there are faster methods to go about doing this, but I went with a fairly intuitive and easy to implement method. This makes up my "__genNextPrime" function. As a side note, the double underscores in the method name denote it as a private function in Python. The "nextPrime" function returns the next prime number, and handles the calling of the "__genNextPrime" function when needed. There is also a function that resets the index to 0 so that the next prime number returned is reset to the first one.

That takes care of the task of generating prime numbers, so what about factoring this large number? First we store the number provided from the website in a variable. It's important to note here that we are spoiled by using Python. In many languages, a number such as 600851475143 is much too large to store in the typical integer. In order to deal with it you would have to explicitly declare it as a "long". However, Python automatically handles the data types, so it knows which type of number to use in each situation. Anyway, back to the solution. We also have to declare a list to hold each of the prime factors. Now the interesting stuff begins. In English, we want to continue looping until the original number is completely factored. In the loop, we want to get a prime number, and see if it is a factor. If it is, then we add it to our list, set the number equal to the number divided by the factor, and then reset the index of the primes. If it's not a factor, we just get the next prime and repeat the loop for that new prime. How do we determine if the number has been completely factored? Well, if the primer number we are testing as a factor is greater than the square root of the number, then it can't be a factor. Why? Because we already know that all the smaller primes are not factors if we've gotten that far in the loop. Once we break out of the loop, then if there is any remainder, then that gets added to the list of prime factors. Finally, we simply print out our list of prime numbers.

If all this confused you, then maybe a look at the following source code will help. It's easier to put into code than words. (Click on the image to make it bigger so the program is readable)

Friday, September 18, 2009

Project Euler Problem 2 (Python)

Alright, for this problem let's switch things up a bit and go with some Python code. I'm currently working with Python on some projects for college, so I decided to go ahead and solve some of these problems in Python rather than continue on in Java.
Also, I'm going to try and make the posts much shorter and to the point. I'm assuming anyone that reads these has at least a basic programming knowledge. (loops, if-statements, variables, functions, classes, etc.) Anything complex will still be explained, but I'd like to simply describe the problem and the steps to solving it. Typing up long explanations of basic programming constructs is time consuming and also probably not helpful. There are plenty of beginner programming tutorials out there, and if problems arise, then questions can be asked in the comments section.
Ok, enough talk, let's see what the second problem has in store for us.

Problem 2:

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, ...

Find the sum of all the even-valued terms in the sequence which do not exceed four million.


--

To solve this problem we know we need a few things:

* We have to be able to calculate the numbers in the Fibonacci sequence.
* We need to be able to loop through the numbers in the sequence and add each number to a running total.
* We need a way to determine if a number in the sequence is even, and if so add it to the sum.
* We need to check when the number in the sequence is greater than 4,000,000 and then stop looping.

Fortunately, all 4 of these things can be done with basic programming constructs. The numbers in the Fibonacci sequence can be generated very easily by following the description given in the problem. A simple while loop can be used to loop through the numbers, and each time we can add to a variable that holds the sum. Determining if a number is odd or even can be done by taking the modulus of the number and seeing if it is 0. If it is, then we know that the number is even and add it to the sum. We make our condition for the while loop break out of the loop if the number exceeds 4,000,000.
That's all we need to solve this problem. Assemble these components correctly and we should get a program that gives us the correct answer.

Here's what I ended up with:


Thanks for reading!
-Michael

Update: After reading through some discussion of this problem, I've realized that there is definitely a better way to solve this problem that would remove the need for the use of the modulus operator to check if a number is even. By writing out some of the Fibonacci sequence, it becomes apparent that every third number is even. This makes sense, and is fairly easy to prove mathematically. Anyway, that being said, we could simply have looped through and added up every third number rather than using an if-statement to check for an even number. I'm not going to post new code, but I thought I would mention this optimization.

Thursday, April 2, 2009

Project Euler Problem 1 (Java)

Problem 1: “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.”

The first problem in Project Euler is very simple and straight-forward. Even though most likely unnecessary for this problem, I will still list the steps to solving it, as I will do with every problem. This first solution will be done in Java.

Definitions:

Natural Number – Integer greater than zero. (1, 2, 3, 4, 5…)

Multiple – Number that is the product of the given number and any factor. (9 is a multiple of 3)

Sum – The resulting number when multiple numbers are added together. (5 is the sum of 2+3)

Simple Approach:

Ok, so this problem asks us to find the sum of all the multiples of 3 or 5 below 1000. Naturally, we should immediately think of using a loop since it requires that we find all the numbers that match the criteria and are under 1000. So how do we loop through all the numbers under 1000? This is actually very easy.

for(int i=0; i<1000; i++)
{
//whatever is put here will be
//run 1000 times
}
Now, this simple loop counts from 0 to 1000, but it doesn’t really do anything yet. We want to add up a series of numbers, so we’ll have to declare a variable to contain our ever-increasing sum. Let’s call this variable sum, and make it of the integer type.
int sum = 0;
for(int i=0; i<1000; i++)
{
sum
= sum + i;
//sum of every number from 1 to 999
}
Alright, that’s better, but we don’t actually want to sum up all the numbers, we only want to sum the multiples of 3 or 5. To do this we need an if-statement. But how do we check if a number is a multiple of another number? This is done by using the “%” modulus operator. This operator basically performs division on the numbers provided and returns the remainder. So if we did (8%5), the value 3 would be returned. So how does this help us with multiples? Well, if we took a number % 3, if the result is 0 then we know the number is a multiple of 3, and similarly with 5. We now add this check within this loop, so every number from 0 to 999 is checked. If the number is a multiple of 3 or 5, then we add it to the sum. The updated code looks like this:
int sum = 0;

for(int i=0; i<1000; i++)
{
if((i%3 == 0) | (i%5 == 0))
{
//if i is a multiple of 3 or 5
//add it to the current sum
sum += i;
}
}
The final piece of code simply prints out the sum that we found.
System.out.println(sum);
As will always be done, I will post the final code at the end, but I will refrain from putting the actual numerical solution on here. I realize you could just compile this code and run it to find the answer, but at least that’s more work than just copying the solution from here. The point of this blog is to discuss the programming, math, and problem-solving aspects of Project Euler, not just to provide the answers. What good would that do?

Improvements:

Right now many of you are probably thinking, “There are much better ways to do this.”, and of course there are. Once you have gone to the website and entered your solution, you will be provided access to a forum where this problem is being discussed. Many of the comments there are very interesting, and many much better solutions are posted. Also, you will sometimes be given a pdf with a guide to solving the problem. These resources are very useful, and a great deal of number theory is usually discussed. I won’t always discuss these better solutions, because sometimes the math is quite heavy, but I’ll do my best to mention anything I find particularly interesting. With that being said, let’s improve our code.

Ok, first of all let’s look for some simple improvements while keeping our method the same. The most obvious one I see is to make the for loop start at 3 instead of 0. Obviously 0, 1, and 2 are not multiples of 3 or 5. That seems like it’s about the only change we can make to this method. This is a pretty simple problem and a pretty simple solution. Many people, including myself, will be content to use this solution.

However, I feel like I should mention a different approach that I found very interesting. There is actually a math formula for finding the sum of a series if you know the first term, last term, and number of terms. Basically stated, the sum of a series equals the first term plus the last, multiplied by one half of the number of terms in the series.

(sum=(first_term + last_term)*(number_of_terms/2)).

See this Wikipedia page for more details, but be warned that the explanation is a bit cryptic. So how does this math formula help us? Well, instead of having to loop through 1000 numbers, instead we can just make our program evaluate this simple formula. This will save time and computing power. So how do we turn this formula into useful Java code. Well, first let’s analyze our problem. We need to sum up the numbers that are multiples of 3, sum up the numbers that are multiples of 5, and add these two sums together. However, this sum will include all the numbers that are multiples of 15 twice, because these numbers are multiples of 3 and also multiples of 5. To fix this problem, we just need to subtract the sum of the multiples of 15. Here is what that looks like in Java:

int multOf3 = (3+999)*333/2;
int multOf5 = (5+995)*199/2;
int multOf15 = (990+15)*66/2;
//subtract multiples of 15.
int sum = (multOf3+multOf5-multOf15);

Both solutions produce the same answer, but this optimized solution requires much less work on the part of the computer. For a simple problem like this it doesn’t matter much, but if you wanted to perform a similar operation up to a billion instead of a thousand then you might want to use the optimized way.

Well, that’s it for this problem, but there will be more to come soon. This problem was pretty easy, but they get difficult pretty quickly.

Thanks for reading,

Michael


Link to Java Code(Note: some ads will be displayed, but the download is completely free)

Tuesday, March 24, 2009

Introduction

Welcome to Project Euler Walkthrough! This site is dedicated to being a guide to solving the many challenges presented in Project Euler. Before I actually get started working on the problems, I'll provide a brief introduction explaining the purpose of this site, what my goal's are, and a little bit about myself.

I recently discovered the website of Project Euler. This popular website consists of "a series of challenging mathematical/computer programming problems that will require more than just mathematical insights to solve. Although mathematics will help you arrive at elegant and efficient methods, the use of a computer and programming skills will be required to solve most problems." I'm very interested in learning and problem-solving, so I joined this website and am currently working to solve as many of these problems as I can.
So why this blog? A couple reasons... First, it is my opinion that recording my learning as I go helps me process information and remember what I learned. Also, if at any time in the future I am interested, I can simply look back at this blog rather than trusting my memory. So is this blog just for me? Well, yes and no. I certainly won't be disappointed if I am the only one that ever reads this blog, but I wanted to make it available to the public for many reasons. I realize that I am not the only one attempting these problems (there are many, many thousands of attempts), so I'd like to also provide a resource for others facing the same challenges. However, that does not mean that I will simply post the solutions to each of the problems. I want this blog to reflect the learning process that I go through as I attempt to solve the challenges. Other websites freely publish solutions to most of the problems, but I want to actually learn the concepts, not just look up the solutions.

Eventually, I'd like to solve these problems using as many different programming languages as possible. I'm going to begin by using Java, but I'd like to also solve these problems in Python, C/C++, and any other language I am learning. Maybe someday I'll turn this information into a website, or maybe I'll only be able to solve 2 of the problems, who knows. This blog simply gives me a place to write about my journey.

So who am I? My name is Michael Patterson and I am currently a student at Iowa State University studying Computer Engineering. I don't have any type of background in Mathematics, but I have taken a number of courses including Calculus I, II, II and Differential Equations. I've also learned to program in a number of languages. I'm not particularly well suited to tackle Project Euler, but I'm always up for a challenge, so I'll see how it goes.

Thanks for reading,
Michael