Hailstone Sequence in Java with ArrayList - java

Hello I am attempting to perform the hailstone sequence.
A hailstone sequence is basically: take a given integer n - if even, the next integer in the sequence is n/2, if odd, the next integer in sequence is n * 3 + 1.
The API I must follow for my assignment requires it to be performed as it is with a method returning an arraylist.
My problem is the code just hangs forever, when I added output in the method itself to see what was happening I see it always hangs when it is given the number 10 for some reason.
I am hoping that there is something small I am missing here perhaps in my conditions.
Here is some sample output when given n value of 15 it outputs this over and over again.
15 is odd so I make it 3n+1: 46
46 is even so I divide by 2: 23
23 is odd so I make it 3n+1: 70
70 is even so I divide by 2: 35
35 is odd so I make it 3n+1: 106
106 is even so I divide by 2: 53
53 is odd so I make it 3n+1: 160
160 is even so I divide by 2: 80
80 is even so I divide by 2: 40
40 is even so I divide by 2: 20
20 is even so I divide by 2: 10
15 is odd so I make it 3n+1: 46
My code
import java.util.ArrayList;
import java.util.Scanner;
public class HailstoneSequence {
public static ArrayList<Integer> getHailstoneSequence(int n){
ArrayList<Integer> results;
results = new ArrayList<Integer>();
results.add(n);
//while the last number is not 1 perform these actions
while((results.size() - 1) != 1){
//for each number in the array
for(int i=0; i< results.get(i); i++){
//test if odd or even
if((results.get(i)%2)==0){
System.out.println(results.get(i)+" is even so I divide by 2: "+ (results.get(i)/2));
results.add((results.get(i)/2));
}
else{
//odd
System.out.println(results.get(i)+" is odd so I make it 3n+1: "+ (3*(results.get(i))+1));
results.add((3*(results.get(i))+1));
}
}
}
return results;
}
public static void main(String[] args) {
int n=0;
Scanner sc = new Scanner(System.in);
System.out.println("Enter the value of n ");
n=sc.nextInt();
sc.close();
//create an initialize new array list to hold results of the hailstonesequence
ArrayList<Integer> list;
list = new ArrayList<Integer>();
list = getHailstoneSequence(n);
//for each number in the array
for(int i=0; i< list.get(i); i++){
if ((list.get(i)!= 1)){
if((list.get(i)%2)==0){
System.out.println(list.get(i)+" is even so I divide by 2: "+ (list.get(i+1)));
}
else{
//odd
System.out.println(list.get(i)+" is odd so I make it 3n+1: "+ (list.get(i+1)));
}
}
else{break;}
}
}
}

In your method for(int i=0; i< results.get(i); i++){ and in main for(int i=0; i< list.get(i); i++){
These do not loops over each element of the list, or at least not only once, and it'll eventually result in out of bounds if you never added to the list.
Say results.get(i) is 10, and that's the only number in the list... You then add 5 ten times because 10 is even and the loop is running ten times. You then are probably adding 16 5*10 times, etc, etc
Adding elements to lists while you iterate over them is generally a bad idea anyway. You only need to keep track of two numbers at a time, and can add to the list separate from the iteration process.
Here's a working sample
ArrayList<Integer> results = new ArrayList<Integer>();
results.add(n);
if (n == 1) return results;
int next;
if (n % 2 == 0) next = n / 2;
else next = 3*n + 1;
results.add(next);
while (next != 1) {
if (next % 2 == 0) next = next / 2;
else next = 3*next + 1;
results.add(next);
}
return results;

Related

My output seems to have extra spacing after each line is printed

Edit: I figured out what was wrong, when count hits 5, it stays at 5 until the first condition is hit then count changes. This results in the extra empty lines.
So my goal is for the output to be one line after the other but its not doing that.
public class Main {
public static void main(String[] args) {
int n=10,m=50,a=2,b=3;
int count = 0;
for (int i=n;i<=m;i++){
if(i%a==0&&i%b!=0) {
System.out.print(i + " ");
count++;
}
if (count%5==0)
System.out.println();
}
}
}
This code is suppose to take integer values of n, m, a and b and displays all the numbers from n to m that are divisible by a but not divisible by b, and prints the results 5 numbers per line. So far I have got printing the numbers 5 times per line down but every time it out puts the next line, instead of immediately printing to the next line it skips some.
Here is what its suppose to do when n=10, m=50, a=2 and b=3:
10 14 16 20 22
26 28 32 34 38
40 44 46 50
Instead its printing this:
10 14 16 20 22
26 28 32 34 38
40 44 46 50
What am I doing wrong?
When count reaches a number that's divisible by 5, you continue iterating over i. In some of these iterations, count is not incremented, so it remains divis5 and you continue adding new lines.
Moving the second if statement inside the for loop should solve this:
for (int i=n;i<=m;i++){
if(i%a==0&&i%b!=0) {
System.out.print(i + " ");
count++;
if (count % 5 == 0) // Here!
System.out.println();
}
}
You forgot to consider that the count variable will not increase as long as you dont satisfy the first if block. The better way is to check if its equal to 5
print new line the set count = 0
public class Main {
public static void main(String[] args) {
int n=10,m=50,a=2,b=3;
int count = 0;
for (int i=n;i<=m;i++){
if(i%a==0&&i%b!=0) {
System.out.print(i + " ");
count++;
}
if (count==5){
System.out.println();
count = 0;
}
}
}
}
When the count is 5 and the code is not entered to the first "if" the new line will be printed because the count will not be increased.
Please try:
public class Main {
public static void main(String[] args) {
int n=10,m=50,a=2,b=3;
int count = 0;
boolean is_new_line = false;
for (int i=n;i<=m;i++){
if(i%a==0&&i%b!=0) {
System.out.print(i + " ");
count++;
is_new_line = false;
}
if ((count%5==0) && (is_new_line==false)) {
System.out.println();
is_new_line = true;
}
}
}
}

ProjectEuler's distinct prime factors of a given number

folks, I've been struggling to figure out the algorithm to get the list of all of the prime factors of the given number (in my case, the given number is myNumber = 14). For example,
14 = 2 × 7
15 = 3 × 5
645 = 3 × 5 × 43
646 = 2 × 17 × 19
But my code is running infinitely and I'm not pretty sure if my algorithm works fine. Could smb take a look or give me a hand how to see the problem? Thanks in advance!
import java.util.*;
public class DistinctFactors {
public static final List<Integer> myList = new ArrayList<>();
public static void main(String[] args){
int result = 1;
int myNumber = 14;
int i = 2;
while(result != myNumber){
if(isPrime(i)){
myList.add(i);
result *= i;
}
i++;
}
for(int j = 0; i < myList.size(); j++){
System.out.print(myList.get(j) + " ");
}
}
private static boolean isPrime(int number){
for(int i = 2; i < number; i++){
if(number % 2 == 0){
return false;
}
}
return true;
}
}
I mean, let's look at what the values of result and i will be.
Pass 1: r = 1, i = 2
Pass 2: r = 2, i = 3
Pass 3: r = 6, i = 4
Pass 4: r = 6, i = 5
Pass 5: r = 30, i = 6
From this point on, r will only increase, and it's already greater than 14. So of course this loop will never terminate.
Your method is also extremely wrong. I have no idea why you chose this way to try and get prime factors.
Not to mention, even your isPrime method is kind of dumb. It checks all the way up to the number you're checking, which is extremely wasteful.
To check if a number n is prime, you should instead compute the square root; if it is an integer, then the number is obviously not prime. Otherwise, take the floor of that sqrt(n) - let's call it k - and run the loop up to k. If n is not prime, you will find a divisor in that range; if you find none, n is prime.
(That is an O(log(n)) method. The best method is the one that involves checking whether the number satisfies Fermat's Little Theorem for random values, which is constant time).
EDIT: Well, not exactly constant time if you don't consider certain operations O(1). For huge numbers it's much better than the other method
Your current loop just checks whether the number is even a bunch of times...

Checking if array is symmetric

public class symm
{
/*
* Returns true if array A is symmetric.
* Returns false otherwise.
* n is the number of elements A contains.
*
* The running time of your algorithm is O( ).
* You may add a brief explanation here if you wish.
*/
public static boolean symmetric( int[] A, int n )
{
return symmHelper(A, n, 0);
}
private static boolean symmHelper(int[] A, int n, int i) {
if(n==1)
return true;
if((n==2) && (A[i] == A[n-1-i]))
return true;
if((i == n-1-i) && (A[i] == A[n-1-i] ))
return true;
if(A[i] == A[n-1-i] && i < n/2 )
return symmHelper(A, n, i+1);
return false;
}
}
Test cases:
I passed all the tests ecxept the fitst on I get no whenever I run it, I think the problem is that there are two 2s in the middle. And I'm not really sure about the code, I think it can be simplified.
Is the running time o(log n)?
5 8 2 2 8 5
YES
10 7 50 16 20 16 50 7 10
YES
5 8 5
YES
1000 1000
YES
6000
YES
10 7 50 16 20 16 50 7 1000
NO
10 7 50 16 20 16 50 700 10
NO
10 7 50 16 20 16 5000 7 10
NO
10 7 50 16 20 1600 50 7 10
NO
10 7 50 16 1600 50 7 10
NO
Complex code makes for more mistakes. Thus, simplify it. Also, look for inequalities rather than equalities; it's easier to check for one mistake than for everything to be correct.
// A = array, n = size of array, i = looking at now
private static boolean symmHelper(int[] A, int n, int i) {
if (i > n/2) // If we're more than halfway without returning false yet, we win
return true;
else if (A[i] != A[n-1-i]) // If these two don't match, we lose
return false;
else // If neither of those are the case, try again
return symmHelper(A, n, i+1);
}
If I remember my O() notation right, I think this should be O(n+1). There are other tweaks you can make to this to remove the +1, but it'll make the code run slower overall.
if(A[i] == A[n-1-i] && i < n/2 )
That line right there is the problem. Because you're using an even number > 2 of values, when it gets to this line it skips over it because at that point i = n/2, rather than being less than it. So the function skips that and continues on to return false. Change it to this and you should be fine:
if(A[i] == A[n-1-i] && i <= n/2 )
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int N;
int i;
boolean sym = true;
N=input.nextInt();
int [] numbers = new int [N];
for (i=0; i<N; i++){
numbers[i]= input.nextInt();
}
for(i=0;i<N;i++){
if(numbers[i]!= numbers[N-1-i]){
sym=false;}
}
if(sym==true){
System.out.println("The array is a symetrical array");
}
else{
System.out.println("The array is NOT a symetrical array");
}
}
}
This check is useless:
if((i == n-1-i) && (A[i] == A[n-1-i] ))
return true;
Of course if the two indices are the same the values there will match.
Also you need to split this if in two:
if(A[i] == A[n-1-i] && i < n/2 )
return symmHelper(A, n, i+1);
And return true if i >= n/2.
Otherwise what happens is that after i > n/2 (which means you already know your array is symmetrical), you do not go into that if and thus return false, which is wrong.
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int N;
int i;
N=input.nextInt();
int [] numbers = new int [N];
for (i=0; i<N; i++){
numbers[i]= input.nextInt();
}
i=0;
while (i<N/2&& numbers[i] == numbers [N-1-i]){i++;
}
if(i==N/2){
System.out.println("The array is a symetrical array");
}
else{
System.out.println("The array is NOT a symetrical array");
}
}

How to write a program that reverses a number a user inputs

The homework problem is the user enters a number. Then you have to write a program that reverses that order. So if the user enters 7364 you have to write a program that presents 4637 on the next line. I think I've figured out the solution but I'm not sure how to write it.
Since the last number is the first number in reverse order that means that if someone enters 7364 that means i want to get 4637. I have to write a program that multiplies 4 by 1000, 6 by 100, 3 by 10 and 7 by 1 then add those up to get 4637. I'm not not 100% sure how to do it. What's messing me up is how to multiply one number by 1000, the next by 100, the next by 10 and the next by 1 then add those up.
import acm.program.*;
public class ReverseNumber extends ConsoleProgram{
public void run(){
int n = readInt("please enter any positive number: ");
int total = 0;
while ( n > 0){
total = total + n % 10; <----?
n = n * 1000; <----?
}
println("the reverse order is" + total);
}
}
The easiest way to do it using library.
System.out.println(new StringBuilder(String.valueOf(i)).reverse());
Try this:
while( n != 0 )
{
reverse = reverse * 10;
reverse = reverse + n%10;
n = n/10;
}
Logic is to get a single digit in each iteration starting from unit place, until all digits are encountered.
n is the input no.
reverse is the variable where reverse of n is stored after while is finished.
% operator when used with 10, gives you the digit at unit place.
/ operator when used with 10, goves you all the digits except the digit at unit place.
When n = 7364 and reverse = 0
in 1st iteration, loop will look like:
while(7364 != 0) // true
{
reverse = 0 * 10; // reverse = 0
reverse = 0 + 7364%10 // reverse = 4
n = 7364/10 // n = 736
}
in 2nd iteration:
while(736 != 0) // true
{
reverse = 4 * 10; // reverse = 40
reverse = 40 + 736%10 // reverse = 46
n = 736/10 // n = 73
}
in 3rd iteration:
while(73 != 0) // true
{
reverse = 46 * 10; // reverse = 460
reverse = 460 + 73%10 // reverse = 463
n = 73/10 // n = 7
}
in 4th iteration:
while(7 != 0) // true
{
reverse = 463 * 10; // reverse = 4630
reverse = 4630 + 7%10 // reverse = 4637
n = 7/10 // n = 0
}
in 5th iteration:
while(0 != 0) // false and loop ends
{
...
}
and we have reverse = 4637.
Well, to reverse the number the simplest solution would be to convert it to a string get the first letter and append it at the end until you reach the last letter or number in this case. Also, you can do pretty much the same with the multiplication part. Get the numbers one by one as a string convert it back to int then multiply and add.
EDIT: if you cant do it using strings. here is a somewhat mathematical solution.
int num = 123456; // any number than you want to reverse
string revnum = ''; // the reversed number
int temp = 0;
do {
temp= (temp*10)+(num%10);
num = (int)(num/10);
}while(num>0){
revnum = revnum + temp;
}
This should work:
total = 0;
while (n > 0) {
total = total * 10 + n % 10;
n = n / 10;
}
println("the reverse order is " + total);
You don't have to know how many digits there are in the original number, you're iterating through all of them anyway. Here's what happens:
When you get a new digit (n % 10), you multiply the result by 10 and add it to it. This way, you offset the digits in the result.
Then you eliminate the last digit (the one you added in the step before) from the original number by doing n / 10.
Do you have to represent it with an int? A String seems more natural?
If you stick with the int, you need to keep track of the factor to multiply with: which means another variable that you multiply by 10 each iteration.
Convert the Int to String, then put it in a StringBuffer
then use .reverse()
I wouldn't want to add the codes because there are many samples for this.
Like this one.
After that, you could convert it again to String.
public class value{
public static void main(String[] args){
int n=Integer.parseInt(args[0]);
int t=0;
do{
t=n%10;
System.out.print(t);
n=n/10;
}while(n>0);
}
}

Algorithm to find all permutations of a given N with condition

I am designing a program to print all permutations of a given N such that the each digit should be greater than the next digit.
For Example
if N=3:
output should be 123,456,789,134,145,178,189 etc...
Initial Design:
Generate all possible permutations
Pass the generated permutation to a digit extraction function which checks for the condition
Print out the result
This is a very naive algorithm. But I do not know the implementation/initial design because of the dynamic size of N.
Since N will always be less than 10, i've used recursion
Call the function as f(3,0,0)
public static void f(int N,int digit,int num)
{
if(N > 0 )
{
for(int d = digit + 1; d < 11 - N; d++) // earlier d < 10, see comments
{
f(N-1,d,num * 10 + d);
}
}else {
System.out.println(num); //add it to a list or whatever
}
}
Output:
123
124
...
678
679
689
789
The most straightforward way to do this is with recursion. Suppose you've generated the first n digits and the last digit generated is i. You have N - n digits left to generate and they must start with i + 1 or higher. Since the last digit can be no more than 9, the next digit can be no more than 10 - (N - n). This gives the basic rule for recursion. Something like this (in Java) should work:
void generate(int N) {
int[] generated = new int[N];
generate(generated, 0);
}
void generate(int[] generated, int nGenerated) {
if (nGenerated == generated.length) {
// print the generated digits
for (int g : generated) {
System.out.print(g);
}
System.out.println();
return;
}
int max = 10 - (generated.length - nGenerated);
int min = nGenerated == 0 ? 1 : (generated[nGenerated - 1] + 1);
for (int i = min; i <= max; ++i) {
generated[nGenerated] = i;
generate(generated, nGenerated + 1);
}
}
Just generate them in lexicographic order:
123
124
125
...
134
135
...
145
...
234
235
...
245
...
345
This assumes you have digits at most 5. For larger bound B, just keep going. Some simple code to do this is:
nextW = w;
for (int i=n-1; i>=0; --i) {
// THE LARGEST THE iTH DIGIT CAN BE IS B-(n-i-1)
// OTHERWISE YOU CANNOT KEEP INCREASING AFTERWARDS
// WITHOUT USING A NUMBER LARGER THAN B
if w[i]<B-(n-i-1) {
// INCREMENT THE RIGHTMOST POSITION YOU CAN
nextW[i] = w[i]+1;
// MAKE THE SEQUENCE FROM THERE INCREASE BY 1
for (int j=i+1; j<N; ++j) {
nextW[j] = w[i]+j-i+1;
}
// VOILA
return nextW;
}
}
return NULL;
Start with w = [1,2,3,...,N]; (easy to make with a for loop), print w, call the function above with w as an input, print that, and continue. With N = 3 and B = 5, the answer will be the above list (without the ... lines).
If there is no bound B, then you're SOL because there are infinitely many.
In general, you are computing the Nth elementary symmetric function e_N.

Categories

Resources