Stuck in an infinite loop in a function - functional-programming

I'm stuck in an infinite loop in this function:
let rec showGoatDoorSupport(userChoice, otherGuess, aGame) =
if( (userChoice != otherGuess) && (List.nth aGame otherGuess == "goat") ) then otherGuess
else showGoatDoorSupport(userChoice, (Random.int 3), aGame);;
And here's how I'm calling the function:
showGoatDoorSupport(1, 2, ["goat"; "goat"; "car"]);
In the first condition in the function, I compare the first 2 input parameters (1 and 2) if the are different, and if the item in the list at index "otherGuess" is not equal to "goat", I want to return that otherGuess.
Otherwise, I want to run the function again with a random number between 0-2 as the second input parameter.
The point is to keep trying to run the function until the second parameter doesnt equal the first, and that slot in the List isn't "goat", then return that slot number.

Don't use ==, it checks for physical equality. Use =. Two different strings will never be physically equal, even if they contain the same sequence of characters. (This is necessary, because strings are mutable in OCaml.)
$ ocaml
OCaml version 4.00.0
# "abc" == "abc";;
- : bool = false
# "abc" = "abc";;
- : bool = true

Another to do that is to use the String.compare. An example:
if String.compare str1 str2 = 0 then (* case equal *)
else (* case not equal *)

Related

sum function in Julia is giving error if the array is empty

I am trying to create a code which identifies if the elements in an array are monotonic or not.
I wrote the below code and got the error -
function isMonotonic(array)
if length(array) <= 2
return true
end
check_up = []
check_down = []
for i in range(2, length(array))
if array[i] <= array[i-1]
append!(check_up, 1)
end
if array[i] >= array[i - 1]
append!(check_down, 1)
end
end
if sum(check_up) == length(array) - 1 || sum(check_down) == length(array) - 1
return true
else
return false
end
end
isMonotonic([1, 2, 3, 4, 5, 6 , 7])
I am getting the below error
Error: Methoderror: no method matching zero(::Type{Any})
I think it is because I am trying to sum up the empth array, I want to understand how to overcome this problem in general, I have a solution for the above code, but in genral I want to know the reason and how to use it. I do not want to first check if the array is empty or not and then do the sum.
If you wanted to save yourself lots of effort, the simplest solution would just be:
my_ismonotonic(x) = issorted(x) || issorted(x ; rev=true)
This will return true if x is sorted either forwards, or in reverse, and false otherwise.
We could maybe make it a little more efficient using a check so we only need a single call to issorted.
function my_ismonotonic(x)
length(x) <= 2 && return true
for n = 2:length(x)
if x[n] > x[1]
return issorted(x)
elseif x[n] < x[1]
return issorted(x ; rev=true)
end
end
return true
end
# Alternatively, a neater version using findfirst
function my_ismonotonic(x)
length(x) <= 2 && return true
ii = findfirst(a -> a != x[1], x)
isnothing(ii) && return true # All elements in x are equal
if x[ii] > x[1]
return issorted(x)
else
return issorted(x ; rev=true)
end
end
The loop detects the first occurrence of an element greater than or less than the first element and then calls the appropriate issorted as soon as this occurs. If all elements in the array are equal then the loop runs over the whole array and returns true.
There are a few problems of efficiency in your approach, but the reason you are getting an actual error message is because given the input, either this expression sum(check_up) or this expression sum(check_down) will effectively result in the following call:
sum(Any[])
There is no obvious return value for this since the array could have any type, so instead you get an error. If you had used the following earlier in your function:
check_up = Int[]
check_down = Int[]
then you shouldn't have the same problem, because:
julia> sum(Int[])
0
Note also that append! is usually for appending a vector to a vector. If you just want to add a single element to a vector use push!.

Tracing a recursive function for longest common substring

I am getting confused tracing the following recursive approach to find the longest common substring. The last two lines are where my confusion is. Specifically how is the count variable getting the answer when characters of both string matches? In the last line which "count" does this refer to i.e count in the function definition or the updated count from function call? Are there any resources for better understanding of recursions?
int recursive_substr(string a, string b, int m, int n,int count){
if (m == -1 || n == -1) return count;
if (a[m] == b[n]) {
count = recursive_substr(a,b,m-1,n-1,++count);
}
return max(count,max(recursive_substr(a,b,m,n-1,0),recursive_substr(a,b,m-1,n,0)));
}
The first thing to understand is what values to use for the parameters the very first time you call the function.
Consider the two following strings:
std::string a = "helloabc";
std::string b = "hello!abc";
To figure out the length of the longest common substring, you can call the function this way:
int length = recursive_substr(a, b, a.length()-1, b.length()-1, 0);
So, m begins as the index of the last character in a, and n begins as the index of the last character in b. count begins as 0.
During execution, m represents the index of the current character in a, n represents the index of the current character in b, and count represents the length of the current common substring.
Now imagine we're in the middle of the execution, with m=4 and n=5 and count=3.
We're there:
a= "helloabc"
^m
b="hello!abc" count=3
^n
We just saw the common substring "abc", which has length 3, and that is why count=3. Now, we notice that a[m] == 'o' != '!' == b[n]. So, we know that we can't extend the common substring "abc" into a longer common substring. We make a note that we have found a common substring of length 3, and we start looking for another common substring between "hello" and "hello!". Since 'o' and '!' are different, we know that we should exclude at least one of the two. But we don't know which one. So, we make two recursive calls:
count1 = recursive_substr(a,b,m,n-1,0); // length of longest common substring between "hello" and "hello"
count2 = recursive_substr(a,b,m-1,n,0); // length of longest common substring between "hell" and "hello!"
Then, we return the maximum of the three lengths we've collected:
the length count==3 of the previous common substring "abc" we had found;
the length count1==5 of the longest common substring between "hello" and "hello";
the length count2==4 of the longest common substring between "hell" and "hello!".

How to convert ints to strings in SML recursively?

I made a very small program which takes an int and converts it into string in SML:
fun int2str i =
if i < 0 then "~" ^ Int.toString (~i)
else Int.toString i;
int2str(~1234) --> "~1234"
int2str(1234) --> "1234"
I have been struggling immensely to accomplish this in a recursive way. Any help? Additionally, I had to take a string and convert it into an int which I finished through stackOverflow help in general, but the '~' screws everything up as well; however this was able to be finished recursively.
I'm not entirely sure why you need to do this recursively since calling Int.toString on any int will produce the desired result (even if it's negative) but you can also do:
fun helper 0 = "" | helper n = helper (Int.div(n, 10)) ^ Int.toString (Int.mod (n, 10));
fun int2str n = if n < 0 then "~" ^ helper(~n) else if n = 0 then "0" else helper(n);
Modding by 10 will get the last digit and integer dividing by 10 will cut off the last digit so this should get you your desired results in a recursive manner.

Return a list of even numbers from a list of integer pairs in sml

I have the following question "Given a list of integer pairs, write a function to return a list of even numbers in that list in sml".
this is what I've achieved so far
val x = [(6, 2), (3, 4), (5, 6), (7, 8), (9, 10)];
fun isEven(num : int) =
if num mod 2 = 0 then num else 0;
fun evenNumbers(list : (int * int) list) =
if null list then [] else
if isEven(#1 (hd list)) <> 0
then if isEven(#2 (hd list)) <> 0
then #1 (hd list) :: #1 (hd list) :: evenNumbers(tl list)
else []
else if isEven(#2 (hd list)) <> 0
then #1 (hd list) :: evenNumbers(tl list)
else [];
evenNumbers(x);
the result should be like this [6,2,4,6,8,10]
any help would be appreciated.
I see two obvious problems.
If both the first and second number are even, you do
#1 (hd list) :: #1 (hd list) :: evenNumbers(tl list)
which adds the first number twice and ignores the second.
If the first number is odd and the second even, you do
#1 (hd list) :: evenNumbers(tl list)
which adds the number that you know is odd and ignores the one you know is even.
Programming with selectors and conditionals gets complicated very quickly (as you've noticed).
With pattern matching, you could write
fun evenNumbers [] = []
| evenNumber ((x,y)::xys) = ...
and reduce the risk of using the wrong selector.
However, this still makes for complicated logic, and there is a better way.
Consider the simpler problem of filtering the odd numbers out of a list of numbers, not pairs.
If you transform the input into such a list, you only need to solve that simpler problem (and there's a fair chance that you've already solved something very similar in a previous exercise).
Exercise: implement this transformation. Its type will be ('a * 'a) list -> 'a list.
Also, your isEven is more useful if it produces a truth value (if you ask someone, "is 36 even?", "36" is a very strange answer).
fun isEven x = x mod 2 = 0
Now, evenNumbers can be implemented as "just" a combination of other, more general, functions.
So running your current code,
- evenNumbers [(6, 2), (3, 4), (5, 6), (7, 8), (9, 10)];
val it = [6,6,3,5,7,9] : int list
suggests that you're not catching all even numbers, and that you're catching some odd numbers.
The function isEven sounds very much like you want to have the type int -> bool like so:
fun isEven n =
n mod 2 = 0
Instead of addressing the logic error of your current solution, I would like to propose a syntactically much simpler approach which is to use pattern matching and fewer explicit type annotations. One basis for such a solution could look like:
fun evenNumbers [] = ...
| evenNumbers ((x,y)::pairs) = ...
Using pattern matching is an alternative to if-then-else: the [] pattern is equivalent to if null list ... and the (x,y)::pairs pattern matches when the input list is non-empty (holds at least one element, being (x,y). At the same time, it deconstructs this one element into its parts, x and y. So in the second function body you can express isEven x and isEven y.
As there is a total of four combinations of whether x and y are even or not, this could easily end up with a similarly complicated nest of if-then-else's. For this I might do either one of two things:
Use case-of (and call evenNumbers recursively on pairs):
fun evenNumbers [] = ...
| evenNumbers ((x,y)::pairs) =
case (isEven x, isEven y) of
... => ...
| ... => ...
Flatten the list of pairs into a list of integers and filter it:
fun flatten [] = ...
| flatten ((x,y)::pairs) = ...
val evenNumbers pairs = ...

function which finds a common number in multiple lists

how would this function be completed to return the common integers between two lists?
how would i complete the get_common_elements(list1, list2) function?. The function should select all the common integers from both parameters and displays them in the result.
ie numbers 1 = 3,6,8,9,12,35
numbers 2 = 6,7,13,34, 35
result = 6,35
you can assume that each number only occurs in each list once
def common_member(a, b):
a_set = set(a)
b_set = set(b)
if (a_set & b_set):
print(a_set & b_set)
else:
print("No common elements")

Resources