Hailstone Program in Java

馋奶兔 提交于 2019-12-12 04:18:29

问题


I have the following program to write:

An interesting (yet unsolved) question in mathematics is called "hailstone numbers". This series is produced by taking an initial integer and if the number is even, dividing it by 2. If the number is odd, multiply it by 3 and add 1. This process is the repeated.

For example: An initial number of 10 produces: 10, 5, 16, 8, 4, 2, 1, 4, 2, 1... An initial value of 23 produces: 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1...

Note that both numbers eventually reach the 4, 2, 1, 4, 2, 1... cycle.

Create an application that offers the user three different ways to run this program.

  • Option 1: Print the hailstone numbers for a single entry and its length
    Example: Input> 10 10, 5, 16, 8, 4, 2, 1 Length 7
  • Option 2: Print all of the hailstone numbers from 4 to a given entry
    Example: Input> 6 4, 2, 1 Length 3 5, 16, 8, 4, 2, 1 Length 6 6, 3, 10, 5, 16, 8, 4, 2, 1 Length 9
  • Option 3: Print out the number with the maximum number of iterations need to reach the cycle and which starting number produces this maximum from 4 to the number entered.
    Example: Input> 6 Longest: 6 Length: 9

    In writing this program you must implement the following method...

  • /** 
     * 
     * @param num  Number that a hailstone chain will be generated 
     * @param showNumbers  true if list of numbers is shown to screen 
     * @return  Count of the numbers in the num hailstone chain.
     */
    private static int hailStone(int num, boolean showNumbers) {
        // your code
    }
    

    This is the code I've written so far:

    public static void main(String[] args) {
            int a = getInt("Give a number: ");
    
            System.out.print("How would you like to run the program? Option 1 prints hailstone numbers for a single entry and its length." +
                    "Option 2 prints all the hailstone numbers from 4 to a given entry. Option 3 prints the number with the maximum number" +
                    "of iterations needed to reach the 4, 2, 1 cycle.");
            int option = console.nextInt();
    
            boolean showNumbers = (option == 1 || option == 2);
    
            hailStone(a, showNumbers);
        }
    
        public static int getInt(String prompt) {
            int input;
    
            System.out.print(prompt);
            input = console.nextInt();
    
            return input;
        }
    
        private static void hailStone (int a, boolean showNumbers) {
            if (showNumbers == true) {
                if (a % 2 == 0) {
                    for (int i = 0; i < 50; i++) {
                       for (int j = 0; j <= i; j++)
                        a /= 2;
                        System.out.print(a + " ");
                        a *= 3;
                        a += 1;
                        System.out.print(a + " ");
                    }
    
                } else {
                    for (int i = 0; i != a; i++) {
    
                    }
                }
            } else {
    
            }
        }
    

    I feel like I've hit a brick wall because I have no idea how to implement all these options in the method my teacher is requiring us to use. Plus, I can't seem to get even the basic hailstone chain to print. Help?


    回答1:


    The HailStone algorithm should not be hard to implement. It will actually be much easier if you make it a recursive function, since that is more natural Writing it as an iterative function is probably what is causing your issues.

    This should be enough to get you started, this is a working HailStone implementation using a recursive function. You can implement the rest of the project requirements quite easily once you've got the algorithm working... but I'd like to challenge you to convert this into a working iterative function once you get the features correct and to write unit tests to test the program. (TDD dictates that you should write your tests BEFORE you write the actual implementation. This is a great practice that is often skipped due to time constraints and the perception that a strong test suite is overkill.)

    HailStone.java

    public class HailStone {
        /* static variable to count calls to hailStone */
        public static int iterCount = 0;
    
        /* This variable is a senti */
        public static boolean isRepeating = 0;
    
        /* Simple main function */
        public static void main(String[] args) {
            // TODO:
            //   Either parse args or use a scanner to get input.
            //   Args = verbose, entryPoint
            hailStone(10, true);
        }
    
        /* Recursive hailStone implementation */
        private static void hailStone(int a, boolean showNumbers) {
            // start off by printing the numbers if showNumbers is true
            if (showNumbers) {
                System.out.printf("Iteration #%d: %d\n", ++iterCount, a);
            }
    
            // base case: a = 1 => most important part of recursion
            if (a == 1) {
                if (isRepeating) {
                    return;
                }
                isRepeating = true;
            }
    
            // check if a is odd
            // You can use modulo divison, but we'll use bitwise &
            /* Explained: [ bitwise AND... bits that are set in a AND in 1 ]
            **********************************************
                 Case 1: a is even =>
                     a = 10
                     10 in binary is 00001010
                      1 in binary is 00000001
                ------------------------------
                 10 & 1 in binary is 00000000
    
                 Case 2: a is odd =>
                     a = 10
                     11 in binary is 00001011
                      1 in binary is 00000001
                ------------------------------
                 11 & 1 in binary is 00000001
            **********************************************
                set(X) = set of all even numbers
                set(Y) = set of all odd numbers
                {
                  x is any arbitrary number in set X,
                  y is any arbitrary number in set Y
                }
                x & 1 will ALWAYS equal 0 -\
                                            >- know this. bitwise hacks rock.
                y & 1 will ALWAYS equal 1 -/
            */
            if ((a & 1) == 1) {
                a *= 3;
                a += 1;
            } else {
                a /= 2;
            }
    
            // Tail recursion.
            hailStone(a, showNumbers);
            return;
        }
    }
    

    without all the comments and extra stuff:

    public class HailStone {
        public static int iter_count = 0;
        public static void main(String[] args) {
            hailStone(10, true);
        }
        /* Recursive hailStone implementation */
        private static void hailStone(int a, boolean showNumbers) {
            if (showNumbers) {
                System.out.printf("Iteration #%d: %d\n", ++iter_count, a);
            }
            // base case: a = 1
            if (a == 1) {
                return;
            }
            if ((a & 1) == 1) { // a is odd:
                a *= 3;
                a += 1;
            } else {
                a /= 2;
            }
            hailStone(a, showNumbers);
            return;
        }
    }
    



    回答2:


    private static Scanner console = new Scanner(System.in);
    
    public static void main(String[] args) {
        System.out.println("How would you like to run the program?");
        System.out.println(" [1] - print hailstone numbers for a single entry and its length.");
        System.out.println(" [2] - print all hailstone numbers from 4 to a given entry.");
        System.out.println(" [3] - print the number with the maximum number of iterations needed to reach the 4, 2, 1 cycle.");
        int option = queryInt("Option: ", 1, 3);
        switch (option) {
            case 1: {
                int seed = queryInt("INPUT> ", 1, Integer.MAX_VALUE);
                hailStone(seed, true);
                break;
            }
            case 2: {
                int maxSeed = queryInt("INPUT> ", 4, Integer.MAX_VALUE);
                for (int i = 4; i <= maxSeed; i++) {
                    hailStone(i, true);
                }
                break;
            }
            case 3: {
                int maxSeed = queryInt("INPUT> ", 4, Integer.MAX_VALUE);
                int longestChain = 0;
                int longestChainLength = 0;
                for (int i = 4; i <= maxSeed; i++) {
                    int length = hailStone(i, false);
                    if(length > longestChainLength) {
                        longestChain = i;
                        longestChainLength = length;
                    }
                }
                System.out.println("Longest: " + longestChain + " Length: " + longestChainLength);
                break;
            }
        }
    }
    
    private static int queryInt(String prompt, int min, int max) {
        while (true) {
            System.out.print(prompt);
            String input = console.nextLine();
            try {
                int result = Integer.parseInt(input);
                if (result >= min && result <= max) {
                    return result;
                } else {
                    System.err.print("Expected a number ");
                    if (min == Integer.MIN_VALUE) {
                        System.err.println(" less than or equal to " + max);
                    } else if (max == Integer.MAX_VALUE) {
                        System.err.println(" greater than or equal to " + min);
                    } else {
                        System.err.println(" between " + min + " and " + max);
                    }
                }
            } catch (NumberFormatException ex) {
                System.err.println("Not a number: " + input);
            }
        }
    }
    
    private static int hailStone(int num, boolean showNumbers) {
        int result = 1;
        for (Iterator<Integer> chain = iterateHailStone(num); num != 1; num = chain.next(), result++) {
            if (showNumbers) {
                System.out.print(num + ", ");
            }
        }
        if (showNumbers) {
            System.out.print(num);
            System.out.println(" (length=" + result + ")");
        }
        return result;
    }
    
    private static Iterator<Integer> iterateHailStone(int seed) {
        return new Iterator<Integer>() {
            int value = seed;
    
            @Override
            public boolean hasNext() {
                return true;
            }
    
            @Override
            public Integer next() {
                if (value % 2 == 0) {
                    value /= 2;
                } else {
                    value *= 3;
                    value++;
                }
                return value;
            }
        };
    }
    


    来源:https://stackoverflow.com/questions/34092721/hailstone-program-in-java

    易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
    该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!