So I'm working on a function to find some valid arithmetic operations to a target number from an int list. It's not allowed to use throw/callac. Only add and mul are valid arithmetic operations here and they are left associative.
datatype operation = ADD | MULT
(* find_op: int -> int list -> (operatino list -> 'a) -> (unit -> 'a) -> 'a *)
fun find_op x [] s k = k()
| find_op x [y] s k = if x=y then s([]) else k()
| find_op x (y1::y2::ys) s k =
let
val add = find_op x ((y1+y2)::ys) (fn a => s(ADD::a)) k
val mul = find_op x ((y1*y2)::ys) (fn a => s(MULT::a)) k
in
need some work here
end
The function should work like below:
Given list [1,1,2,~1] and target number ~4, the accpeted operation list should be [ADD,ADD,MULT] or [ADD,MULT,MULT], because (((1+1)+2)*~1) = ((1+1)2~1) = ~4. But [MULT,ADD,MULT] will not be valid since (((1*1)+2)*~1) = ~3.
I'm confused how to check whether returned results are k(). Using = to check return value is not possible since it is polymorphic. Is there any method to handle this?
What you have to do is use the two strategies, first try reducing the numbers via ADD, then reduce the numbers via MULT, but sequentially. In order to do this you need to provide a custom failure continuation (k) to the result of the first chosen strategy. If that strategy fails, you try the second strategy in the continuation failure.
You can't try both strategies at the same time and have them both succeed. The function type does not permit returning multiple correct answers. For that you'd need the success continuation's type to be operation list list.
datatype operation = ADD | MULT
fun opToString ADD = "ADD"
| opToString MULT = "MULT"
(* find_op: int -> int list -> (operation list -> 'a) -> (unit -> 'a) -> 'a *)
fun find_op x [] s k = k ()
| find_op x [y] s k = if x = y then s [] else k ()
| find_op x (y1 :: y2 :: ys) s k =
let
(* You need a custom failure continuation that tries the MULT variant
* if the ADD one fails.
*)
fun whenAddFails () =
find_op x ((y1 * y2) :: ys) (fn a => s (MULT :: a)) k
val add =
find_op x ((y1 + y2) :: ys) (fn a => s (ADD :: a)) whenAddFails
in
add
end
fun test () =
let
val opList = [1,1,2,~1]
val target = ~4
fun success ops =
"success: " ^ (String.concatWith " " (List.map opToString ops))
fun failure () =
"couldn't parse numbers as an operation list"
in
find_op target opList success failure
end
Related
I have a list of (string * int) list elements and I need to find the biggest int element and return the corresponding(string * int) element.
I have something like this atm, but problem is, I think my approach is more of "typical programming"
let it = [] in
for x = 0 to length LIST - 1 do
let str = ((List.nth LIST x).string) in
let num = ((List.nth LIST x).int) in
let it = it # [num, str] in
let (str, num) = List.hd(List.rev it) in
[str, num]
What I tried to do is to loop through the list and add the string and int value in another list, then sort them, reverse it and then take the head, which should be the max int, then I need to return the pair in (string * int)
Your code is not a well-formed OCaml code. It highlights, however, some number of issues with your understanding of OCaml.
First of all, by default, values in OCaml are immutable. For example,
let x = 0 in
for i = 0 to 10 do
let x = x + 1 in
print_int x;
done
You will get 11111111111 as the output. This is because, during the loop, you are just computing every time the x+1 expression, where x is always 0 and you will always get 1 as the result. This is because, let x = <expr> in <body> is not changing the existing variable x but is creating a new variable x (shadowing any previous definitions) and make it available in the scope of the <body> expression.
Concerning your problem in general, it should be solved as a recursive function greatest_element, which has the following definition,
for an empty list [] it is undefined;
for a list of one element [x] is it is x;
otherwise, for a list of x::xs it is max x (greatest_element xs),
where max x y is x if it is greater or equal to y.
Finally, it looks like you have missed the first steps in OCaml and before solving this task you have to move back and to learn the basics. In particular, you have to learn how to call functions, bind variables, and in general what are the lexical conventions and syntax of the language. If you need pointers, feel free to ask.
First of all, it doesn't seem that you did any kind of sorting in
the code that you provided.
Assuming that your list is of type
(string * int) list then a possible to find the element with the
maximum integer using recursion:
let max_in_list list =
let rec auxiliary max_str max_int = function
| []
-> (max_str, max_int)
| (crt_str, crt_int)::tail when crt_int > max_int
-> auxiliary crt_str crt_int tail
| _::tail
-> auxiliary max_str max_int tail
in
match list with
| []
-> None
| (fst_str, fst_int)::tail
-> Some (auxiliary fst_str fst_int tail)
let check = max_in_list [("some", 1); ("string", 3); ("values", 2)]
You could write a generic maxBy function. This allows you to get the max of any list -
let rec maxBy f = function
| [] -> None
| [ x ] -> Some x
| x :: xs ->
match (maxBy f xs) with
| Some y when (f y) > (f x) -> Some y
| _ -> Some x
(* val maxBy : ('a -> 'b) -> 'a list -> 'a option = <fun> *)
let data = [("a", 3); ("b", 2); ("c", 6); ("d", 1)]
(* val data : (string * int) list = [("a", 3); ("b", 2); ("c", 6); ("d", 1)]*)
maxBy (fun (_, num) -> num) data
(* - : (string * int) option = Some ("c", 6) *)
maxBy (fun (str, _) -> str) data
(* - : (string * int) option = Some ("d", 1) *)
maxBy (fun x -> x) [3; 2; 6; 1]
(* - : int option = Some 6 *)
maxBy (fun x -> x) ["c"; "d"; "b"; "a"]
(* - : string option = Some "d" *)
maxBy (fun x -> x) []
(* - : 'a option = None *)
It can be fun to rewrite the same function in various ways. Here's another encoding -
let maxBy f list =
let rec loop r = function
| [] -> r
| x::xs when (f x) > (f r) -> loop x xs
| _::xs -> loop r xs
in
match list with
| [] -> None
| x::xs -> Some (loop x xs)
(* val maxBy : ('a -> 'b) -> 'a list -> 'a option = <fun> *)
I'm a beginner in OCaml and algorithms.
I'm trying to get the number of 5 digits numbers with no repeating digits bigger than 12345.
Here is what I did in OCaml, I tried to make as tail recursive as possible, and I also used streams. But still, due to size, it stack overflowed:
type 'a stream = Eos | StrCons of 'a * (unit -> 'a stream)
let rec numberfrom n= StrCons (n, fun ()-> numberfrom (n+1))
let nats = numberfrom 1
let rec listify st n f=
match st with
|Eos ->f []
|StrCons (m, a) ->if n=1 then f [m] else listify (a ()) (n-1) (fun y -> f (m::y))
let rec filter (test: 'a-> bool) (s: 'a stream) : 'a stream=
match s with
|Eos -> Eos
|StrCons(q,w) -> if test q then StrCons(q, fun ()->filter test (w ()))
else filter test (w ())
let rec check_dup l=
match l with
| [] -> false
| h::t->
let x = (List.filter (fun x -> x = h) t) in
if (x == []) then
check_dup t
else
true;;
let digits2 d =
let rec dig acc d =
if d < 10 then d::acc
else dig ((d mod 10)::acc) (d/10) in
dig [] d
let size a=
let rec helper n aa=
match aa with
|Eos-> n
|StrCons (q,w) -> helper (n+1) (w())
in helper 0 a
let result1 = filter (fun x -> x<99999 && x>=12345 && (not (check_dup (digits2 x)))) nats
(* unterminating : size result1 *)
(*StackOverflow: listify result1 10000 (fun x->x) *)
I can't reproduce your reported problem. When I load up your code I see this:
# List.length (listify result1 10000 (fun x -> x));;
- : int = 10000
# List.length (listify result1 26831 (fun x -> x));;
- : int = 26831
It's possible your system is more resource constrained than mine.
Let me just say that the usual way to code a tail recursive function is to build the list up in reverse, then reverse it at the end. That might look something like this:
let listify2 st n =
let rec ilist accum st k =
match st with
| Eos -> List.rev accum
| StrCons (m, a) ->
if k = 1 then List.rev (m :: accum)
else ilist (m :: accum) (a ()) (k - 1)
in
if n = 0 then []
else ilist [] st n
You still have the problem that listify doesn't terminate if you ask for more elements than there are in the stream. It might be better to introduce a method to detect the end of the stream and return Eos at that point. For example, the filter function might accept a function that returns three possible values (the element should be filtered out, the element should not be filtered out, the stream should end).
The problem is that the size of your stream result1 is undefined.
Indeed, nats is an never-ending stream: it never returns Eos.
However, filtering a never-ending stream results in another never-ending stream
since a filtered stream only returns Eos after the underlying stream does so:
let rec filter (test: 'a-> bool) (s: 'a stream) : 'a stream=
match s with
| Eos -> Eos
| StrCons(q,w) -> if test q then StrCons(q, fun ()->filter test (w ()))
else filter test (w ())
Consequently, size result1 is stuck trying to reach the end of integers.
Note also that, in recent version of the standard library, your type stream is called Seq.node.
I am trying to write a simple add function that takes two real lists and adds the matching indices together and generates a real list, but for some reason I can't get it to accept real lists as the parameters, but instead only int lists.
fun add (nil, _) = nil
| add (_, nil) = nil
| add (a :: b, x :: y) = (a + x) :: add (b,y)
When I try running my test input, val addTest = add([1.0, 2.0, 3.0], [0.1, 0.2, 0.3]); it gives me:
Error: operator and operand do not agree [tycon mismatch]
operator domain: int list * int list
operand: real list * real list
And I am just curious as to why SML is defaulting to an int list even though the "+" operand is used for both reals and ints. Shouldn't it be accepting `a list instead of just int lists?
Yes, + (along with other arithmetic operators) is overloaded but not parametrically polymorphic.
So you can do 1.0 + 1.0 and 1 + 1 and they give a real and an int respectively.
But fun f x y = x + y can infer to either, so the compiler defaults to the int overload.
As an addition to your own answer, you can do with a single : real in your code:
fun add ([], _) = []
| add (_, []) = []
| add (x::xs, y::ys) = (x + y : real) :: add (xs, ys)
and it will infer that you must mean real in all the other places, too.
You could generalise this operation into one called zipWith:
- fun zipWith f [] _ = []
| zipWith f _ [] = []
| zipWith f (x::xs) (y::ys) = f (x, y) :: zipWith f xs ys
> val ('a, 'b, 'c) zipWith = fn :
('a * 'b -> 'c) -> 'a list -> 'b list -> 'c list
- val add = zipWith (op + : real * real -> real)
> val add = fn : real list -> real list -> real list
- add [1.0, 2.0, 3.0] [4.0, 5.0, 6.0];
> val it = [5.0, 7.0, 9.0] : real list
I found out that the default behavior for SML in a case like this is to default to int behavior, so if you have an operand that works for either reals or ints it will be evaluated as an int. As for the method above I was able to get my desired behavior by specifying the parameters in the tuple to be real lists like so:
fun add (nil, _) = nil
| add (_, nil) = nil
| add (a::b : real list, x::y : real list) = (a + x) :: add (b,y)
I have a module in one file that contains the type type move = Move of int. In another file, I open this module and can refer to the type by ModuleName1.move. But is it possible to construct an instance of this type in the second file, given that I'd have to use the Move i syntax, and since that Move parameter/keyword isn't really accessible from the second file?
Here's the module where I want to instantiate the type from the first module (which is called Game and contains the type type move = Move of int. It's right at the end, in the next_move function, that I want to construct a (Move 0) and pass it to make_tree, however it doesn't recognize Move since it's a parameterized type constructor from the other module:
#use "sig_player.ml" ;;
#use "game.ml" ;;
module TestAIPlayer =
struct
module PlayerGame = Game
open PlayerGame
let max_depth = 4 ;;
(* Data Definition *)
type tree = Node of PlayerGame.state * PlayerGame.move * tree list ;;
let rec make_tree (root: PlayerGame.state * PlayerGame.move) (d: int): tree =
let (s, m) = root in
let lms = PlayerGame.legal_moves s in
match lms, d with
| [], _ | _, 0 -> Node (s, m, [])
| _, _ -> Node (s, m, (List.map
(fun mv -> make_tree ((PlayerGame.next_state s mv), mv) (d - 1))
lms)) ;;
let compare_node (n1: PlayerGame.move * float) (n2: PlayerGame.move * float)
(comp: 'a -> 'a -> 'a): PlayerGame.move * float =
match n1, n2 with
| (m1, f1), (m2, f2) -> if (comp f1 f2) = f1 then n1 else n2 ;;
let rec minimax (t: tree) (mm: bool): PlayerGame.move * float =
match t with
| Node (s, m, []) -> (m, PlayerGame.estimate_value s)
| Node (s, m, children) -> let propagated = List.map
(fun c -> minimax c (not mm)) children in
(match mm with
| true -> List.fold_right
(fun x y -> compare_node x y max)
propagated (m, neg_infinity)
| false -> List.fold_right
(fun x y -> compare_node x y min)
propagated (m, infinity)) ;;
let next_move s = minimax (make_tree (s, (Move 0)) max_depth) true ;;
end ;;
module AIPlayer = (TestAIPlayer : PLAYER with module PlayerGame := Game) ;;
My task is to remove the duplicates from a list. To do that I have to first sort the list.
I have written the function that sorts the list and the one that remove the
duplicates(once they are sorted) but I don't know how to combine them.
Example:
input: [4;5;2;2;1;3;3]
output: [1;2;3;4;5]
let rec setify = function
| [] -> []
| x :: l -> insert x (setify l)
and insert elem = function
| [] -> [elem]
| x :: l -> if elem < x then elem :: x :: l
else x :: insert elem l;;
let rec rem =function
|[] -> []
| x :: []-> x :: []
| x :: y :: rest -> if x = y then rem (y :: rest)
else x :: rem (y :: rest) ;;
You want to make the function that takes a list, creates the sorted list, and deduplicates that. In other words, you want:
let task list =
let sorted_list = setify list in
rem sorted_list
It is possible to do this in arbitrarily more complicated ways, but the above is one straightforward, one-action-per-line version. Since the phrasing of the title of your question invites it, here is one of the more sophisticated ways:
(* it's possible to write a generic combinator of functions, that takes two functions f and g *)
let combine f g =
(* and returns a function *)
fun x ->
(* that maps x to f(g(x)) *)
f (g x)
(* this function is typed as:
val combine : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>
*)
(* the task can then be expressed as the combination of setify and rem: *)
let task = combine rem setify
Don't use this style unless something is actually gained from it. Most of
the times it only makes programs less readable and slower with no corresponding benefit. *)