I've lurked around for years, but today I have a question concerning my code. I am currently trying to create a collatz program that puts the number of steps for a certain number in an array, but at the same time puts the number of steps for every single number it passes through. Here's my code:
public class GenerousRecursion {
public static short steps;
public static int length;
public static short[] array = new short[101];
public static void main(String[] args) {
length = 100;
for (int count = 2; count < length + 1; count++){
steps = 0;
System.out.println(count + ": " + findCollatz(count));
}
}
public static short findCollatz(int number) {
if (number < length){
if (array[number] > 0) {
steps = array[number]++; return steps;
}
else if(number % 2 == 0) {
array[number] = findCollatz(number / 2);
steps ++;
return steps;
}
else {
array[number] = findCollatz(3 * number + 1);
steps ++;
return steps;
}
}
else {
if(number % 2 == 0) {
findCollatz(number / 2);
steps ++;
return steps;
}
else {
findCollatz(3 * number + 1);
steps ++;
return steps;
}
}
}
}
Here's a great video on the Collatz Conjecture: Numberphile
So here is the error being thrown (reduced), but I don't understand, because I am not anywhere near the bounds of any int or short:
Exception in thread "main" java.lang.StackOverflowError
at GenerousRecursion.findCollatz(GenerousRecursion.java:22)
at GenerousRecursion.findCollatz(GenerousRecursion.java:33)
at GenerousRecursion.findCollatz(GenerousRecursion.java:27)
I just listed these first three lines because these same three lines draw errors for hundreds of lines.
Whats the problem and how do I fix it? Thanks abunch!
Edit: When I ran the debugger, my program continously throws exceptions whenever the array is refrenced.
As stated in the video-clip continuing with 1 will end in an endless loop.
Try the following.
static int[] collatzCounts = new int[100];
static final int NO_COUNT = -1;
static {
Arrays.fill(collatzCounts, NO_COUNT);
collatzCounts{1] = 0; // Define collatz(1) = 0 (1, 4, 2, 1, ...)
}
public static void main(String[] args) {
for (int n = 2; n < 120; n++) {
int steps = countCollatz(n);
System.out.println(n + ": " + steps);
}
}
public static int countCollatz(int n) {
IntFunction f = k ->
k % 2 == 0
? 1 + countCollatz(k / 2)
: 1 + countCollatz(3 * k + 1);
//: 2 + countCollatz((3 * k + 1) / 2);
//if (n == 1) {
// return 0;
//}
if (n < collatzCounts.length) {
if (collatzCounts[n] == NO_COUNT) {
collatzCounts[n] = f.apply(n);
}
return collatzCounts[n];
} else {
return f.apply(n);
}
}
countCollatz simply counts the steps needed - to reach 1 actually. Though till further proof there might be a cycle of higher numbers.
I have used a Java 8 lambda expression, the IntFunction f, as it is more natural to repeat the calculation, once to fill the array, once for too large numberss.
Related
Have some loops homework to do, and need some help! Here are the 3 questions:
Us the method below to take two integers and only output numbers divisible by ten. Make the list start with the largest of the numbers.
public static void divisibleByTen( int start, int end )
The above method is the example on the HW sheet. I have no idea how to implement it. I also don't know how to start with the largest number. Right now, I don't know how to take user input into the loop, so I made an example with 10 and 100:
public class QuestionOne {
public static void main(String [] args) {
for (int i = 10; i <= 100; i += 10){
System.out.println(i + "");
}
}
}
Use the method below to output the triangle below. Assume the positive number is between 3 and 9.
public static void printLeftUpper( int num)
Desired output is this number triangle:
1 2 3 4 5
1 2 3 4
1 2 3
1 2
1
Here's my code so far:
public class QuestionTwo {
public static void main(String [] args) {
for(int i = 5; i >= 1; i--) {
for(int j = 1; j <= i; ++j) {
System.out.print(j + " ");
}
System.out.println();
}
}
}
The third question I have ZERO idea how to start.
3. public static void sumEvens( int begin, int end )
Use the method above to take in two numbers, called begin and end, inclusive, checks if the numbers between them are even. Include the numbers in the sum if they are even as well, and print out the sum of all such numbers.
Example: sumEven(16, 11) uses 16+14+12 = 42, and outputs "For numbers between 16 and 11, the sum of all even numbers is 42."
The help is GREATLY appreciated. Thanks so much!!
Who likes homework? I've taken the liberty of doing Question 3, hope that helps!
import java.util.List;
import java.util.ArrayList;
public class OddEven {
public static void main(String[] args) {
sumEvens(0,1000);
}
// Gets sum of odd and even numbers between a given range:
public static void sumEvens(int begin, int end)
{
List<Integer> evenNumbers = new ArrayList<Integer>();
List<Integer> oddNumbers = new ArrayList<Integer>();
if (begin < end)
{
for (int i = begin; i <= end; i++)
{
// Number is even:
if (i % 2 == 0)
{
evenNumbers.add(i);
}
// Number is odd:
else
{
oddNumbers.add(i);
}
}
}
else
{
for (int i = begin; i >= end; i--)
{
// Number is even:
if (i % 2 == 0)
{
evenNumbers.add(i);
}
// Number is odd:
else
{
oddNumbers.add(i);
}
}
}
// Calculate even values:
int evenSum = 0;
for (int i: evenNumbers) {
evenSum += i;
}
System.out.println("The sum of all even numbers is: " + evenSum);
// Calculate odd values:
int oddSum = 0;
for (int i: oddNumbers) {
oddSum += i;
}
System.out.println("The sum of all odd numbers is: " + oddSum);
}
}
public class QuestionOne {
public static void main(String [] args) {
divisibleByTen( 1, 100 );
}
public static void divisibleByTen( int start, int end ){
// reversal big to small (100 to 1)
for(int i = end; i >= start; i--){
// use mod (%) to check if i is divisible by 10
if( i%10 == 0 ){
// it is then output
System.out.println(i);
}
}
}
}
Question 2 is correct.
Question 3
public static void main(String [] args) {
sumEvens( 16, 10);
}
public static void sumEvens( int begin, int end ){
int start = 0;
int last = end;
int sum = 0;
if(begin > end){
start = end;
end = begin;
}else{
start = begin;
}
for(int i = start; i <= end; i++){
// get even integers
if(i%2 == 0){
sum += i;
}
}
System.out.println("For numbers between " +begin+ " and " +last+ ", the sum of all even numbers is " +sum);
}
I want to write a little program which is able to find the first 10 digit long prime number out of the euler number.
The number on the 99th place is the number I am searching for, but the isPrim() method does not respond correctly. Do you see what went wrong?
My Code
public class Main {
public static final String e = "27182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966";
public static void main(String[] args) {
System.out.println(e);
for (int i = 0; i < e.length() - 10; i++) {
String str = e.substring(i, i + 10);
long num = Long.parseLong(str);
boolean isPrim = isPrim(num);
if (isPrim == true) {
System.out.println("First prime: " + num);
break;
}
System.out.println(i + " " + str + " " + isPrim);
}
}
public static boolean isPrim(long number) {
if (number % 2 == 0) {
return false;
}
for (int j = 3; j * j < number; j+=2) {
if (number % j == 0) {
return false;
}
}
return true;
}
}
Should be j * j <= number, otherwise you will treat squares of primes as primes. I.e. your method says that 9 is prime, because there are no dividers less than sqrt(9).
Also, your code will probably find prime that is shorter than 10 digits, because it checks all 10-digits substrings of E, including those with leading zeros, such as 0452353602.
Also, you need to change type of j to long to avoid overflow.
I wrote this program using return but would like the program to do the exact same thing only using the run-method and a for-loop. It should print the n-th number in the Fibonacci sequence.
import acm.program.*;
public class TESTfibonacci extends ConsoleProgram {
public void run() {
long n = readInt("Enter a number: ");
println(fibo(n));
}
// Prints the n-th Fibonacci number.
long fibo(long n) {
if (n == 0) {
return 0;
} else if (n <= 2) {
return 1;
} else {
return fibo(n - 2) + fibo(n - 1);
}
}
}
you can use dynamic programming for this. The code is taken from here
class Fibonacci {
static int fib(int n) {
/* Declare an array to store Fibonacci numbers. */
int f[] = new int[n + 2]; // 1 extra to handle case, n = 0
int i;
/* 0th and 1st number of the series are 0 and 1*/
f[0] = 0;
f[1] = 1;
for (i = 2; i <= n; i++) {
/* Add the previous 2 numbers in the series
and store it */
f[i] = f[i - 1] + f[i - 2];
}
return f[n];
}
public static void main(String args[]) {
int n = 9;
System.out.println(fib(n));
}
}
I am working on problem twelve on project Euler. It is all about triangle numbers; I am trying to find the first triangle number with more than 500 divisors. I have written a program to find this, however, it is not giving me the correct answer and I can not see why. I have provided my code below:
public class problemTwelve {
public static void main(String [] args) {
int i = 1;
int number = 1;
while(getDivisors(number) < 500) {
number += i;
i++;
}
System.out.println("The first triangle number to have greater than 500 divisors is: " + number);
}
private static int getDivisors(int triangleNum) {
int noOfDivisors = 0;
int numToTest = (int) Math.sqrt(triangleNum);
for(int i = 1; i <= numToTest; i++) {
if((triangleNum % i) == 0) {
noOfDivisors += 2;
}
}
if((numToTest * numToTest) == triangleNum) {
noOfDivisors--;
}
return noOfDivisors;
}
}
The output given by the program upon running it is as follows:
The first triangle number to have greater than 500 divisors is: 146611080
Upon entering this number as the answer on project Euler, we can see that it is wrong. I don't know where I have gone wrong in my program...
It seems that the number you are checking are not triangle. Just at looking at the code, the second number checked is 2 which is not a triangle number.
Try moving the line i++; before the line number+=i;
you have to start your numbers from 0 not 1 , here is the correct code :
int i = 1;
int number = 0;
while(getDivisors(number) < 500) {
number += i;
i++;
}
System.out.println("The first triangle number to have greater than 500 divisors is: " + number);
}
private static int getDivisors(int triangleNum) {
int noOfDivisors = 0;
int numToTest = (int) Math.sqrt(triangleNum);
for(int i = 1; i <= numToTest; i++) {
if(triangleNum % i == 0) {
noOfDivisors += 2;
}
}
if((numToTest * numToTest) == triangleNum) {
noOfDivisors--;
}
return noOfDivisors;
}
For those unfamiliar with the problem, here it is.
I am getting a StackOverflowError with the following code:
public class LongestCollatzSequence {
static int count = 1;
public static void main(String[] args) {
final int range = 1000000;
int maxSeq = 0;
List<Integer> chainList = new ArrayList<Integer>();
for(int i = 1; i <= range; i++) {
generateSequence(i);
if(chainList.isEmpty()) {
chainList.add(count);
count = 1;
} else if(!chainList.contains(count) && count > Collections.max(chainList)) {
chainList.clear();
chainList.add(count);
maxSeq = i;
count = 1;
}
}
System.out.println("Sequence starting number: "+maxSeq);
}
private static void generateSequence(int num) {
if(num == 1) {
return;
}
if(num % 2 == 0) {
count++;
generateSequence(num/2);
} else {
count++;
generateSequence(num*3+1);
}
}
}
High level flow:
-For numbers 2 - 100000, generate a collatz sequence for that number.
-Chain list is a list to store the length of the sequence generated for each number i.e. sequence size for number 13 is 10 (see example).
-If the current sequence size is bigger than the max in the chain list, clear chain list and add the new max, also store the value of i in maxReq to remember the starting number that produces the longest chain.
Interesting problem but the int in java is limited to 2^31-1 you could crox this limit use long or BigInteger
private static void generateSequence(long num) {
if (num == 1) {
return;
}
if (num % 2 == 0) {
count++;
generateSequence(num / 2);
} else {
count++;
generateSequence(num * 3 + 1);
}
}