How can I solve the Collatz conjecture algorithm in C#?

4.8k views Asked by At

I was able to solve the Collatz conjecture algorithm (no, i didn't try to prove it) in about 5 minutes using Java.

Now that I'm learning C# to make web apps, I'm running into trouble doing the same thing. I simply want the user to enter a number, click a button, and print the output to a text box.

Here is the button Click event handler method I'm using:

protected void Button3_Click(object sender, EventArgs e)
{
    string x = TextBox1.Text;   //user entered a number
    string y =collatz(x);       //this function is below and returns a string
    chatbox.Text = y;           //output
}

And here is the Collatz method:

public static string collatz(string y)
{   
    if (y == null)
        return null;

    double x = double.Parse(y); //x is my "n"
    y = x.ToString(); //output string

    double large = x; //keep track of biggest number

    // the algorithm
    // the redundancies (like x==1.. x!= 1) are part of troubleshooting :/

    while (x > 1)
    {
        if (x % 2 == 0)
        {
            x = x / 2;
            if (x > large)
                large = x;
            if (x != 1)
                y = y+" "+ x.ToString();
            if (x == 1)
            {
                y = y + " " + x.ToString();
                y = y + " largest number was " + large;

            }
        }

        if (x % 2 != 0)
        {
            if (x == 1)
            {
                y = y+" "+ x.ToString();
                y = y + " largest number was " + large;

            }

            x = (3 * x) + 1;
            if (x > large)
                large = x;
            y = y+" "+ x.ToString();

        }
    }

    return y;
}

EDIT when I use the VS.net debugger and enter a number like 2, I get NO output and NO error. I'm just left waiting forever. If it were an infinite loop, I would get an error eventually, right?

and no, this is not a homework problem (it was 2 years ago when I did it in JAVA though :).) I'm learning C# independently.

5

There are 5 answers

0
Artem Koshelev On
public static string collatz(string y)
{
    if (y == null)
        return null;
    double x = double.Parse(y);
    y = x.ToString();
    double large = x;
    while (x > 1) {
        if (x % 2 == 0) {
            x = x / 2;      // x reassigned
            if (x > large)
                large = x;
            if (x != 1)
                y = y + " " + x.ToString();
            if (x == 1) {
                y = y + " " + x.ToString();
                y = y + " largest number was " + large;

            }
        }
        // Infinite loop goes because of that
        if (x % 2 != 0) {  // double check on reassigned variable, use “else” instead
            if (x == 1) {
                y = y + " " + x.ToString();
                y = y + " largest number was " + large;

            }
            x = (3 * x) + 1;
            if (x > large)
                large = x;
            y = y + " " + x.ToString();
        }
    }
    return y;
}

I tried it with fixed code (using else) and it works fine.

Also, you don't need double type since Collatz works with natural numbers. The following is a quick refactoring to add more .NET-ty to your code:

public static string collatz(string input)
{
    int current = 0;
    if (string.IsNullOrEmpty(input) || !int.TryParse(input, out current) || current < 1) {
        return "Empty, not a number or less then 1";
    }
    int max = current;
    while (current > 1) {
        if (current % 2 == 0) {
            current = current / 2;          // current reassigned
            if (current > max)
                max = current;
            if (current != 1)
                input = input + " " + current.ToString();
            if (current == 1) {
                input = input + " " + current.ToString();
                input = input + " largest number was " + max;

            }
        } else {
            if (current == 1) {
                input = input + " " + current.ToString();
                input = input + " largest number was " + max;
            }
            current = (3 * current) + 1;
            if (current > max)
                max = current;
            input = input + " " + current.ToString();
        }
    }
    return input;
}
0
Ken Smith On

You had an infinite loop. Try this:

public static string collatz(string y)
{
    if (y == null)
    {
        return null;
    }

    int x = int.Parse(y); //x is my "n"
    var results = new StringBuilder();
    results.Append(x.ToString());
    int largest = x; //keep track of biggest number

    // the algorithm
    // the redundancies (like x==1.. x!= 1) are part of troubleshooting :/
    while (x > 1)
    {
        if (x % 2 == 0)
        {
            x = x / 2;
            if (x > largest)
            {
                largest = x;
            }
            if (x != 1)
            {
                results.Append(" " + x.ToString());
            }
            if (x == 1)
            {
                results.Append(" " + x.ToString());
                results.Append(" largest number was " + largest.ToString());
                return results.ToString();
            }
        }

        if (x % 2 != 0)
        {
            if (x == 1)
            {
                results.Append(" " + x.ToString());
                results.Append(" largest number was " + largest.ToString());
                return results.ToString();
            }
            x = (3 * x) + 1;
            if (x > largest)
            {
                largest = x;
            }
            results.Append(" " + x.ToString());
        }
    }
    return results.ToString();
}

Two notes:

  1. When you're doing string concatenation in a loop, it's a good habit to use a StringBuilder rather than s = s + t. Lots, lots less memory allocations.

  2. A lot of times you can't rely on == when it comes to double values. It seems to work in this case, but it might not when you get to higher numbers where there's less precision. Since all the numbers are going to be int's anyway, might as well use those.

0
user607455 On
if (x == 1)
{
    y = y+" "+ x.ToString();
    y = y + " largest number was " + large;
}

This part here (odd x) is redundant. For if x is 1, it will never enter the while loop. Your code seems logically. Maybe try using integer instead.

x = x / 2;
if (x > large)
    large = x;

Redundant code again for even x part. How do you expect x to be bigger than large after division by 2? Just check it in the 3n+1 part will do.

if (x == 1)
{
    y = y + " " + x.ToString();
    y = y + " largest number was " + large;
}

You can just leave this part out and let the while loop handle this check.

0
Carlos Eduardo On

View Equation:

  • if the number is even: n/2

  • if the number is odd: 3n+1

Step One:

Add a method called Collazt which returns a collection of objects of type int of class List<?>

public static List<int> Collazt(int n) {
            List<int> data = new List<int>();
            data.Add(n);

            int resul = 0;

            while (true) {

                if (n == 1) {
                    break;
                }
                if ((n % 2) == 0)
                {
                    resul = n / 2;
                    n = resul;

                }
                else {
                    resul = (n * 3) + 1;                    
                    n = resul;
                }

                data.Add(n);                
            }

            return data;
        }

Step Two:

We call the method in our main class.

static void Main(string[] args)
        {
            
            Console.Write("N: ");
            int r = int.Parse(Console.ReadLine());
            List<int> result = Collazt(r);
            Console.WriteLine("Lista:");
            Console.WriteLine("[");
            for (int i= 0; i<result.Count; i++) {
                Console.Write(result[i]+"\n");
            }
            Console.WriteLine("]");
        }
1
Captain Unknown On
        string restart;
        do
        {
        Console.WriteLine("Type a Whole Number");
        double n = Convert.ToDouble(Console.ReadLine());

        do
        {double a = n;

    if (n % 2 == 0)
        {
            Console.WriteLine("Even");
            n = a / 2;
            Console.WriteLine(n);
        }
        else
        {
            Console.WriteLine("Odd");
            n = (3*a) + 1;
            Console.WriteLine(n);
        }
        }
        while (n != 1);
        Console.WriteLine("Yo Wanna Restart? Type y and press enter");
        restart = Console.ReadLine();
        Console.Clear();
        }
        while (restart == "y");



        Console.ReadKey(true);

(not a professional programmer, made it for fun, i know there are better ways)