Checking for matching parenthesis - sml

I am trying to write a code such that, given a list of parenthesis, I will check if the order is valid or not.
For simpleness, the follwoing datatype is defined.
datatype par = LPAR | RPAR
type pList = par list
What I have until now is:
fun valid(nil:plist): bool = true
| valid([Lpar]) = false
| valid([Rpar]) = false
| valid([Lrap,Rpar) = true
| valid(L::L1) =
For instance, "(()()"--> [Lpar,Lpar,Rpar,Lpar,Rpar] will return false
You can see that the parenthesis is in string format. I am confused since I will have to check to two things: that the left ( are equal to the left ) and that each ( matches a ). If so then I will need to make some helper functions.
Can you please provide me with information about what my helper functions should be or a better implementation of this?
ty

I have found out a way to solve my problem by counting the parenthesis. The logic goes like this:
I start from 0, if i find a left p I add 1, other wise I minus 1. Once I enter -1 i return false right away since I cannot have a right p come first. Then I recurse. If the final output is 0, the its true since this means that every left p matches a right p.
Q.E.D

I didn't try this in the repl but it should look something like this
fun valid_paren xs : bool =
fun aux (xs, ctr) = case xs of
[] => ctr = 0
| (x:xs') => case x of
'(' => aux (xs', ctr+1)
')' => aux (xs', ctr-1)
_ => aux (xs', ctr)
in
aux (xs, 0)

Related

How do you see if adjacent elements repeat in a list? (SML)

SML is a challenging language for me to learn. I'm trying to find a way to screen an undetermined list and return a boolean based on whether two elements adjacent on a list are the same value or not. What I've tried and think is close to correct is below.
fun repeatE nil = false
| repeatE (first::last) = first = last orelse repeatsE(last);
Obviously, this results in an error. I based my answer on this code, which tells me if a value is an element in the list.
fun member (e, nil) = false
| member (e, first::last) = e = first orelse member(e, last);
Why does the first one not work, but the last one does? It tells me that the operator and the operand don't agree, and maybe I'm thick-headed, but I don't quite understand why they don't?
Thank you in advance!
first=last tries to compare the first element of a list with the tail of that list, and you can only compare things of the same (comparable) type.
The working code works because it doesn't try to compare a list element to an entire list.
You need to compare the first element to the second element, and you need to handle the case of a singleton list.
Something like this:
fun repeats nil = false
| repeats (first::rest) = case rest of
(x::xs) => first = x orelse repeats rest
| _ => false
or
fun repeats nil = false
| repeats (first::rest) = not (null rest)
andalso (first = (hd rest) orelse repeats rest)
It's actually possible to use as to clean up #molbdnilo's answer a fair bit.
Ask yourself: An empty list is false, but so is a list with a single element, right?
fun repeats([]) = false
| repeats([_]) = false
Now, we need to match a list with at least two elements, and compare those. If they're not equal, we'll check everything but the first element.
fun repeats([]) = false
| repeats([_]) = false
| repeats(a::b::tail) =
a = b orelse repeats(b::tail)
But we don't need to use b::tail.
fun repeats([]) = false
| repeats([_]) = false
| repeats(a::(tail as b::_)) =
a = b orelse repeats(tail)
If we want, we can recognize that the empty list and the single element list are just the "other" when the last pattern doesn't match, and we'll rewrite it to reflect that.
fun repeats(a::(tail as b::_)) =
a = b orelse repeats(tail)
| repeats(_) = false

A typical bracket balanced problem in ocaml

I'm trying to create a function which returns a boolean value to see if the string is balanced. But the result is just not what I expect. Can someone point out what I did wrong?
For example:
false = is_balanced")("
false = is_balanced "(a)b)"
true = is_balanced "fo"
true = is_balanced "a(b(c)d)e"
let rec list_car ch = match ch with
| "" -> []
| ch -> (String.get ch 0 ) :: (list_car (String.sub ch 1 ( (String.length ch)-1) ) ) ;;
let is_balanced klm =
let brk = list_car klm in
let rec left = function
| x::xs, 0 ->
if x = ')' then false
else left (xs, 0)
| x::xs, level ->
if x = '(' then left (xs, succ level)
else if x = ')' then left (xs, pred level)
else left (xs, level)
| [], level -> if level = 0 then true else false
in
left (brk, 0) ;;
But I got the following results:
is_balanced "(((";;
- : bool = true
is_balanced "()";;
- : bool = false
Exploding a string into a list of char by using String.sub is inefficient and unnecessary. Your code can be rewritten as
let is_balanced s =
let rec count pos level =
if (* termination condition *) ... then level = 0
else match s.[pos] with
| '(' -> ...
| ')' -> ...
| _ -> ...
in
count 0 0
With this variant, your mistake should disappear by itself.
Indeed one possible root issue with your previous code is that you are matching on both the list of chars and the level and end up mixing the logic of the termination condition with the logic of the level counting.
In particular, should the level at position n influence the effect of characters on the level at the position n+1?
Presented as an alternative, this is a good opportunity to gain experience with folds. They work well in any situation where you are iterating over something one element at a time and need to evaluate that element in conjunction with an initial state to generate a new value.
The state we'll keep track of is the nesting level. It'll start out as 0. Each iteration, if it's less than 0, the nesting is obviously unbalanced. No further elements from the string will balance the parens, so we'll simply propagate this value to the end of the fold, resulting in a false return.
Otherwise we'll increment or decrement the levels as we encounter open and close parens. Or take no action for non-paren characters.
let balanced str =
let f level ch =
if level < 0 then
level
else
match ch with
| '(' -> level + 1
| ')' -> level - 1
| _ -> level
in
String.fold_left f 0 str = 0
# balanced ")(";;
- : bool = false
# balanced "(a)b)";;
- : bool = false
# balanced "fo";;
- : bool = true
# balanced "a(b(c)d)e";;
- : bool = true
Consider how this operates on "(a)b)":
balanced "(a)b)"
String.fold_left f 0 "(a)b)"
String.fold_left f 1 "a)b)"
String.fold_left f 1 ")b)"
String.fold_left f 0 "b)"
String.fold_left f 0 ")"
String.fold_left f -1 ""
-1
-1 = 0
false
If we look at "a(b(c)d)e":
balanced "a(b(c)d)e"
String.fold_left f 0 "a(b(c)d)e"
String.fold_left f 0 "(b(c)d)e"
String.fold_left f 1 "b(c)d)e"
String.fold_left f 1 "(c)d)e"
String.fold_left f 2 "c)d)e"
String.fold_left f 2 ")d)e"
String.fold_left f 1 "d)e"
String.fold_left f 1 ")e"
String.fold_left f 0 "e"
String.fold_left f 0 ""
0
0 = 0
true
The propagation of the negative level value can be seen if we test "())hello()":
balanced "())hello()"
String.fold_left f 0 "())hello()"
String.fold_left f 1 "))hello()"
String.fold_left f 0 ")hello()"
String.fold_left f -1 "hello()"
String.fold_left f -1 "ello()"
String.fold_left f -1 "llo()"
String.fold_left f -1 "lo()"
String.fold_left f -1 "o()"
String.fold_left f -1 "()"
String.fold_left f -1 ")"
String.fold_left f -1 ""
-1
-1 = 0
false
One note about this approach: it does not short circuit. A string that starts with ) will clearly result in false but the entire string will need to be iterated over.
One way around this would be to have our locally scoped f function raise an exception on level being negative, and then to handle this exception by returning false.
exception Unbalanced_parens
let balanced str =
let f level ch =
if level < 0 then
raise Unbalanced_parens
else
match ch with
| '(' -> level + 1
| ')' -> level - 1
| _ -> level
in
match String.fold_left f 0 str with
| 0 -> true
| _ | exception Unbalanced_parens -> false
Now, if we test "())hello()":
balanced "())hello()"
String.fold_left f 0 "())hello()"
String.fold_left f 1 "))hello()"
String.fold_left f 0 ")hello()"
String.fold_left f -1 "hello()"
raise Unbalanced_parens
false
I believe the problem is with this line:
|x::xs,0-> if x =')'then false else left(xs,0)
Here, if x is not ), the character is simply ignored. Hence, if it is instead (, level will not be incremented.
The quick fix is to instead match the character directly:
| ')'::xs, 0 -> false
But I fully agree with #octachron's advice, and that the problem would have been avoided by not mixing list iteration and level counting.
Also, note that you can use when to attach a condition to a branch. For example, if you match on just the list, you could instead do:
| ')'::xs when level = 0 -> false
And you could also do
| ')'::xs when level < 0 -> false
which is unnecessary in this case, but serves to demonstrate a case that cannot be covered by pattern matching on level directly.
When learning to program, it's important not only to learn programming techniques (such as algorithms) and programming languages, but also tools.
You're confronted with a problem: you've written some code that takes some input and returns the wrong input, but you don't understand why. There are two main approaches to this kind of problem:
Break down the code into smaller pieces, and test them separately, until you find one (or more) that doesn't return the outputs you wanted.
Use debugging tools to look at what's happening inside the program.
Here you can test list_car independently and see that it's not the source of the problem. There's not much you can do to break down is_balanced, but you can take out left and make it a top-level function.
let rec left = function
| x::xs, 0 ->
if x = ')' then false
else left (xs, 0)
| x::xs, level ->
if x = '(' then left (xs, succ level)
else if x = ')' then left (xs, pred level)
else left (xs, level)
| [], level -> if level = 0 then true else false
;;
let is_balanced klm =
let brk = list_car klm in
left (brk, 0) ;;
That's not going to help directly, because the problem is inside left and it's all one thing that can't really be broken down into smaller pieces. However, making left a toplevel function allows you to use a simple debugging tool: tracing in the toplevel. (A function doesn't have to be at the top level to debug it, but it does to use the toplevel's simple tracing function.)
# #trace left;;
left is now traced.
# is_balanced "()";;
left <-- (['('; ')'], 0)
left <-- ([')'], 0)
left --> false
left --> false
Now you can see where the code is going wrong: the second call to left is made with the level 0, but it should be 1 since the previous call opened a parenthesis. So the problem is that left (['('; ')'], 0) is passing the wrong level value when it makes its recursive call.
| x::xs, 0 ->
if x = ')' then false
else left (xs, 0)
^
Now that you've located the problem, the correction should be obvious: in the recursive call, you need to remember the number of opening parentheses somehow — that's what level is for. So level here should be 1, not 0.
let rec left = function
| x::xs, 0 ->
if x = ')' then false
else left (xs, 1)
| x::xs, level ->
if x = '(' then left (xs, succ level)
else if x = ')' then left (xs, pred level)
else left (xs, level)
| [], level -> if level = 0 then true else false
;;
let is_balanced klm =
let brk = list_car klm in
left (brk, 0) ;;
(Remember that in the toplevel, after redefining left, you need to redefine is_balanced as well, even if its textual definition hasn't changed: the old definition refers to the old definition of left.)
I think is_balanced is now correct for inputs that consists solely of parentheses. It doesn't properly ignore other characters, but I'll let you debug that on your own. It may help to write the code in a simpler way, taking advantage of the fact that you can match on the first element of the list, on the level, or both. For example, the incorrect case above was actually unnecessary: you could have made the first case
| ')'::xs, 0 -> false
and the second case already handles lists starting with ( correctly: when the first character is (, the logic is the same regardless of the value of the level.
Now I fixed mt code,and it works!Thanks a lot for the tipps
let rec list_car ch = match ch with
  | "" -> []
  | ch -> (String.get ch 0 ) :: (list_car (String.sub ch 1 ( (String.length ch)-1) ) )  ;;
let is_balanced klm =
  let brk = list_car klm in
  let rec left = function
    |')'::xs,level ->
    if level >0 then left(xs,pred level) else false
    | '('::xs,level ->left(xs,succ level)
    | _::xs, level -> left (xs, level)
    |[],level ->if level =0 then true else false
  in
  left (brk, 0) ;;

Why do i get syntax error at end problem with pattern matching

I have to make a function that takes list a list and returns list of pairs of first and last element,2nd and 2nd last and so forth It doesn't matter if the list has even or odd number of elements because if its odd i will just ignore the middle element.The idea i have is that make a new rec fun that takes old list and its revers as input i think i finished the code but i get Syntax error for ;;
let lip l =
if [] then []
else let l1=l l2=List.rev l in
let rec lp l1 l2 = match l1,l2 with
| [],[] ->[]
| [],h2::t2->[]
| h1::_,h2::_ ->
if (List.length l -2) >= 0 then [(h1,h2)]# lp(List.tl l1) t2
else [] ;;
There are quite a few errors in your code.
I think the specific error you're seeing is caused by the fact that there is no in after let rec lp ....
Every let that's not at the top level of a module needs to be followed by in. One way to think of it is that it's a way of declaring a local variable for use in the expression that appears after in. But you need to have the in expr.
Another way to look at it is that you're defining a function named lp but you're not calling it anywhere.
As #lambda.xy.x points out, you can't say if [] then ... because [] isn't of type bool. And you can't say let x = e1 y = e2 in .... The correct form for this is let x = e1 in let y = e2 in ...
(Or you can write let x, y = e1, e2 in ..., which looks nicer for defining two similar variables to two similar values.)
The following code should at least compile:
let lip list1 =
if list1 = [] then []
else
let list2=List.rev list1 in
let rec lp l1 l2 = match l1,l2 with
| [], [] ->[]
| [], _::_->[]
| h1::_::_, h2::t2 -> (* l1 length >= 2*)
(h1,h2) :: lp(List.tl l1) t2
| h1::_,h2::t2 -> (* l1 length = 1 *)
[]
in
[]
I have made the following changes:
renamed the arguments of lip to make clear they are different from the arguments of lp
removed the alias let l1 = l
changed the if condition to a term of type boolean -- there's not much to compare, so I assume you are checking list1
replaced the list length condition by a pattern match against two heads
the else path is the second match - it might be better to rewrite that one to | [h1, _] -> ...
the definition of lp needs to be followed with the actual body of lip - to make it compile, we just return [] at the moment but you probably would like something else there
As #Jeffrey Scofield already mentioned, you are not using lp in your code. It could help if you added a comment that explains what you'd like to achieve and what the intended role of lp is.

how to check if list has consecutive powers

I am new to ruby and working on a problem but I don't know how to figure it out.
I want to write a function that return true if each consecutive element is a power of the previous element, otherwise return false
for example: if I have a list [2;4;8;16] the function should return true
function should return false , [3; 7; 9;]
let consec_ele element = match element with
[] -> true
h::t ->
if h > t then false
else
if t/h = 0 && t mod h = 0 then true
;;
i just can't figure out how to make it work and that so recursively.
Well, you first need to formalise your problem :
if my list is empty, then true
if my list is not, then it starts with a number n
if n = 1, then I need to start again because a^0 = 1 for all a
if n > 0 then I call a new function check on the rest of the list, tl, acting like this :
if tl is empty, then true
else tl starts with n' then if n' = n * n then I call check recursively on the rest and I need to keep the fact that I'm now checking for n * n * n ...
If n <= 0 then false
In OCaml this would be
let consec_ele l =
let rec cer b = function
| [] -> true
| n :: tl ->
if n <= 0 then false
(* We can start again for the first 1 we see, but if our
* list is [1; 1; 1; ...; 1] then we need to stop
* That's why we have this boolean b which is true and once
* we see 1 as the head of our list we swap it to false
*)
else if n = 1 then b && cer false tl
else
let rec check p = function
| [] -> true
| n' :: tl -> n' = pow n p && check (p + 1) tl
in check 1 tl
in cer true l;;
(For the pow function, I let you write it ;-) Of course, this can be bad because you could have an overflow, maybe you'd prefer to see if n' ^ (1/p) = n (the pth root of n' (why don't we have LaTeX mathmode on stackoverflow ? :-())
Being able to pattern-match on the first two elements in a list makes this trivial. Obviously an empty list is true, and a list with one element is also true. Otherwise, if we consider the first two elements, if the second is a power of the first, the function is true, and we can discard the first and consider the rest of the list recursively. Otherwise, the result is clearly false.
let rec consec_ele =
function
| [] | [_] -> true
| a::(b::_ as tl) when is_power_of a b -> consec_ele tl
| _ -> false
As a note, your test case of [2;4;8;16] should actually return false as 8 is a multiple, but not a power of 4.

SML - Get Indices of List

I'm working on a program that appends either a '+' or '-' to an element of a list, depending on whether the index of that element is odd or even (i.e an alternating sums list).
However, I'm having trouble identifying what the index of each element is. I have code that I believe should append the correct symbol, using if statements and mod
fun alternating([]) = 0
| alternating(l) =
if List.nth(l,hd(l)) mod 2 == 0 then '+'#hd(l)#alternating(tl(l))
else '-'#hd(l)#alternating(tl(l))
However, List.nth(l,hd(l)) always returns the element at the second index, not the first.
On the off chance that you really just want to negate integers them so you can pass them into some kind of summation, I would just negate the argument if it's odd. Using mutual recursion one can do it without any explicit index bookkeeping:
fun alternate l =
let
fun alternate1 [] = []
| alternate1 (x::xs) = (~x) :: alternate2 xs
and alternate2 [] = []
| alternate2 (x::xs) = x :: alternate1 xs
in
alternate1 l
end
It works like so:
- alternate [1,2,3,4];
val it = [~1,2,~3,4] : int list
I would strongly encourage you to use pattern matching instead of hd.
Edit discussing hd
As a rule of thumb, if you need hd you probably need tl as well. hd is a partial function--it's going to throw Empty if your list is empty. If you pattern match, you conveniently get variables for the head and tail of the list right there, and you get a visual reminder that you need to handle the empty list. It's more aesthetically pleasing, IMO, to see:
fun foo [] = ...
| foo (x::xs) = ...
than the equivalent
fun foo l =
if null l
then ...
else (hd l) ... (tl l)
In other words, you get shorter, cleaner code with an automatic reminder to make it correct. Win/win. To my knowledge there's no significant advantage to doing it the other way. Of course, you may find yourself in a situation where you know the list will have at least one element and you don't need to do anything else. You still have to consider the cases you're given, but it's a good rule of thumb.
If you want to decorate your list with an index you could try something like the following
fun add_index l =
let
fun add_index_helper (nil, _) = nil
| add_index_helper (h::tl,i) = (h,i) :: add_index_helper (tl,1+i)
in
add_index_helper (l,0)
end
val x = add_index [0,1,4,9,16,25]
but you can also just directly compute parity with the same method
fun add_sign l =
let
fun add_sign_helper (nil, _) = nil
| add_sign_helper (h::tl,i) = (h,i) :: add_sign_helper (tl,1-i)
in
add_sign_helper (l,0)
end
val y = add_sign [0,1,4,9,16,25]
then you can map the parity to a string
fun sign_to_char (x,0) = (x,"+")
| sign_to_char (x,_) = (x,"-")
val z = List.map sign_to_char y
or you can just add the sign directly
fun add_char l =
let
fun add_char_helper (nil, _) = nil
| add_char_helper (h::tl,0) = (h,"+") :: add_char_helper (tl,1)
| add_char_helper (h::tl,_) = (h,"-") :: add_char_helper (tl,0)
in
add_char_helper (l,0)
end
val zz = add_char [0,1,4,9,16,25]
Alternatively if you had a string list and you wanted to add chars you could try something like this
fun signs L =
let
datatype parity = even | odd
fun signs_helper ( nil ,_) = nil
| signs_helper (x::xs,even) = ("+" ^ x) :: signs_helper(xs,odd)
| signs_helper (x::xs,odd) = ("-" ^ x) :: signs_helper(xs,even)
in
signs_helper (L,even)
end
val z = signs ["x","2y","3z","4"]
(* this gives you val z = ["+x","-2y","+3z","-4"] : string list *)