I'm trying to use a Sieve of Eratosthenes method for finding the largest prime factor of a large number (problem 3 in Project Euler).
My syntax seems to be correct, and i am using Long (not int), but I'm getting the following error message:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at problem3.ProblemThree.Factor(ProblemThree.java:49)
at problem3.ProblemThree.Recursion(ProblemThree.java:37)
at problem3.ProblemThree.main(ProblemThree.java:83)
I don't know why this is happening. Could somebody please tell me what I'm doing wrong here?
package problem3;
import java.util.List;
import java.util.ArrayList;
public class ProblemThree
{
//initializing variables and lists
long factorNo;
long nowTesting;
int i;
List<Long> allPrimeList = new ArrayList<Long>();
List<Long> ourPrimes = new ArrayList<Long>();
ProblemThree(long x) //constructor; the input "x" is the number whose highest prime factor is being sought
{
factorNo = x;
}
void initialize() //use the workaround initialization (add 2 to the allPrimesList, set nowTesting to 3).
//If the factorNo is even, add 2 to the primes list
//TODO: need more elegant solution
{
allPrimeList.add((long) 2);
nowTesting=3;
if(factorNo % 2 == 0) ourPrimes.add((long) 2);
i = 0;
}
void recursion() //keep factoring the next nowTesting until the next nowTesting is greater than half of the factorNo
{
while (nowTesting <= (factorNo/2))
{
nowTesting = factor(nowTesting);
}
System.out.println(ourPrimes);
}
long factor(long t) //The factorization algorithm. Lists all the factors of long t
{
nowTesting = t;
// Line 49:
if ((nowTesting % allPrimeList.get(i)) == 0)
{
i = 0;
return (nowTesting + 2);
}
else
if(i <= allPrimeList.size()) //if we have not yet reached the end of ourPrimeList
{
i++;
return nowTesting;
}
else //if the end of ourPrimeList has been reached without a single modulus==0, this number is a prime
{
allPrimeList.add(nowTesting);
if(factorNo%nowTesting==0) //if the nowTesting is a prime factor of factorNo, it will be perfectly divisible
{
ourPrimes.add(nowTesting);
}
i=0;
return (nowTesting+2);
}
}
public static void main (String[] args)
{
ProblemThree pt = new ProblemThree(600851475143L);
pt.initialize();
pt.recursion();
}
}
thank you everyone for patiently wading through my code, I realize that it must have been excruciatingly painful :)
I have just solved the problem. My previous approach seems very complicated in retrospect. This is the final solution I used, quite a bit more elegant, although it still has room for improvement:
//second attempt from the ground up!
package problem3;
public class BiggestPrime
{
long lInput;
long factorTest;
long currentHeight;
boolean divided;
public BiggestPrime(long n)
{
factorTest = 2;
currentHeight = n;
System.out.println("The prime factors of " + n + " are:");
while (factorTest<currentHeight)
{
if (divided == true) {factorTest = 2; divided = false;}
if (factorTest > currentHeight) {System.out.println("factorTest is greater than currentHeight; breaking"); break;}
if (currentHeight%factorTest==0)
{
System.out.println(factorTest);
currentHeight /= factorTest;
divided = true;
}
else { factorTest = factorTest + 1L; divided = false;}
}
if (factorTest == currentHeight)
{
System.out.println(factorTest);
}
System.out.println("The end");
}
public static void main (String[] args)
{
BiggestPrime bp = new BiggestPrime(600851475143L);
}
}
An interesting approach. Of course, nobody should solve your Euler challenges. But did you know that the second time, you enter 'factor' nowTesting is 3?
// The factorization algorithm. Lists all the factors of long t
long factor (final long nowTesting)
{
System.out.println ("entering factor: " + nowTesting);
Minor ideas:
allPrimeList.add ((long) 2);
can be written:
allPrimeList.add (2L);
and you pobably recognized the "final" in front of the 'long' parameter in factor? It helps reasoning about code, if you mark everything which isn't changed final. In practise, the consequence is, that your Javacode is cluttered with 'final' modifiers, but that's how it is. It's a sign of good code - maybe not of good design. Final could have been the default.
At line 49, shouldn't you be checking if nowTesting is divisible by i, not the ith element of allPrimes?
Related
I'm trying to implement the algorithm to solve Project Euler Problem #14, which asks to find a number in a given range that outputs the largest Collatz conjecture sequence length. My code is below:
import java.util.ArrayList;
class Collatz {
private static ArrayList<ArrayList<Long>> previousNums = new ArrayList();
public static int seqLen(int x) {
ArrayList<Long> colSeq = new ArrayList();
long val = x;
colSeq.add(val);
while (val > 1) {
if (val%2 == 0) {
val/=2;
if (val < previousNums.size()) /*used to check if index exists*/{
colSeq.addAll(previousNums.get((int)val));
break;
}
else colSeq.add(val);
}
else {
val = 3*val + 1;
if (val < previousNums.size()) {
colSeq.addAll(previousNums.get((int)val));
break;
}
else colSeq.add(val);
}
}
previousNums.add(colSeq);
return colSeq.size();
}
public static void main(String[] args) {
int greatestNum = 0;
long totalVal = 0;
for (int i = 0; i<=1000000; i++) {
int collatz = seqLen(i);
if (collatz > totalVal) {}
greatestNum = i;
totalVal = collatz;
}
System.out.println(greatestNum + " " + totalVal);
}
}
The output I get is
1000000 153
While this is not the correct answer, 153 is the correct sequence length for 1 million. Based off of this, I could assume that my Collatz conjecture algorithm works, but not the comparison part. However, I can't really find anywhere else I could modify the code. Any ideas? Thank you and please pardon the possibility of this being a duplicate (not many other posts had the same problem).
Wow, a mere syntax error was the issue. Looks like I didn't pay attention to:
if (collatz > totalVal) {}
greatestNum = i;
totalVal = collatz;
Yup, didn't enclose the code with the braces.
My code results with endless number "2", I don't understand why.
Also my tutor told me to add validation for negative values - I don't know how to do it.
public class FibonacciRecursive {
public static void main(String[] args) {
int fibonacciNumberOrder = 10;
do {
System.out.print(fibonacci(fibonacciNumberOrder) + " ");
} while (true);
}
public static long fibonacci(int fibonacciNumberInOrder) {
if (fibonacciNumberInOrder == 0) {
return 0;
}
if (fibonacciNumberInOrder <= 2) {
return 1;
}
long fibonacci = fibonacci(-1) + fibonacci(-2);
return fibonacci;
}
}
edit:
When I changed that line
long fibonacci = fibonacci(-1) + fibonacci(-2);
to:
long fibonacci = fibonacci(fibonacciNumberInOrder-1) + fibonacci(fibonacciNumberInOrder-2);
It prints endless "55"
How should I change my code to make it work?
It happens because you calculate the Fibonacci number with constants instead of relative numbers to passed ones through, which is the point of recursion.
public static long fibonacci(int fibonacciNumberInOrder) {
if (fibonacciNumberInOrder == 0) {
return 0;
}
if (fibonacciNumberInOrder <= 2) {
return 1;
}
long fibonacci = fibonacci(fibonacciNumberInOrder - 1) + fibonacci(fibonacciNumberInOrder - 2);
return fibonacci;
}
The key changed line is:
long fibonacci = fibonacci(fibonacciNumberInOrder-1) + fibonacci(fibonacciNumberInOrder-2);
You are recursing with constants! Change this
long fibonacci = fibonacci(-1) + fibonacci(-2);
to
long fibonacci = fibonacci(fibonacciNumberInOrder-1) + fibonacci(fibonacciNumberInOrder-2);
And, in your while loop in main - you need to modify fibonacciNumberInOrder
int fibonacciNumberOrder = 1;
do {
System.out.print(fibonacci(fibonacciNumberOrder) + " ");
fibonacciNumberOrder++;
} while (true);
Question:
In this problem, the scenario we are evaluating is the following: You're standing at the base of a staircase and are heading to the top. A small stride will move up one stair, and a large stride advances two. You want to count the number of ways to climb the entire staircase based on different combinations of large and small strides. For example, a staircase of three steps can be climbed in three different ways: three small strides, one small stride followed by one large stride, or one large followed by one small.
The call of waysToClimb(3) should produce the following output:
1 1 1,
1 2,
2 1
My code:
public static void waysToClimb(int n){
if(n == 0)
System.out.print("");
else if(n == 1)
System.out.print("1");
else {
System.out.print("1 ");
waysToClimb(n - 1);
System.out.print(",");
System.out.print("2 ");
waysToClimb(n - 2);
}
}
My output:
1 1 1,
2,
2 1
My recursion doesn't seem to remember the path it took any idea how to fix it?
Edit:
Thank you guys for the responses. Sorry for the late reply
I figured it out
public static void waysToClimb(int n){
String s ="[";
int p=0;
com(s,p,n);
}
public static void com(String s,int p,int n){
if(n==0 && p==2)
System.out.print(s.substring(0,s.length()-2)+"]");
else if(n==0 && p !=0)
System.out.print(s+"");
else if(n==0 && p==0)
System.out.print("");
else if(n==1)
System.out.print(s+"1]");
else {
com(s+"1, ",1,n-1);
System.out.println();
com(s+"2, ",2,n-2);
}
}
If you explicity want to print all paths (different than counting them or finding a specific one), you need to store them all the way down to 0.
public static void waysToClimb(int n, List<Integer> path)
{
if (n == 0)
{
// print whole path
for (Integer i: path)
{
System.out.print(i + " ");
}
System.out.println();
}
else if (n == 1)
{
List<Integer> newPath = new ArrayList<Integer>(path);
newPath.add(1);
waysToClimb(n-1, newPath);
}
else if (n > 1)
{
List<Integer> newPath1 = new ArrayList<Integer>(path);
newPath1.add(1);
waysToClimb(n-1, newPath1);
List<Integer> newPath2 = new ArrayList<Integer>(path);
newPath2.add(2);
waysToClimb(n-2, newPath2);
}
}
initial call: waysToClimb(5, new ArrayList<Integer>());
Below mentioned solution will work similar to Depth First Search, it will explore one path. Once a path is completed, it will backtrace and explore other paths:
public class Demo {
private static LinkedList<Integer> ll = new LinkedList<Integer>(){{ add(1);add(2);}};
public static void main(String args[]) {
waysToClimb(4, "");
}
public static void waysToClimb(int n, String res) {
if (ll.peek() > n)
System.out.println(res);
else {
for (Integer elem : ll) {
if(n-elem >= 0)
waysToClimb(n - elem, res + String.valueOf(elem) + " ");
}
}
}
}
public class Test2 {
public int climbStairs(int n) {
// List of lists to store all the combinations
List<List<Integer>> ans = new ArrayList<List<Integer>>();
// initially, sending in an empty list that will store the first combination
csHelper(n, new ArrayList<Integer>(), ans);
// a helper method to print list of lists
print2dList(ans);
return ans.size();
}
private void csHelper(int n, List<Integer> l, List<List<Integer>> ans) {
// if there are no more stairs to climb, add the current combination to ans list
if(n == 0) {
ans.add(new ArrayList<Integer>(l));
}
// a necessary check that prevent user at (n-1)th stair to climb using 2 stairs
if(n < 0) {
return;
}
int currStep = 0;
// i varies from 1 to 2 as we have 2 choices i.e. to either climb using 1 or 2 steps
for(int i = 1; i <= 2; i++) {
// climbing using step 1 when i = 1 and using 2 when i = 2
currStep += 1;
// adding current step to the arraylist(check parameter of this method)
l.add(currStep);
// make a recursive call with less number of stairs left to climb
csHelper(n - currStep, l, ans);
l.remove(l.size() - 1);
}
}
private void print2dList(List<List<Integer>> ans) {
for (int i = 0; i < ans.size(); i++) {
for (int j = 0; j < ans.get(i).size(); j++) {
System.out.print(ans.get(i).get(j) + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
Test2 t = new Test2();
t.climbStairs(3);
}
}
Please note this solution will timeout for larger inputs as this isn't a memoized recursive solution and can throw MLE(as I create a new list when a combination is found).
Hope this helps.
if anyone looking for a python solution, for this problem.
def way_to_climb(n, path=None, val=None):
path = [] if path is None else path
val = [] if val is None else val
if n==0:
val.append(path)
elif n==1:
new_path = path.copy()
new_path.append(1)
way_to_climb(n-1, new_path, val)
elif n>1:
new_path1 = path.copy()
new_path1.append(1)
way_to_climb(n-1, new_path1, val)
new_path2 = path.copy()
new_path2.append(2)
way_to_climb(n-2, new_path2, val)
return val
Note: it is based on the #unlut solution, here OP has used a top-down recursive approach. This solution is for all people who looking for all combination of staircase problem in python, no python question for this so i have added a python solution here
if we use a bottom-up approach and use memorization, then we can solve the problem faster.
Even though you did find the correct answer to the problem with your code, you can still improve upon it by using just one if to check if the steps left is 0. I used a switch to check the amount of steps taken because there are only 3 options, 0, 1, or 2. I also renamed the variables that were used to make the code more understandable to anyone seeing it for the first time, as it is quite confusing if you are just using one letter variable names. Even with all these changes the codes run the same, I just thought it might be better to add some of these things for others who might view this question in the future.
public static void climbStairsHelper(String pathStr, int stepsTaken, int stepsLeft)
{
if(stepsLeft == 0)
{
switch(stepsTaken)
{
case 2:
System.out.print(pathStr.substring(0, pathStr.length() - 2) + "]");
break;
case 1:
System.out.print(pathStr + "");
break;
case 0:
System.out.print("");
break;
}
}
else if(stepsLeft == 1)
{
System.out.print(pathStr + "1]");
}
else
{
climbStairsHelper(pathStr + "1, ", 1, stepsLeft - 1);
System.out.println();
climbStairsHelper(pathStr + "2, ", 2, stepsLeft - 2);
}
}`
`
I am working on a problem from Cracking the Coding Interview, problem 9.6 page 110.
Here is the problem:
Implement an algorithm to print all valid (e.g., properly opened and closed combinations of n-pairs of parentheses. Examples
b(1) - "()"
b(2) - "(()), ()()"
b(3) - "((())), (()()), (())(), ()(()), ()()()"
I am trying to use the bottom up recursion approach that the author discusses on page 107 - "We start with knowing how to solve the problem for a simple case, like a list with only one element, and figure out how to solve the problem for two elements, then for three elements, and so on. The key here is to think about how you can build the solution for one case off the previous case"
Here is the code I have so far
static void print(int n) {
print(n, new HashSet<String>(), "", "");
}
static void print(int n, Set<String> combs, String start, String end) {
if(n == 0) {
if(!combs.contains(start + end)) {
System.out.print(start + end);
combs.add(start + end);
}
} else {
print(n-1, combs, "(" + start, end +")");
System.out.print(", ");
print(n-1, combs, start, end + "()");
System.out.print(", ");
print(n-1, combs, "()" + start, end);
}
}
To get this code, I worked from the first case to the second case. I saw that b(2) = "(b(1)), b(1),b(1)"
This code does work for the first two cases. I am really struggling with the third case though. Can someone give me a hint(not the whole answer, could turn to the back of the book for that), about how to go from case 2 to case 3, or in other words using case 2 to get to case 3? Like how would you go from (()), ()() to ((())), (()()), (())(), ()(()), ()()()? Would you abandon the pattern you saw from b(1) to b(2) because it doesn't work for b(2) to b(3)?
We can generate from b(n) to b(n + 1) by using this recursive formula:
(b(n - x))b(x) with 0 <= x <= n
So, you can have all of your combinations by iterating through all x.
Code:
public static ArrayList<String> cal(int num){
if(num == 0){
ArrayList<String> list = new ArrayList();
list.add("");
return list;
}else{
ArrayList<String>result = new ArrayList();
for(int i = 0; i <= num - 1; i++){
ArrayList<String> a = cal(i);
ArrayList<String> b = cal(num - 1 - i);
for(String x : a){
for(String y : b){
result.add("(" + x + ")" + y);
}
}
}
return result;
}
}
Input: 3
Output: ()()(), ()(()), (())(), (()()), ((()))
Input: 4
Output: ()()()(), ()()(()), ()(())(), ()(()()), ()((())), (())()(), (())(()), (()())(), ((()))(), (()()()), (()(())), ((())()), ((()())), (((())))
Thanks Khanna111 for pointing out the mistake I made in my original answer, which was incomplete and under-counted the string patterns. As a result, I have updated my answer accordingly.
Please consider giving credit to Pham Trung for his answer with the correct recursive formula. My answer is essentially the same as his, with only a slight difference in the way I formulate the construction of patterns from smaller sub-problems (as I find it easier to explain the details in my approach).
========================================================================
Update Solution
For any valid pattern s of size n, s falls in exactly one of the following cases:
Case 1: s cannot be partitioned into two valid patterns of smaller size
Case 2: s can be partitioned into two valid patterns of smaller size
For case 1, s must be of the form (_____), where _____ is a valid pattern of size n - 1. So in this case, for every valid pattern t of size n - 1, we simply construct a pattern s by concatenating t with ( and ) as prefix and suffix, respectively (i.e. s = (t)).
For case 2, we can partition s into uv, where u and v are both valid patterns of smaller size. In this case, we have to consider all possible patterns of u and v, where u can be any valid pattern of size i = 1, 2, ..., n - 1, while v can be any valid pattern of size n - i.
When n = 0, clearly only the empty string is a valid pattern, so we have dp(0) = { "" } as our base case. A complete implementation with caching to improve the performance is given below:
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class BalancingBrackets {
private static Map<Integer, Set<String>> dp = new HashMap<>();
public static void main(String[] args) {
Set<String> result = compute(4);
boolean isFirst = true;
for (String s : result) {
if (isFirst) {
isFirst = false;
System.out.print(s);
} else {
System.out.print(", " + s);
}
}
}
private static Set<String> compute(Integer n) {
// Return the cached result if available
if (dp.containsKey(n)) {
return dp.get(n);
}
Set<String> set = new HashSet<>();
if (n == 0) {
// This is the base case with n = 0, which consists only of the
// empty string
set.add("");
} else if (n > 0) {
// For generating patterns in case 1
for (String s : compute(n - 1)) {
set.add("(" + s + ")");
}
// For generating patterns in case 2
for (int i = 1; i < n; i++) {
Set<String> leftPatterns = compute(i);
Set<String> rightPatterns = compute(n - i);
for (String l : leftPatterns) {
for (String r : rightPatterns) {
set.add(l + r);
}
}
}
} else {
// Input cannot be negative
throw new IllegalArgumentException("Input cannot be negative.");
}
// Cache the solution to save time for computing large size problems
dp.put(n, set);
return set;
}
}
I just discovered the project euler website, I have done challenges 1 and 2 and have just started number 3 in java... here is my code so far:
import java.util.ArrayList;
public class IntegerFactorise {
private static int value = 13195;
private static ArrayList<Integer> primeFactors = new ArrayList<Integer>();
private static int maxPrime = 0;
/**
* Check whether a give number is prime or not
* return boolean
*/
public static boolean isPrimeNumber(double num) {
for(int i = 2; i < num; i++) {
if(num % i == 0) {
return false;
}
}
return true;
}
/*Multiply all of the prime factors in the list of prime factors*/
public static int multiplyPrimeFactors() {
int ans = 1;
for(Integer i : primeFactors) {
ans *= i;
}
return ans;
}
/*Find the maximum prime number in the list of prime numbers*/
public static void findMaxPrime() {
int max = 0;
for(Integer i : primeFactors) {
if(i > max) {
max = i;
}
}
maxPrime = max;;
}
/**
* Find all of the prime factors for a number given the first
* prime factor
*/
public static boolean findPrimeFactors(int num) {
for(int i = 2; i <= num; i++) {
if(isPrimeNumber(i) && num % i == 0 && i == num) {
//could not possibly go further
primeFactors.add(num);
break;
}
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
findPrimeFactors(num / i);
}
}
int sumOfPrimes = multiplyPrimeFactors();
if(sumOfPrimes == value) {
return true;
}
else {
return false;
}
}
/*start here*/
public static void main(String[] args) {
boolean found = false;
for(int i = 2; i < value; i++) {
if(isPrimeNumber(i) && value % i == 0) {
primeFactors.add(i);
found = findPrimeFactors(value / i);
if(found == true) {
findMaxPrime();
System.out.println(maxPrime);
break;
}
}
}
}
}
I am not using the large number they ask me to use yet, I am testing my code with some smaller numbers, with 13195 (their example) i get down to 29 in this bit of my code:
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
findPrimeFactors(num / i);
}
}
int sumOfPrimes = multiplyPrimeFactors();
if(sumOfPrimes == value) {
return true;
}
It gets to the break statement then finally the check and then the return statement.
I am expecting the program to go back to the main method after my return statement, but it jumps up to:
findPrimeFactors(num / i);
and tries to finish the iteration...I guess my understanding is a flawed here, could someone explain to me why it is behaving like this? I can't wait to finish it of :) I'll find a more efficient way of doing it after I know I can get this inefficient one working.
You are using recursion, which means that a function will call itself.
So, if we trace what your function calls are when you call return, we will have something like that:
IntegerFactorise.main()
|-> IntegerFactorise.findPrimeFactors(2639)
|-> IntegerFactorise.findPrimeFactors(377)
|-> IntegerFactorise.findPrimeFactors(29) -> return true;
So, when you return in the last findPrimeFactors(), you will only return from this call, not from all the stack of calls, and the execution of the previous findPrimeFactors() will continue just after the point where you called findPrimeFactors().
If you want to return from all the stack of calls, you have to modify your code to do something like that:
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
return findPrimeFactors(num / i);
}
So that when the last findPrimeFactors() returns, all the previous findPrimeFactors() which called it will return too.
I think the problem is that you are ignoring the return value from your recursive call to findPrimeFactors().
Let's walk through this. We start with the initial call to findPrimeFactors that happens in main. We then enter the for loop as it's the first thing in that method. Now let's say at some point we get into the else statement and thus recursively call frindPrimeFactors(num / i). This will suspend the looping, but as this recursive call starts to run you enter the for loop again (remember, the previous loop is merely paused and not finished looping yet). This time around you encounter the break, which allows this recursive call to finish out, returning true of false. When that happens you are now back to the original loop. At this point the original loop continues even if the recursive call returned true. So, you might try something like this:
if (findPrimeFactors(num / i))
return true;
I'm assuming that you need to continue looping if the recursive call returned false. If you should always finish looping upon return (whether true or false) then try this:
return findPrimeFactors(num / i);