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) ;;
Related
I want to prove a property parameterized over a finite number of cases. I would like to divide the problem to one instance per case and solve each instance separately. Here is an example to clear up things:
module Minimal
open FStar.List
open FStar.Tactics
open FStar.Reflection.Data
unfold let lst = [0;1]
unfold let prop i =
match i with
| 0 -> i == 0
| 1 -> i == 1
| _ -> False
val propHolds (i:int) : Lemma (requires (List.mem i lst)) (ensures (prop i))
In this case the cases are defined by the list lst.
I can easily prove propHolds:
let propHolds i =
assert_by_tactic (prop 0) (fun () -> norm[delta;primops;iota;zeta]; dump "normalized"; trivial ());
assert_by_tactic (prop 1) (fun () -> norm[delta;primops;iota;zeta]; dump "normalized"; trivial ())
but I obviously don't want to write a separate assert_by_tactic for each case (not when there may be thousands..).
I somehow want to generate the proof above automatically for all elements in lst.
I tried various things, here is one of them:
assert_by_tactic (let rec props i =
if i = 0 then prop 0
else (prop i) /\ (props (i-1))
in
props 1) (fun () -> norm[delta;primops;iota;zeta]; dump "normalized")
Unfortunately, this doesn't quite achieve what I would like, the assert_by_tactic fails (and is not reduced in the way I would expect). I think I am missing something obvious about normalization, but what is the canonical way to do this in F*? Bonus points if the solution points to the "case"/assertion that failed if there exists one.
F*'s type system only ensures weak normalization of terms. Well-typed open terms can diverge, e.g., when reduced in an inconsistent context. To guard against this, the F* normalizer employs various heuristics and, by default, conservatively refuses to reduce recursive calls in the bodies of unreduced matches. This is what prevents List.mem from reducing fully to a cascade of unreduced if/then/else's (if/then/else is just sugar for a match on a Boolean).
List.memP, a related function from F*'s standard library is more reduction friendly in this case, since it does not block on unreduced matches internally. Note, List.memP need not always be more reduction friendly than List.mem---the latter is Boolean, so it can in some cases compute more (e.g., List.mem 3 [1;2;3] will reduce just fine to true);
Try this program:
module Minimal
open FStar.Tactics
let lst = [0;1;2;3;4;5;6;7;8;9;10]
let prop i =
match i with
| 0 -> i == 0
| 1 -> i == 1
| 2 -> i == 2
| 3 -> i == 3
| 4 -> i == 4
| 5 -> i == 5
| 6 -> i == 6
| 7 -> i == 7
| 8 -> i == 8
| 9 -> i == 9
| 10 -> i == 10
| _ -> False
let propHolds (i:int) =
assert (List.memP i lst ==> prop i)
by (dump "A";
norm [delta_only [`%List.memP; `%lst]; iota; zeta; simplify];
dump "B")
At dump B, you'll see the hypothesis reduced to a nested disjunction. Z3 can prove the goal easily from there.
Here's another way to do it, this time without tactics.
let trigger_norm (a:Type)
: Lemma
(requires a)
(ensures (Pervasives.norm [delta_only [`%List.memP; `%lst]; iota; zeta; simplify] a))
= ()
let propHolds (i:int)
: Lemma
(requires List.memP i lst)
(ensures prop i)
= trigger_norm (List.memP i lst)
Now, in response to jebus' comment below, you can go further and prove the postcondition using a tactic, although, the SMT solver is really pretty fast at doing this … so I wouldn't use a tactic for this unless you had some specific strong reason for doing so.
Here's one more solution:
module SO
open FStar.Tactics
let lst = [0;1;2;3;4;5;6;7;8;9;10]
let pred i =
match i with
| 0 -> i == 0
| 1 -> i == 1
| 2 -> i == 2
| 3 -> i == 3
| 4 -> i == 4
| 5 -> i == 5
| 6 -> i == 6
| 7 -> i == 7
| 8 -> i == 8
| 9 -> i == 9
| 10 -> i == 10
| _ -> False
let case_impl (a b c:Type)
: Lemma
(requires (a ==> c) /\ (b ==> c))
(ensures (a \/ b) ==> c)
= ()
let solve_pred_impl () : Tac unit =
let eq = implies_intro () in
rewrite eq;
norm [delta_only [`%pred]; iota];
trivial()
let test i =
assert (List.memP i lst ==> pred i)
by (norm [delta_only [`%List.memP; `%lst]; iota; zeta; simplify];
let _ = repeat
(fun () ->
mapply (`case_impl);
split();
solve_pred_impl()) in
solve_pred_impl())
I'm trying to understand the following code to declare a function:
let string_of_int = function
| 0 -> "zero"
| 1 -> "one"
| 2 -> "two"
| _ -> "many"
which is the same as
let string_of_int2 x = match x with
|0 -> "zero"
|1 -> "one"
| 2-> "two"
_ -> "many
I understand The second way of declaring the function with is trying to match the input x with several possibilities that it could be. But I don't understand the first way to do it. What does function keyword do?
Also,
what does 'a'..'z' do in the following code?
let is_capital = function
| 'a'..'z' -> false
| 'A'..'Z' -> true
|_ -> failwith "Not a valid letter"
Why can't I have a function like this:
let examplefunc = function
|"string"-> Printf.printf "a string"
|3 -> Printf.print "an integer"
|true-> Printf.printf "a boolean"
|- -> Printf.printf "whatever"
The function keyword is a variant of fun that takes in account that the behavior of the function often directly depends on the value of the argument. For instance, if we start with the following definition of the factorial function:
For a positive integer n, n! is 1 if n = 0, and n * (n-1)! otherwise
then the natural translation to OCaml is
let factorial = function
| 0 (* if n = 0 *) -> 1
| n (* otherwise *) -> n * factorial (n-1)
like you said this strictly equivalent to
let factorial = fun n -> match n with
| 0 (* if n = 0 *) -> 1
| n (* otherwise *) -> n * factorial (n-1)
but when the argument of the function is immediately deconstructed in a pattern matching, it may be more readable to use function directly.
Concerning '0'..'9', those are range pattern that matches all characters (i.e '0'|'1'|'2'|'3'|'4'|..| '9' between the lower and upper bounds (included) of the range (following the ascii ordering of characters)
let is_digit = function '0'..'9' -> true | _ -> false
is_digit '0' (* returns true *);;
is_digit 'a' (* returns false *);;
new to Ocaml. I've no clue what is happening here and I've been trying to solve this for maybe 2 hours.
Here is the code:
let hailstorm n =
match n with
| (mod n 2 == 0) -> (n/2)
| (mod n 2 == 1) -> (3*n+1);;
When I try to compile it says:
File "./x.ml", line 3, characters 11-12:Error: Syntax error: ')' expected
File "./x.ml", line 3, characters 6-7:
Error: This '(' might be unmatched
The keyword mod is a binary operator (like lsl, lsr, asr, land, lor, lxor and or) . For instance,
let zero = 2 mod 2
Binary operator can be transformed into standard function by wrapping them around parentheses,
let zero = (mod) 2 2
this is why the parser is expecting a closing parenthesis after (mod .
Then, you pattern matching is wrong because n mod 2 == 0 is an expression, not a pattern (and you should use structural equality = rather than physical equality ==):
let f n = match n mod 2 with
| 0 -> ...
| _ -> ...
or
let f n = match n mod 2 = 0 with
| true -> ...
| false -> ...
which is probably simpler with an if ... then ... else ... .
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.
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)