Informing the IBM Community

Everyone needs a hobby – Maths on IBM i

0
(0)



First of all, credit to Simon Hutchinson @ RPGPGM.com and the article ‘Calculating prime numbers in RPG’ for reminding me of this.

8 years ago, when I was first learning RPG (and had slightly more hair than I do now, not sure if those two factors are related!) I decided to test some of what I’d learned by writing a program for the Collatz Conjecture.

According to Wikipedia:

The Collatz conjecture is a conjecture in mathematics that concerns a sequence defined as follows: start with any positive integer n. Then each term is obtained from the previous term as follows: if the previous term is even, the next term is one half of the previous term. If the previous term is odd, the next term is 3 times the previous term plus 1. The conjecture is that no matter what value of n, the sequence will always reach 1.

Personally, I prefer the xkcd definition:

The Collatz Conjecture states that if you pick a number, and if it’s even divide it by two and if it’s odd multiply it by three and add one, and you repeat this procedure long enough, eventually your friends will stop calling to see if you want to hang out.

(un)fortunately I can’t find the original source despite digging through my old system saves, was written when I was learning RPG III so I imagine it would look atrocious.

The basic loop of the RPG IV version that I could find:

C                   Move(P)   P#Input       WK#Result  

C                   Dou       Output = 1                                                         

C                   Eval      InputNo = WK#Result      

C                   If        %REM(WK#Result:2) = 1
C                   Eval      Output = ((WK#Result*3)+1)
C                   Else                               
C                   Eval      Output = (WK#Result/2)   
C                   EndIf                               
C                   Eval      WK#Result = Output                                      

C                   Eval      OutputNo = OutPut        
C                   Eval      Counter = Counter + 1   
C                   Eval      StepNo = Counter         

C                   Write     CALCR                                                     

C                   EndDo                               

So, take a number and check does it have a remainder when you /2? Thus, you know if it’s odd (in which case * 3 + 1) or even (in which case /2). Write to a workfile (CL in front setting it up not shown here) and repeat until you hit 1. InputNo/OutputNo/StepNo are my fields on the workfile.

Given that I like to think I’ve learned more since then, it seems a perfect time to update into a slightly more modern style. First off let’s convert it to free-format:

        WK#Result = %dec(P#Input:10:0);

        DOU Output = 1;

          InputNo = WK#Result;

          IF %REM(WK#Result:2) = 1;
            Output = ((WK#Result*3)+1);
          ELSE;
            Output = (WK#Result/2);
          ENDIF;

          WK#Result = Output;

          OutputNo = OutPut;
          StepNo = Counter;
          Counter = Counter + 1;

          WRITE CALCR;

        ENDDO;

That looks a little nicer (yes, I’m lazy so the input is character for ease of typing on the command line.)

However, given that I’ve been playing with nodejs recently I wonder what it would look like there? I also fancy actually outputting my results on a screen rather than a file that I then query.

function collatzcalc(){

    // Start off by getting input value

    var StartValue = document.getElementById(“Start”).value;
    var Steps = 0;
    var resultstext = “”;

    // Test if we’ve been given a number, if not then no point doing anything else
    if (isNaN(StartValue) || StartValue == ”) {
        document.getElementById(“results”).value = “Not a number”;
    }

    else {
    // Actual processing of calculation
    // No point processing if we’ve been given < 1 as a value
        if (StartValue >= 1)
        {
            var Conjecture = function(value,callback)
            {
                var outvalue = 0;
                var remain = value % 2;
                if (remain != 0) {
                    var outvalue = (value * 3) + 1;
                    return callback(outvalue);
                }
                else {
                    var outvalue = value / 2;
                    return callback(outvalue);
                }
            }

            do {
                Steps ++;
                Conjecture(StartValue,function(outvalue){
                    resultstext += “Step Number: ” + Steps + “, results in value: ” + outvalue + “\n”;
                    StartValue = outvalue;
                });
            }
            while (StartValue != 1);
            document.getElementById(“results”).value = resultstext;
        }
        // We’ve been given a number < 1 so cannot process
        else {
            document.getElementById(“results”).value = “No processing, invalid start number”;
        }
    }
}

Ignoring the fact that I’m god awful at UI design this works quite nicely:

The main thing I might want to improve upon is the validation (would be nice to take the isNaN out and check it before we get here, maybe the >= 1 as well) and maybe add in an option to download to CSV (I’m sure I have a Scott Klement example kicking around somewhere….)

I wonder what other languages I’ll convert it to in the future, and/or if anyone has any suggestions for improvement. Do you have any pet programs you come back to when you’re learning a language / want to practise a new trick?



How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *