Kyler Tolleson
Kyler Tolleson

Reputation: 11

Why is my 3n+1 solution not working?

My assignment for class is to write a method that Returns a string consisting of a Hailstone sequence beginning with the positive integer n and ending with 1. The string should consist of a sequence of numerals, with each numeral followed by a single space. When a numeral m (other than 1) appears in the sequence, it should be followed by nextHailstone(m). For example, nextHailstone(1) should return "1 " and nextHailstone(5) should return "5 16 8 4 2 1 ".

I have the following code and can't figure out why it gets stuck in an infinite loop.

public static int nextHailstone (int n)
{
    if (n==1)
    {
        return n;
    }
    if (n%2 == 0)
    {
        return n/2;
    }
    else
    {
        return ((3*n)+1);
    }
}

public static String hailstones (int n)
{
    String result = "";
    result+=n;
    result+= ' ';

    while (true)
    {
        if (result.charAt(result.length()-2)=='1')
        {
            return result;
        }
        else
        {
            result +=(nextHailstone(result.charAt(result.length()-2)) + ' ');
        }
    }
}

Test cases:

public void testHailstones ()
{
    assertEquals("1 ", hailstones(1));
    assertEquals("16 8 4 2 1 ", hailstones(16));
    assertEquals("7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1 ", hailstones(7));
}

Upvotes: 1

Views: 179

Answers (2)

Eran
Eran

Reputation: 393946

You are passing result.charAt(result.length()-2) to nextHailstone. This means you are passing a char and your nextHailstone operates on its int value, and not on the digit represented by that char. In addition, you only pass a single char to the nextHailstone. You don't handle multi-digit numbers.

For example, suppose you try halstones (1) :

You set result to "1 ". Then you pass '1' to nextHailstone. But the char '1' is 49 as int. So instead of returning 1 as you expect, it would return 49*3+1=148. result would be updated to "1 148 ".

At the next step you'll pass the char '8' (ignoring the 14) to nextHailstone, which is 56 as int. You can see why your loop will never terminate.

You should probably store the sequence in a List of ints, and only convert it to String when you are ready to return the output.

You can do something like this :

public static String hailstones (int n)
{
    List<Integer> seq = new ArrayList<Integer>();
    seq.add(n);

    while (true)
    {
        if (seq.get(seq.size()-1)==1)
        {
            return seq.toString(); // You might have to change that if you require
                                   // the output in a different format
        }
        else
        {
            seq.add(nextHailstone(seq.get(seq.size()-1)));
        }
    }
}

Upvotes: 1

PsyCode
PsyCode

Reputation: 664

The reason your stuck in an infinite is that you have a while(true) loop. This will run infinitely unless broken. You never have the if statement true so it will continually run.

Upvotes: 1

Related Questions