Stanford CS106A Assignment 2 Hailstone Solution

I’m pretty proud to say, that this one took me about 20-30 minutes to complete 🙂 It didn’t look easy initially (that’s why I waited all the way till the end to start it), but after doing the Find Range one, this one was a piece of cake! Here is the problem:

Here is my solution, also available on gist:


The hardest part of this problem was remembering to use the if / else statement instead of to “if” statements, since the first time I ran this, the operation continued to execute both of the “if” statements each time through the loop. Also, remember that an even number will not have a remainder when divided by 2 – hence the n%2 if statement for even numbers 🙂

<pre>/*
 * File: Hailstone.java
 * Name: 
 * Section Leader: 
 * --------------------
 * This file is the starter file for the Hailstone problem.
 */

import acm.program.*;

public class Hailstone extends ConsoleProgram {
	public void run() {
		int n = readInt("?"); //ask user for initial number input
		int steps = 0; //store the number of steps it takes to get to 1
		while ( n != 1 ) {
			if ( n%2 == 0) { //if the remainder of n/2 is 0, then the number is even
				println (n + " is even, so I take half: " + n/2);
				n = (n/2);
				steps = steps + 1;
			}
			else {
				println (n + " is odd, so I make 3n+1: " + (3*n+1));
				n = (3*n +1);
				steps = steps + 1;
			}
		}
		println ("The process took " + steps + " to reach 1");
	}	
}</pre>

Ok, now moving on to bigger and greater things in Java 🙂

Enjoy the article? Join over 17,500+ Swift developers and enthusiasts who get my weekly updates.

  • Hi! I ended up with a solution as good as identical to yours. Here it is:

    import acm.program.*;
    
    public class HailstoneSequence extends ConsoleProgram {
    	
    	public void run(){
    		int x = 0; //Counts number of cycles
    		int n = readInt("Enter a number: ");
    		while(n != 1){
    			if(n % 2 == 0){
    				print(n + " is even so I take half: ");
    				n /= 2;
    				println(n);
    			}else{
    				print(n + " is odd, so I make 3n + 1: ");
    				n = (n * 3) + 1;
    				println(n);
    			}
    			x++;
    		}
    		println("The process took " + x + " cycles to reach 1");
    	}
    
    }
  • jasmine

    Just want to point out that you might need to have a special case for the case where the input = 1. The idea is to have operations on any positive integer until they reach 1– which means this should be applicable to 1 itself as well. In the current program it would say took 0 steps to reach 1, but that would be logically inaccurate since you are also suppose to perform operations on 1 until it reaches 1.

    • Thanks for letting me know! Not everything I publish is the best solution, so I love getting feedback.

  • I decide to take the program to a tiny little extra level (feeling actually kinda happy with myself on this one, as i achieved it without help)

    The program tests if its true! that there is no number that can simplified… Clearly this method i am using is not practical to be implemented but it does show proof of concept.. and it can easily be tweaked to actually serve the function to search for such a number…. feedback would be super welcome

    /*
     * File: Hailstone.java
     * Name: 
     * Section Leader: 
     * --------------------
     * This program checks to see if there is a solution the Hailstone problem, cannot
     * simplify to 1.
     * 
     * It tell to you how many steps it takes to simply each number and if it worked
     */
    
    import acm.program.*;
    
    public class Hailstone extends ConsoleProgram {
    	
    	private boolean status = true;  // default success of simplifyTo1. True means it worked 
    	private int valueToSimplify = 1; // The number that is to be simplified to 1 
    	private int MAX_VALUE = 1000;  // control number of iterations of simplify to 1 (using the simplifyTo1 method)
    	
    	public void run() {
    		getSimplified();
    		
    	}
    
    	// This method takes a number and simplifies it to 1.
    	private void getSimplified(){
    		while (status) { // the status is set to true by default
    			simplifyTo1(valueToSimplify);  // calling the method
    			valueToSimplify++; 
    			
    			if (valueToSimplify > MAX_VALUE) {  // check how many instances the simplifyTo1 was used
    				 break;
    			}
    		
    		}
    	}
    	
    	
    	private void simplifyTo1(int newValue){
    		int n = newValue;
    		int count = 0; // use to keep track of steps per simplification
    		
    		println("Simplifying " + n + " to 1");
    		while (n != 1) {
    			if (n % 2 == 0) { //tests is n is even, if it is it halves the value
    				//int temp = n;
    				n /= 2;	
    				//println(temp + " is even, so i take half: " + n);
    			} else {
    				//int temp = n;
    				n = 3*n + 1;
    				//println(temp + " is odd, so i make 3n + 1: " + n);
    			}
    			count++;
    			
    			
    		}
    		//produces the text to inform us how many step it took to solve, and if it solved it
    		if ((n == 1) ? true : false);
    		println("It took " + count + " steps to reach 1 _ " + status);
    	}		
    }
    
    
    
    
  • Hi Natasha,

    My solutions looks a bit different from yours:

    private void run(){
    		int n = readInt ("Enter a number: ");
    		for (int j=1; n!=1; j++){ 
    				if (n%2==0){
    					int even = n/2;
    					println(n + " is even so I take half: " + even);
    					n = even;
    				} else {
    					int odd = 3*n + 1;
    					println(n + " is odd, so 3n + 1: " + odd);
    					n = odd;
    			} if (n==1){
    				println("This process took " + j + " steps!");
    			}
    		}
    		
    	}
    

    I’ve just been programming for like a month, so I dunno if my idea was not good… could you give me a help? =)

  • Krys

    Here’s my solution. It’s similar to yours, but it takes care of some other special cases, like if n=1 or 0.
    http://pastebin.com/Rnh0gxtj

  • Nathan

    Here’s mine:

    
    import acm.program.*;
    import java.awt.*;
    
    public class DefaultConsole extends ConsoleProgram{
        public void run()
        {
        int n, count=0;
        println("Godel Escher's Puzzle.");
        n = readInt("Pick an Integer: ");
        
            do {
                n = processNum(n);
                count++;
            }while (n!=1);
            println(" The count took " + count + " iterations to reach 1");
            }
        public int processNum(int num){
                if(num%2==0) {
                println("   " + num + " is even, so I take half: " + num/2);
                return num/2;
            }
            else {
                println("   " + num + " is odd, so I make 3n+1: " + (num*3)+1);
                return (num*3)+1;
            }
        }
    } 
  • filmibuff

    here is my code. I guess I could have made it a little simpler but it seems to work:

    [ code language = “java” ]

    /*

    * File: Hailstone.java

    * Name:

    * Section Leader:

    * ——————–

    * This file is the starter file for the Hailstone problem.

    */

    import acm.program.*;

    public class Hailstone extends ConsoleProgram {

    public void run() {

    int n=readInt(“Enter a positive Integer: “);

    if (n==0) println(“0 entered Program Quits”);

    else hailStone(n);

    }

    private void hailStone(int n){

    int total=0;

    String flag=””;

    int newn=0;

    while (n!=1){

    boolean even=evenOrOdd(n);

    if (even) {

    newn=n/2;

    flag=”even, so I take half: “;

    }

    else{

    newn=(3*n)+1;

    flag=”odd, so I make 3n+1: “;

    }

    println(n+” is “+ flag+newn);

    total++;

    n=newn;

    }

    println(“The process took “+total+ ” to reach 1″ );

    }

    private boolean evenOrOdd(int n){

    return (n%2==0);

    }

    }

    [/code]

  • But if the intitial value was 1 then you haven’t performed any operations on it before it reaches 1, so 0 steps is correct…