How would I go about traversing a list in SMLNJ. I have been at this for 3 hours now and I cannot figure it out for the life of me.
So just to traverse and print a list out. In the simplest way [5,2,3] would print out 5 2 3 or a list variant of this.
How would I go about traversing a list in SMLNJ
It depends on the type of traversal you want to do: mapping, folding, iterating.
Using recursion:
(* mapping: *)
fun incr_each_by_1 [] = []
| incr_each_by_1 (x::xs) = x + 1 :: incr_each_by_1 xs
val demo_1 = incr_each_by_1 [5,2,3] (* [6,3,4] *)
(* folding: *)
fun sum_all_together [] = 0
| sum_all_together (x::xs) = x + sum_all_together xs
val demo_2 = sum [5,2,3] (* 10 *)
(* iteration: *)
fun print_each [] = ()
| print_each (x::xs) = ( print (Int.toString x ^ "\n") ; print_each xs )
val demo_3 = print_each [5,2,3] (* no result, but side-effect *)
Using higher-order functions:
val demo_1 = List.map (fn x => x + 1) [5,2,3]
val demo_2 = List.foldl (fn (x, result) => x + result) 0 [5,2,3]
val demo_3 = List.app (fn x => Int.toString x ^ "\n") [5,2,3]
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 am attempting to create a function in OCaml that gives the "k-average" of consecutive elements in a list. For example:
average 4 [1; 2; 3; 4; 5; 6] = [2; 3; 4]
since the average of 1, 2, 3, 4 is 2, of 2, 3, 4, 5 is 3, and of 3, 4, 5, 6 is 4.
I have created a function that averages the list, but with every 2 elements:
let rec average2 xs = match xs with
| [] -> []
| x :: [] -> [x]
| x :: x' :: xs -> if xs = [] then [(x + x') / 2] else [(x + x') / 2] #
(average2 (x'::xs))
How can I modify this to allow me to average k-elements?
What you should do is just verify that the list has the proper length and then two recursive functions will do it easily :
let average n l =
if List.length l < n then failwith "List is too small"
else
(* this function computes one k-average and returns the result *)
let rec aux2 acc i = function
| hd :: tl when i < n -> aux2 (acc + hd) (i + 1) tl
| _ -> acc / n
in
let rec aux acc l = match l with
(* the resulting list is reversed *)
| [] -> List.rev acc
| _ :: tl ->
(* Get the k-average of the k first elements of the list *)
let avgn = aux2 0 0 l in
(* if the rest of the list is too small, we reached the
end for sure, end *)
if List.length tl < n then List.rev (avgn :: acc)
(* recursive call on the rest of the list (without the head) *)
else aux (avgn :: acc) tl
in aux [] l
I'm trying to write a function that takes in a list, and returns the number of successive duplicate elements in the list.
For example, given [1;2;3;3;4;4;5], the function should return 2
This is my initial implementation, but unfortunately it always returns 0. I'm not quite sure where the bug lies.
Any help on how to improve it will be highly appreciated.
let rec count_successive_duplicates (lst: int list) (count: int) : (int) =
match lst with
| [] | [_]-> 0
| x :: y :: tl ->
if x = y then count_successive_duplicates (y::tl) (count + 1) else count_successive_duplicates (y::tl) count
;;
let () =
print_int (count_successive_duplicates [1;2;3;3;4;4;5] 0)
In the end, you'll want to return the accumulator with the count instead of 0 always:
let rec count_successive_duplicates (lst: int list) (count: int) : (int) =
match lst with
| [] | [_] -> count
(* ^^^^^ */)
| x :: y :: tl -> count_successive_duplicates (y::tl) (count + if x = y then 1 else 0)
Seems I was doing something silly by always returning 0 for the base case, instead of the computed count. The previous version was just ignoring the computed count it received. This now works:
let rec count_successive_duplicates lst count : (int) = match lst with
| [] | [_]-> count
| x :: y :: tl ->
if x = y then count_successive_duplicates (y::tl) (count + 1) else count_successive_duplicates (y::tl) count
;;
let () =
print_int (count_successive_duplicates [1;2;3;3;4;4;5] 0)
I want to go through an array and return a list of ints (the value of indexes) when a value in the array matches true.
The array is a boolean array of just true/false values.
let get_elements (i:int)(b:bool) : int =
if b = true then (i::l)
else (())
;;
let rec true_list (b: bool array) : int list =
(fun i l -> get_elements i l)
;;
The syntax is wrong for my code and I am confused on exactly how to return a list of ints.I only want to return the indexes of those elements that are true in the array.
You refer to 'l' in get_elements, but it's not in the scope of that function.
Here's an approach using a ref to an integer list (a mutable list):
boolarray = [|true; false; true; false; false; true|] ;;
type ilist = (int list) ref ;;
let intlist () : ilist = ref [] ;;
let push ( l: ilist) (x: int) : unit = l := x::(!l) ;;
let lst = intlist () ;;
Array.iteri ( fun i b -> if b = true then (push lst i )) boolarray ;;
!lst ;; (* => int list = [5; 2; 0] *)
Or, if you'd rather avoid refs (which is usually a good idea) this is cleaner:
let get_true_list (b: bool array) : int list =
let rec aux i lst =
if (i = Array.length b) then lst else
(if b.(i) = true then ( aux (i+1) (i::lst)) else (aux (i+1) lst)) in
aux 0 [] ;;
(* using boolarray defined above *)
get_true_list boolarray ;; (* => int list = [5; 2; 0] *)
I present an example which does not use state, avoids the 'if then else' construct making it easier to read and verify.
let mylist = [| true; false; false; true; false; true |] in
let get_true_indexes arr =
let a = Array.to_list arr in
let rec aux lst i acc = match lst with
| [] -> List.rev acc
| h::t when h = true -> aux t (i+1) (i::acc)
| h::t -> aux t (i+1) acc
in
aux a 0 []
in
get_true_indexes mylist
One more question about most elegant and simple implementation of element combinations in F#.
It should return all combinations of input elements (either List or Sequence).
First argument is number of elements in a combination.
For example:
comb 2 [1;2;2;3];;
[[1;2]; [1;2]; [1;3]; [2;2]; [2;3]; [2;3]]
One less concise and more faster solution than ssp:
let rec comb n l =
match n, l with
| 0, _ -> [[]]
| _, [] -> []
| k, (x::xs) -> List.map ((#) [x]) (comb (k-1) xs) # comb k xs
let rec comb n l =
match (n,l) with
| (0,_) -> [[]]
| (_,[]) -> []
| (n,x::xs) ->
let useX = List.map (fun l -> x::l) (comb (n-1) xs)
let noX = comb n xs
useX # noX
There is more consise version of KVB's answer:
let rec comb n l =
match (n,l) with
| (0,_) -> [[]]
| (_,[]) -> []
| (n,x::xs) ->
List.flatten [(List.map (fun l -> x::l) (comb (n-1) xs)); (comb n xs)]
The accepted answer is gorgeous and quickly understandable if you are familiar with tree recursion. Since elegance was sought, opening this long dormant thread seems somewhat unnecessary.
However, a simpler solution was asked for. Iterative algorithms sometimes seem simpler to me. Furthermore, performance was mentioned as an indicator of quality, and iterative processes are sometimes faster than recursive ones.
The following code is tail recursive and generates an iterative process. It requires a third of the amount of time to compute combinations of size 12 from a list of 24 elements.
let combinations size aList =
let rec pairHeadAndTail acc bList =
match bList with
| [] -> acc
| x::xs -> pairHeadAndTail (List.Cons ((x,xs),acc)) xs
let remainderAfter = aList |> pairHeadAndTail [] |> Map.ofList
let rec comboIter n acc =
match n with
| 0 -> acc
| _ ->
acc
|> List.fold (fun acc alreadyChosenElems ->
match alreadyChosenElems with
| [] -> aList //Nothing chosen yet, therefore everything remains.
| lastChoice::_ -> remainderAfter.[lastChoice]
|> List.fold (fun acc elem ->
List.Cons (List.Cons (elem,alreadyChosenElems),acc)
) acc
) []
|> comboIter (n-1)
comboIter size [[]]
The idea that permits an iterative process is to pre-compute a map of the last chosen element to a list of the remaining available elements. This map is stored in remainderAfter.
The code is not concise, nor does it conform to lyrical meter and rhyme.
A naive implementation using sequence expression. Personally I often feel sequence expressions are easier to follow than other more dense functions.
let combinations (k : int) (xs : 'a list) : ('a list) seq =
let rec loop (k : int) (xs : 'a list) : ('a list) seq = seq {
match xs with
| [] -> ()
| xs when k = 1 -> for x in xs do yield [x]
| x::xs ->
let k' = k - 1
for ys in loop k' xs do
yield x :: ys
yield! loop k xs }
loop k xs
|> Seq.filter (List.length >> (=)k)
Method taken from Discrete Mathematics and Its Applications.
The result returns an ordered list of combinations stored in arrays.
And the index is 1-based.
let permutationA (currentSeq: int []) (n:int) (r:int): Unit =
let mutable i = r
while currentSeq.[i - 1] = n - r + i do
i <- (i - 1)
currentSeq.[i - 1] <- currentSeq.[i - 1] + 1
for j = i + 1 to r do
currentSeq.[j - 1] <- currentSeq.[i - 1] + j - i
()
let permutationNum (n:int) (r:int): int [] list =
if n >= r then
let endSeq = [|(n-r+1) .. n|]
let currentSeq: int [] = [|1 .. r|]
let mutable resultSet: int [] list = [Array.copy currentSeq];
while currentSeq <> endSeq do
permutationA currentSeq n r
resultSet <- (Array.copy currentSeq) :: resultSet
resultSet
else
[]
This solution is simple and helper function costs constant memory.
My solution is less concise, less effective (altho, no direct recursion used) but it trully returns all combinations (currently only pairs, need to extend filterOut so it can return a tuple of two lists, will do little later).
let comb lst =
let combHelper el lst =
lst |> List.map (fun lstEl -> el::[lstEl])
let filterOut el lst =
lst |> List.filter (fun lstEl -> lstEl <> el)
lst |> List.map (fun lstEl -> combHelper lstEl (filterOut lstEl lst)) |> List.concat
comb [1;2;3;4] will return:
[[1; 2]; [1; 3]; [1; 4]; [2; 1]; [2; 3]; [2; 4]; [3; 1]; [3; 2]; [3; 4]; [4; 1]; [4; 2]; [4; 3]]
Ok, just tail combinations little different approach (without using of library function)
let rec comb n lst =
let rec findChoices = function
| h::t -> (h,t) :: [ for (x,l) in findChoices t -> (x,l) ]
| [] -> []
[ if n=0 then yield [] else
for (e,r) in findChoices lst do
for o in comb (n-1) r do yield e::o ]