Comparing and finding an ArrayList with the longest length - java

I am solving a task linked to the Collatz Problem. I have created a method that produces 1 from any starting number:
public static void sequence(int value)
{
ArrayList<Integer> calc = new ArrayList<Integer>();
calc.add(value);
while(value != 1)
{
if(value % 2 == 0)
{
value = value / 2;
}
else if(value % 2 != 0)
{
value = (value * 3) + 1;
}
calc.add(value);
if(value == 1 )
{
System.out.println(calc);
}
}
}
public static void main(String[] args) {
for(int x = 1000000; x > 0; x--)
{
sequence(x);
}
}
}
The next part of my task is finding a method which will find the longest Collatz sequence below 1,000,000.
I came up with several solutions such as the one below..of course none of them worked.
while(value != 1)
{
if(value % 2 == 0)
{
value = value / 2;
}
else if(value % 2 != 0)
{
value = (value * 3) + 1;
}
calc1.add(value);
if(calc1.size() > calc2.size())
{
calc2 = calc1;
}
}
System.out.println(calc2);
}
Could anyone please help and guide me to finding the correct methods for finding the longest Collatz sequence using the comparison of 2 or more ArrayLists. If there are better options than the use of an ArrayList I more than welcome these methods.
Thanks.

You need to maintain a maxList which will get updated with the longest sequence.
You can either pass it to your calc() method in each call or declare it as a Class variable for using it on top of both calc() and main() methods.
// to update the max list
maxList = (list.size() > maxList.size()) ? list : maxList;
At the end just print the results
System.out.println(maxList.size());
System.out.println(maxList);
Update: You need to figure out efficient ways to pass numbers in the calc() method.
It will throw java.lang.OutOfMemoryError for large input.

Related

Trying to find the smallest positive number that is evenly divisible by all of the numbers from 1 to 20

I'm trying to find the smallest positive number that is evenly divisible by all of the numbers from 1 to 20. We are given that 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. My find() finds the number starting from 2520 that is divisible by all numbers from 1-20 but is returning 2520 for some reason. I cannot find what's wrong about my find()?
public class Solution {
public ArrayList<Integer> list = new ArrayList<Integer>();
// creating a list of integers from 1 to 20
public ArrayList<Integer> addtolist() {
for (int i = 1; i <= 20; i++) {
list.add(i);
}
return list;
}
// finds the smallest positive number that is evenly divisible by all
of the numbers from 1 to 20
public int find() {
int num = 2520;
while(true) {
for(int i: list) {
if(num % i == 0) {
return num;
}
else {
num = num + 1;
}
}
}
}
public static void main(String[] args) {
Solution sol = new Solution();
sol.addtolist();
System.out.println(sol.find());//2520
}
}
Your find function returns num if any i in list divides it. It should only return num if every i in num is a divisor.
Although it has to be said that this is far from the most efficient solution to the problem.
You return from the for loop when (num % i == 0), given that i starts at 1 this always true. Instead you need to wait until the end to return:
public int find() {
int num = 2520;
while(true) {
boolean allDivisible = true;
for(int i: list) {
if(num % i != 0) {
allDivisible = false;
break;
}
}
if (allDivisible) {
return num;
else {
num = num + 1;
}
}
}
In your code:
for(int i: list) {
if(num % i == 0) {
return num; // Returns immediately.
}
else {
num = num + 1;
}
}
you return as soon as you find some number in the list that has a match. What you want to do is only return when you have found a value that matches all in the list.
Nice question!
long answer = LongStream.iterate(1, n -> n + 1)
.filter(n -> IntStream.rangeClosed(1, 20).allMatch(f -> n % f == 0))
.findFirst().getAsLong();
Answer is 232792560
There are obviously plenty of shortcuts using math (e.g. only looking at even numbers, ignoring numbers in 1 to 20 that are factors of other numbers in that range).

Fibonacci Modified:How to fix this algorithm?

I have this problem in front of me and I can't figure out how to solve it.
It's about the series 0,1,1,2,5,29,866... (Every number besides the first two is the sum of the squares of the previous two numbers (2^2+5^2=29)).
In the first part I had to write an algorithm (Not a native speaker so I don't really know the terminology) that would receive a place in the series and return it's value (6 returned 29)
This is how I wrote it:
public static int mod(int n)
{
if (n==1)
return 0;
if (n==2)
return 1;
else
return (int)(Math.pow(mod(n-1), 2))+(int)(Math.pow(mod(n-2), 2));
}
However, now I need that the algorithm will receive a number and return the total sum up to it in the series (6- 29+5+2+1+1+0=38)
I have no idea how to do this, I am trying but I am really unable to understand recursion so far, even if I wrote something right, how can I check it to be sure? And how generally to reach the right algorithm?
Using any extra parameters is forbidden.
Thanks in advance!
We want:
mod(1) = 0
mod(2) = 0+1
mod(3) = 0+1+1
mod(4) = 0+1+1+2
mod(5) = 0+1+1+2+5
mod(6) = 0+1+1+2+5+29
and we know that each term is defined as something like:
2^2+5^2=29
So to work out mod(7) we need to add the next term in the sequence x to mod(6).
Now we can work out the term using mod:
x = term(5)^2 + term(6)^2
term(5) = mod(5) - mod(4)
term(6) = mod(6) - mod(5)
x = (mod(5)-mod(4))^2 + (mod(6)-mod(5))^2
So we can work out mod(7) by evaluating mod(4),mod(5),mod(6) and combining the results.
Of course, this is going to be incredibly inefficient unless you memoize the function!
Example Python code:
def f(n):
if n<=0:
return 0
if n==1:
return 1
a=f(n-1)
b=f(n-2)
c=f(n-3)
return a+(a-b)**2+(b-c)**2
for n in range(10):
print f(n)
prints:
0
1
2
4
9
38
904
751701
563697636866
317754178345850590849300
How about this? :)
class Main {
public static void main(String[] args) {
final int N = 6; // Your number here.
System.out.println(result(N));
}
private static long result(final int n) {
if (n == 0) {
return 0;
} else {
return element(n) + result(n - 1);
}
}
private static long element(final int n) {
if (n == 1) {
return 0L;
} else if (n == 2) {
return 1L;
} else {
return sqr(element(n - 2)) + sqr(element(n - 1));
}
}
private static long sqr(final long x) {
return x * x;
}
}
Here is the idea that separate function (element) is responsible for finding n-th element in the sequence, and result is responsible for summing them up. Most probably there is a more efficient solution though. However, there is only one parameter.
I can think of a way of doing this with the constraints in your comments but it's a total hack. You need one method to do two things: find the current value and add previous values. One option is to use negative numbers to flag one of those function:
int f(int n) {
if (n > 0)
return f(-n) + f(n-1);
else if (n > -2)
return 0;
else if (n == -2)
return 1;
else
return f(n+1)*f(n+1)+f(n+2)*f(n+2);
}
The first 8 numbers output (before overflow) are:
0
1
2
4
9
38
904
751701
I don't recommend this solution but it does meet your constraints of being a single recursive method with a single argument.
Here is my proposal.
We know that:
f(n) = 0; n < 2
f(n) = 1; 2 >= n <= 3
f(n) = f(n-1)^2 + f(n-2)^2; n>3
So:
f(0)= 0
f(1)= 0
f(2)= f(1) + f(0) = 1
f(3)= f(2) + f(1) = 1
f(4)= f(3) + f(2) = 2
f(5)= f(4) + f(3) = 5
and so on
According with this behaivor we must implement a recursive function to return:
Total = sum f(n); n= 0:k; where k>0
I read you can use a static method but not use more than one parameter into the function. So, i used a static variable with the static method, just for control the execution of loop:
class Dummy
{
public static void main (String[] args) throws InterruptedException {
int n=10;
for(int i=1; i<=n; i++)
{
System.out.println("--------------------------");
System.out.println("Total for n:" + i +" = " + Dummy.f(i));
}
}
private static int counter = 0;
public static long f(int n)
{
counter++;
if(counter == 1)
{
long total = 0;
while(n>=0)
{
total += f(n);
n--;
}
counter--;
return total;
}
long result = 0;
long n1=0,n2=0;
if(n >= 2 && n <=3)
result++; //Increase 1
else if(n>3)
{
n1 = f(n-1);
n2 = f(n-2);
result = n1*n1 + n2*n2;
}
counter--;
return result;
}
}
the output:
--------------------------
Total for n:1 = 0
--------------------------
Total for n:2 = 1
--------------------------
Total for n:3 = 2
--------------------------
Total for n:4 = 4
--------------------------
Total for n:5 = 9
--------------------------
Total for n:6 = 38
--------------------------
Total for n:7 = 904
--------------------------
Total for n:8 = 751701
--------------------------
Total for n:9 = 563697636866
--------------------------
Total for n:10 = 9011676203564263700
I hope it helps you.
UPDATE: Here is another version without a static method and has the same output:
class Dummy
{
public static void main (String[] args) throws InterruptedException {
Dummy app = new Dummy();
int n=10;
for(int i=1; i<=n; i++)
{
System.out.println("--------------------------");
System.out.println("Total for n:" + i +" = " + app.mod(i));
}
}
private static int counter = 0;
public long mod(int n)
{
Dummy.counter++;
if(counter == 1)
{
long total = 0;
while(n>=0)
{
total += mod(n);
n--;
}
Dummy.counter--;
return total;
}
long result = 0;
long n1=0,n2=0;
if(n >= 2 && n <=3)
result++; //Increase 1
else if(n>3)
{
n1 = mod(n-1);
n2 = mod(n-2);
result = n1*n1 + n2*n2;
}
Dummy.counter--;
return result;
}
}
Non-recursive|Memoized
You should not use recursion since it will not be good in performance.
Use memoization instead.
def FibonacciModified(n):
fib = [0]*n
fib[0],fib[1]=0,1
for idx in range(2,n):
fib[idx] = fib[idx-1]**2 + fib[idx-2]**2
return fib
if __name__ == '__main__':
fib = FibonacciModified(8)
for x in fib:
print x
Output:
0
1
1
2
5
29
866
750797
The above will calculate every number in the series once[not more than that].
While in recursion an element in the series will be calculated multiple times irrespective of the fact that the number was calculated before.
http://www.geeksforgeeks.org/program-for-nth-fibonacci-number/

Median method returning higher value median

So im writing a method in which it finds the median of an n-numbered array. If the array has an odd number of elements it works fine, however if the array has an even number of elements, I want the program to output the higher of the 2 middle numbers rather than the lower of the 2. At the current moment, my code is outputting the lower number. This is the code:
public Long getMedian() {
long median = 0;
Arrays.sort(elements);
if (length % 2 != 0) {
median = elements[length/2];
} if (length % 2 == 0) {
median = ((elements[length/2]) + (elements[(length/2) - 1])) / 2;
median++;
}
return median;
}
For example, if the array with numbers [30 41 45 50] was inputted, the median would be 45, not 41. Please help!
Surprisingly it is most straightforward solution:
public Long getMedian() {
Arrays.sort(elements);
return elements[elements.length / 2];
}
in your code, I suspect that the variable length is not elements.length.
Anyway, I use this median function:
public static double median(int[] values) {
Arrays.sort(values);
if (values.length == 0)
return 0;
else if (values.length % 2 == 0)
return ((double)values[values.length/2] + (double)values[values.length/2 - 1])/2;
else
return (double)values[values.length/2];
}
public double findmedian(int[] arr) {
int middlevalue = arr.length/2;
if (arr.length%2 == 1) {
return arr[middle];
} else {
return (arr[middle-1] + arr[middle]) / 2.0;
}
}
i think its best to return a double value when finding meadian. may be this approach will help you.
You can achieve the right border of your median like this:
median = elements[(length/2)]
for the even-case

Java - Displaying Palindromic Primes

For my Java class, we have to write a program that displays all palindromic primes based on a number the user inputs. There are a couple other questions like this, but I need to do it without creating an array, or just typing in all of the palindromic primes.
My program works, and displays all primes, but the problem is that it displays ALL primes, not just the palindromic ones. I don't know where the error is, but I would appreciate any help I can get!
Thanks,
Ben
import java.util.Scanner;
public class PalindromePrimes {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int startingPoint = 1;
int startingPrime = 2;
final int printPerLine = 10;
IsItPrime(startingPrime);
IsItPalin(startingPrime);
System.out.println("Please Enter a Number: ");
int n = in.nextInt();
while (startingPoint <= n)
{
if (IsItPrime(startingPrime) && IsItPalin(startingPrime)) {
System.out.print(startingPrime + " ");
if (startingPoint % printPerLine == 0)
System.out.println();
startingPoint++;
}
startingPrime++;
}
}
public static boolean IsItPrime(int sPrime) {
if (sPrime == 2) {
return true;
}
for(int i = 2; 2 * i < sPrime; i++) {
if(sPrime % i == 0){
return false;
}
}
return true;
}
public static boolean IsItPalin(int sPrime) {
int p;
int reverse = 0;
while (sPrime > 0) {
p = sPrime % 10;
reverse = reverse * 10 + p;
sPrime = sPrime / 10;
}
if (sPrime == reverse) {
return false;
}
return true;
}
}
You could really improve both functions:
Some notes about IsItPrime:
Check first only for even numbers (you are doing this)
The for-loop could begin in 3 and increment by 2, to check only odd numbers, the even are checked in the previous point.
The for-loop only needs to check from 3 .. sqrt(N) + 1, if the number is not prime. It would be a prime if the number is less or equal to sqrt(N) and devides N.
Function IsItPrime improve:
public static boolean IsItPrime(int sPrime) {
if (sPrime % 2 == 0 && sPrime != 2) {
return false;
}
int sqrtPrime = (int)Math.sqrt(sPrime);
for (int i = 3; i <= sqrtPrime; i += 2) {
if (sPrime % i == 0) {
return false;
}
}
return true;
}
Some notes about IsItPalin:
The return result is swapped, when sPrime == reverse is palindrome, you must return true, not false.
The other problem is that in the function you are modifying the parameter sPrime in the while-loop, you need to save the original value for comparing in sPrime == reverse.
Function IsItPalin improved:
public static boolean IsItPalin(int sPrime) {
int sPrimeBackup = sPrime;
int reverse = 0;
while (sPrime > 0) {
reverse = reverse * 10 + sPrime % 10;
sPrime = sPrime / 10;
}
return (sPrimeBackup == reverse);
}
The problem is in the IsItPalin method. You are changing the value of sPrime, but then comparing sPrime to reverse. Make a copy of sPrime and compare the copy to reverse. Also, you should return true if they are equal, not false.
It looks like the problem is with your IsItPalin method. It's almost right, except for two problems.
The first problem is this:
if (sPrime == reverse) {
return false;
}
return true;
Whenever your prime number is equal to the reverse, you're returning false! This is the opposite of what we want.
The fix is to switch "true" and "false":
if (sPrime == reverse) {
return true;
}
return false;
We can actually simplify this into a single line:
return sPrime == reverse;
The second problem is with sPrime. Within your while loop, you're decreasing sPrime, and will only exit the loop when sPrime is equal to zero. That means that the only time sPrime will be equal to reverse is when you input the value of 0. To fix this, make a copy of sPrime at the top of the method and compare the copy to reverse.
The fixed version would look like this:
public static boolean IsItPalin(int sPrime) {
int copy = sPrime;
int reverse = 0;
while (sPrime > 0) {
int p = sPrime % 10;
reverse = reverse * 10 + p;
sPrime = sPrime / 10;
}
return copy == reverse;
}
This solution doesn't involve a loop, so it's probably faster
public static boolean isPaladrome(int mNumber) {
String numToString = String.valueOf(mNumber);
int sLength = numToString.length();
int midPoint = sLength / 2;
return (new StringBuilder(numToString.substring(0, midPoint)).reverse()
.toString()).equals(numToString.substring(sLength - midPoint));
}

Using Recursion to reverse an integer without the use of strings

I have been trying this for some time now but could not get it to work. I am trying to have a method to reverse an integer without the use of strings or arrays. For example, 123 should reverse to 321 in integer form.
My first attempt:
/** reverses digits of integer using recursion */
public int RevDigs(int input)
{
int reverse = 0;
if(input == 0)
{
return reverse;
}
int tempRev = RevDigs(input/10);
if(tempRev >= 10)
reverse = input%10 * (int)Math.pow(tempRev/10, 2) + tempRev;
if(tempRev <10 && tempRev >0)
reverse = input%10*10 + tempRev;
if(tempRev == 0)
reverse = input%10;
return reverse;
}//======================
I also tried to use this, but it seems to mess up middle digits:
/** reverses digits of integer using recursion */
public int RevDigs(int input)
{
int reverse = 0;
if(input == 0)
{
return reverse;
}
if(RevDigs(input/10) == 0)
reverse = input % 10;
else
{
if(RevDigs(input/10) < 10)
reverse = (input % 10) *10 + RevDigs(input/10);
else
reverse = (input % 10)* 10 * (RevDigs(input/10)/10 + 1) + RevDigs(input/10);
}
return reverse;
}
I have tried looking at some examples on the site, however I could not get them to work properly. To further clarify, I cannot use a String, or array for this project, and must use recursion. Could someone please help me to fix the problem. Thank you.
How about using two methods
public static long reverse(long n) {
return reverse(n, 0);
}
private static long reverse(long n, long m) {
return n == 0 ? m : reverse(n / 10, m * 10 + n % 10);
}
public static void main(String... ignored) {
System.out.println(reverse(123456789));
}
prints
987654321
What about:
public int RevDigs(int input) {
if(input < 10) {
return input;
}
else {
return (input % 10) * (int) Math.pow(10, (int) Math.log10(input)) + RevDigs(input/10);
/* here we:
- take last digit of input
- multiply by an adequate power of ten
(to set this digit in a "right place" of result)
- add input without last digit, reversed
*/
}
}
This assumes input >= 0, of course.
The key to using recursion is to notice that the problem you're trying to solve contains a smaller instance of the same problem. Here, if you're trying to reverse the number 13579, you might notice that you can make it a smaller problem by reversing 3579 (the same problem but smaller), multiplying the result by 10, and adding 1 (the digit you took off). Or you could reverse the number 1357 (recursively), giving 7531, then add 9 * (some power of 10) to the result. The first tricky thing is that you have to know when to stop (when you have a 1-digit number). The second thing is that for this problem, you'll have to figure out how many digits the number is so that you can get the power of 10 right. You could use Math.log10, or you could use a loop where you start with 1 and multiply by 10 until it's greater than your number.
package Test;
public class Recursive {
int i=1;
int multiple=10;
int reqnum=0;
public int recur(int no){
int reminder, revno;
if (no/10==0) {reqnum=no;
System.out.println(" reqnum "+reqnum);
return reqnum;}
reminder=no%10;
//multiple =multiple * 10;
System.out.println(i+" i multiple "+multiple+" Reminder "+reminder+" no "+no+" reqnum "+reqnum);
i++;
no=recur(no/10);
reqnum=reqnum+(reminder*multiple);
multiple =multiple * 10;
System.out.println(i+" i multiple "+multiple+" Reminder "+reminder+" no "+no+" reqnum "+reqnum);
return reqnum;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int num=123456789;
Recursive r= new Recursive();
System.out.println(r.recur(num));
}
}
Try this:
import java.io.*;
public class ReversalOfNumber {
public static int sum =0;
public static void main(String args []) throws IOException
{
System.out.println("Enter a number to get Reverse & Press Enter Button");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String input = reader.readLine();
int number = Integer.parseInt(input);
int revNumber = reverse(number);
System.out.println("Reverse of "+number+" is: "+revNumber);
}
public static int reverse(int n)
{
int unit;
if (n>0)
{
unit = n % 10;
sum= (sum*10)+unit;
n=n/10;
reverse(n);
}
return sum;
}
}

Categories