OCaml : Infinite Loop - while-loop

I am trying to do this simple while loop but it's not working. The compiler is not giving any type of error or warning but when i try to run my function it ends up in an infinite loop:
let example x =
let k = ref x in
while (!k > 42) do
if ( (!k mod 5) == 0) then (
k:= !k/2
);
done;
if(!k<42) then (
Printf.printf "k is less than 42"
);
if(!k == 42) then (
Printf.printf "k is equal to 42"
)
;;

Well, your loop only modifies !k when !k mod 5 = 0. If !k isn't divisible by 5, it will never change in value. This suggests that the loop will either run 0 times or will run an infinite number of times.
You don't show any calls to example, but any call where you pass a value > 42 and not a multiple of 5 should loop infinitely it seems to me.
By the way, this is what #user2864740 was trying to point out. 43 is a value > 42 that's not divisible by 5.
(As a side comment, you should use = to compare values for equality. The == operator in OCaml is useful in limited cases. This often causes problems for people coming from other languages.)

Related

Raku pop() order of execution

Isn't order of execution generally from left to right in Raku?
my #a = my #b = [9 , 3];
say (#a[1] - #a[0]) == (#b[1] R- #b[0]); # False {as expected}
say (#a.pop() - #a.pop()) == (#b.pop() R- #b.pop()); # True {Huh?!?}
This is what I get in Rakudo(tm) v2020.12 and 2021.07.
The first 2 lines make sense, but the third I can not fathom.
It is.
But you should realize that the minus infix operator is just a subroutine under the hood, taking 2 parameters that are evaluated left to right. So when you're saying:
$a - $b
you are in fact calling the infix:<-> sub:
infix:<->($a,$b);
The R meta-operator basically creates a wrap around the infix:<-> sub that reverses the arguments:
my &infix:<R->($a,$b) = &infix:<->.wrap: -> $a, $b { nextwith $b, $a }
So, if you do a:
$a R- $b
you are in fact doing a:
infix:<R->($a,$b)
which is then basically a:
infix:<->($b,$a)
Note that in the call to infix:<R-> in your example, $a become 3, and $b becomes 9 because the order of the arguments is processed left to right. This then calls infix:<->(3,9), producing the -6 value that you would also get without the R.
It may be a little counter-intuitive, but I consider this behaviour as correct. Although the documentation could probably use some additional explanation on this behaviour.
Let me emulate what I assumed was happening in line 3 of my code prefaced with #a is the same as #b is 9, 3 (big number then little number)
(#a.pop() - #a.pop()) == (#b.pop() R- #b.pop())
(3 - 9) == (3 R- 9)
( -6 ) == ( 6 )
False
...That was my expectation. But what raku seems to be doing is
(#a.pop() - #a.pop()) == (#b.pop() R- #b.pop())
#R meta-op swaps 1st `#b.pop()` with 2nd `#b.pop()`
(#a.pop() - #a.pop()) == (#b.pop() - #b.pop())
(3 - 9) == (3 - 9)
( -6 ) == ( -6 )
True
The R in R- swaps functions first, then calls the for values. Since they are the same function, the R in R- has no practical effect.
Side Note: In fuctional programming a 'pure' function will return the same value every time you call it with the same parameters. But pop is not 'pure'. Every call can produce different results. It needs to be used with care.
The R meta op not only reverses the operator, it will also reverse the order in which the operands will be evaluated.
sub term:<a> { say 'a'; '3' }
sub term:<b> { say 'b'; '9' }
say a ~ b;
a
b
ab
Note that a happened first.
If we use R, then b happens first instead.
say a R~ b;
b
a
ba
The problem is that in your code all of the pop calls are getting their data from the same source.
my #data = < a b a b >;
sub term:<l> { my $v = #data.shift; say "l=$v"; return $v }
sub term:<r> { my $v = #data.shift; say "r=$v"; return $v }
say l ~ r;
l=a
r=b
ab
say l R~ r;
r=a
l=b
ab
A way to get around that is to use the reduce meta operator with a list
[-](#a.pop, #a.pop) == [R-](#a.pop, #a.pop)
Or in some other way make sure the pop operations happen in the order you expect.
You could also just use the values directly from the array without using pop.
[-]( #a[0,1] ) == [R-]( #a[2,3] )
Let me emulate what happens by writing the logic one way for #a then manually reversing the operands for #b instead of using R:
my #a = my #b = [9 , 3];
sub apop { #a.pop }
sub bpop { #b.pop }
say apop - apop; # -6
say bpop - bpop; # -6 (operands *manually* reversed)
This not only appeals to my sense of intuition about what's going on, I'm thus far confused why you were confused and why Liz has said "It may be a little counter-intuitive" and you've said it is plain unintuitive!

Determining when to stop a possibly infinite iteration?

As a beginner programmer, a common problem I encounter is when to stop an iteration. For example, if I were to program a function to determine if an integer was happy or not (by brute-force ), when would I stop? Another example, concerning something like the Mandelbrot set, how would I know to stop an iteration and firmly say that a number diverges or converges? Does it depend on the problem you're dealing with, or is there a method to do things like this?
Brute-force method you have to find your base case to terminate your program as in case of recursion. For Happy Prime number the base case is finding loop in your iteration.
Code
# sum of square of digit of n
def numSquareSum(n):
squareSum = 0
while(n):
squareSum += (n % 10) * (n % 10)
n = int(n / 10)
return squareSum
#method return true if n is Happy Number
def isHappyNumber(n):
li = []
while (1):
n = numSquareSum(n)
if (n == 1):
return True
if (n in li):
return False
li.append(n)
# Main Code
n = 7;
if (isHappyNumber(n)):
print(n , "is a Happy number")
else:
print(n , "is not a Happy number")
Hope this will be helpful.
I believe what you are describing is the Halting Problem. The main takeaway to Halting Problem is that computers cannot solve every problem. One of which being detecting generic infinite loops. It depends on the specific problem you are trying to solve, whether there is a solution to detecting infinite loops.
If you have anymore questions please refer to Wiki on the Halting Problem
In NASA's The Power of 10: Rules for Developing Safety-Critical Code there is a rule "All loops must have fixed bounds. This prevents runaway code."
In this trivial example this would be:
# sum of square of digit of n
def numSquareSum(n):
count = 0
squareSum = 0
while(n):
squareSum += (n % 10) * (n % 10)
n = int(n / 10)
count += 1
if count > 100000000:
raise Exception('loop bound exceeded')
return squareSum

OCaml Syntax Error fixed by double semicolon

I'm sorry for asking such a basic question here, but I'm getting a syntax error when trying to compile the following code,
let sum_of_squares_of_two_largest x y z =
let a :: b :: _ = List.sort (fun x y -> -(compare x y)) [x; y; z] in
a * a + b * b;
let rec factorial n =
if n = 0 then 1 else n * factorial (n - 1);
let e_term n = 1.0 /. float_of_int (factorial n);
let rec e_approximation n =
if n = 0 then (e_term 0) else (e_term n) +. (e_approximation (n - 1));
let rec is_even x = if x = 0 then true else is_odd (x - 1);
and is_odd x = not (is_even x);
let rec f_rec n =
if n < 3 then n else f_rec(n - 1) + 2 * f_rec(n - 2) + 3 * f_rec(n - 3);
The uninformative compiler tells me there is syntax error on line 19, which is the last line of the file.
File "source.ml", line 19, characters 0-0:
Error: Syntax error
That is, line 19 is a blank line, only with a new-line character.
I can "fix" this syntax error by adding ;; at the end of each function definition instead of the ;.
Am I missing a semicolon somewhere?
As has been pointed out in the comments, ; is not a statement terminator like in many other (Algol-inspired) languages, but a sequence operator. It takes two values, throws away the first (but warns if it is not unit) and returns the second. a; b is therefore roughly equivalent to let _ = a in b.
You say you would have expected the error to say something like ';' is missing the second operand., but the thing is: it doesn't. Not until it reaches the end of the file (at which point the error message certainly could have been more intelligent, but probably not very accurate anyway).
What follows each ; in your code looks like a perfectly valid expression that might yield a value. For example, if let rec factorial n = ...; had been let rec factorial n = ... in 2 The value of the expression would have been 2. The problem here, from the compiler's point of view, is that it runs out of file before the expression is finished.
As you've also found out, ;; actually is a statement terminator. Or perhaps a toplevel definition terminator is a better term (I don't know if it even has an official name). It's used in the REPL to terminate input, but isn't needed in normal OCaml code unless you mix toplevel definitions and expressions, which you never should.
;; can still be useful for beginners as a "bulkhead", however. If you put just one ;; in place of a ; in the middle of your file, you'll find the compiler now points the error location there. That's because ;; terminates the definition without the preceding expression being complete. So you now know there's an error before that. (Actually in the preceding expression, but since your entire file is one single expression, "before that" is really the best we can do).

Loop is not doing what expected

I'm studying Obj-C and now I'm not understand why my loop isn't work how it should. I know a way i could achieve result with single while loop, but i want to do this through do while and can't figure out whats going wrong.
What i want is, to show integer called triangularNumber for integers 5,10,15.. and so on. There is what i've tried:
for (int i=1; i<51; i++){
int triangularNumber;
do {
triangularNumber = i * (i+1)/2;
NSLog(#"Trianglular number is %i", triangularNumber);
}
while (i%5 == 0);
}
It produce odd results:
1) Condition of i%5==0 is not met, it output 1,3,6,10 then infinite numbers of 15
2) It create an infinite loop
Please tell me, what is wrong in that code and how to fix it. Thanks!
Instead of do while loop within for loop, use if to check whether a number is divisible by 5 or not.
If you want to do it with do while loop, you could do the following:
int i = 5;
int triangularNumber;
do {
triangularNumber = i * (i+1)/2;
NSLog(#"Trianglular number is %i", triangularNumber);
i += 5;
} while (i < 51);
Reason your code is not working:
Within your do while loop, if i say is 5, then you will end up running in infinite loop as you will satisfy your do while loop's condition which is i%5==0
You just need numbers like 5, 10, 15.. so it's just matter of one loop. Now loop starts with 1 till 50, and you are picky in the sense you just need one element of 5, hence to be picky you could use if condition which says print if and only if my i is multiple of 5.
Do while will always enter into loop and will execute it once. So for 1 it will enter and do calculation for triangularNumber as 1 * 2 /2 = 1 and hence your output 1 and checks condition post printing is 1 divisible by 5, no then it comes out and increments i to 2 and follows same routine as above.

Looping until multiple conditions reached in Objective-C

So i am trying to create a program that can find a number that can be divided by numbers 1-20. I know that i will have to use the following simple code concepts:
I know how loops work and how to create a loop that runs until a condition is met. Is there a simple was to run a loop until several conditions are met?
while ( condition1 && condition2 && condition3... ) {}
or
for ( int i = 0; i < n && condition1 && condition2... ) {}
Obviously these will loop while the conditions are true, not until the conditions are met. Its a simple change in the logic though to get the result you want
EDIT
Ane example of the kind of loop youre looking for could be like:
int number = ...;//initialized somewhere, this is what we're checking
BOOL divisible = YES;
for ( int i = 1; i <= 20 && divisible; ++i )
{
if ( (number % i) != 0 )
divisible = NO;//not divisible by i
}
Good answers in play, but I think it's good to mention the break operator in this discussion. Any loop, at any time, can be terminated using this operator. This can be helpful if you do not know all of the parameters which might go out-of-bounds, and you want to have a way of breaking the loop for reasons you may not have explicitly anticipated (i.e. perhaps your connection to a resource is no longer available...)
NSError *error = nil;
while(true) {
// run your app
if(error) {
break;
}
}
If a number is divisible by all numbers from 1 to 20 then it is divisible by the LCM of 1 to 20 so divisibility test is if(!(n%232792560)).
Further if m = pq | n then p|n, q|n so to explicitly test you only need to check for divisibility by primes. i.e if the number is not even then there is no need to check for divisibility by 4, 6, 8, 10, 12, 14, 16, 18 or 20. This reduces the test to the number being congruent to the 8th primorial = 9699690
OK, perhaps on second reading not as explicit as I should like: the expanded test looks like (by de Morgan's theorem)
if(!(n%19 || n%17 || n%16 || n%13 || n%11 || n%9 || n%7 || n%5))
// number is divisible by 1..20