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)
Related
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]
I just looking for a little advice, how to rewrite code using tail recursion
open Core.Std;;
let rec dig x =
match x with
| 0 -> []
| _ -> x :: dig (x - 1)
;;
let () =
let numbers = dig 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
Any advice will be helpful
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (x::s)
f x []
Is this what you want? It's using tail recursion.
Edit:
for a decreasing seq, just replace (x::s) with (List.append s [x]) or (s # [x]) but it's NOT a good idea,and List.rev is better:
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (s # [x])
f x []
let dig x =
let rec f s z =
if z = x then s
else f (z::s) (z+1)
in
f [] 0
not sure if this floats your boat: You may have to tweak the border cases depending if you want 0 or the starting number included.
If you don't want to use List.rev after building the list backwards (which in my opinion is perfectly fine), nor starting your recursion with 0 instead of n, you can use some kind of continuation:
let dig2 x =
let rec aux x kont =
match x with
| 0 -> kont
| _ -> aux (x-1) (fun l -> kont (x::l))
in
aux x (fun l -> l) [];;
Basically each step returns a function that, given the list built by the remaining steps, will append x to it. We start the recursion with the identity function since we don't have anything to build yet. Then, when we exit from the recursion, we thus just have to apply the empty list to the obtained function.
Well, it seems to can have multiple solutions
open Core.Std;;
let rec digtail ?(l=[]) x =
match x with
| 0 -> l
| _ -> digtail ~l: (l # [x]) (x - 1)
;;
let () =
let numbers = digtail 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
Thanks to all, you helped a lot.
I am new to ocaml and trying to write some code to generate all lists of number between two value.
For example, if I call this function generate, I want to obtain something like this :
let generate ~min ~max ~length (* Maybe other arguments *) =
(* The code *)
;;
generate ~min:0 ~max:3 ~length:4;;
Should return
[
[0;0;0];
[1;0;0];
[2;0;0];
[3;0;0];
[0;1;0];
And so on, to
[3;2;3];
[0;3;3];
[1;3;3];
[2;3;3];
[3;3;3];
]
I already tried code like this :
open Core.Std;;
type next_list =
| Complete of int list
| Partial of int list
| Result of (int array) list
;;
let rec next ~r ~min ~max ~l =
let detox = function | Partial a -> a | _ -> assert false in
match l with
| Partial (hd :: tl) when hd <= max -> Partial (hd + 1 :: tl)
| Partial (hd :: tl) when hd = max + 1 -> next ~r ~min ~max
~l:(Partial (min :: (detox (next ~r ~min ~max ~l:(Partial tl))) ))
| Complete (hd :: tl) when hd <= max -> next ~r:([l] :: r) ~min ~max
~l:(Complete (hd + 1 :: tl))
| Complete (hd :: tl) when hd = max + 1 -> next ~r ~min ~max
~l:(Complete (min :: (detox (next ~r ~min ~max ~l:(Partial tl)))))
(*| Partial [] -> next ~r ~min ~max ~l:(Result r)*)
| Result a -> Result a
It may be spread around several functions if necessary, that is not a problem.
I am also interested by non ocaml code or idea.
Thanks for your help.
This is my first question on Stackoverflow, do not hesitate to say if my question is unclear.
here some solution :
First, let's define that takes 2 lists l1 & l2 as input and that produces a list of list, where each element is l2 augmented by 1 element of l1 :
let enumerate l ll = List.fold ~init:[] ~f:(fun op x -> (x::ll)::op) l;;
enumerate [0;1;2;3] [4;5;6];;
- : int list list = [[3; 4; 5; 6]; [2; 4; 5; 6]; [1; 4; 5; 6]; [0; 4; 5; 6]]
Now generate :
let rec generate length ll =
if length=1 then List.fold ~init:[] ~f:(fun op x -> [x]::op) ll
else
let result = generate (length-1) ll in
List.fold ~init:[] ~f:(fun op x -> (enumerate ll x)#op) result;;
and usage is as follows :
generate 2 [1;2;3];; (* instead of generate ~min:1 ~max:3 ~length:2 *)
Some explanation :
List.fold ~init:[] ~f:(fun op x -> [x]::op) ll
=> this creates the initial list of list (singleton)
And the second : takes each of the list of length -1 and performs the enumeration.
Here's a hint:
let count_prefix low high lists =
???
let generate min max length =
let rec recur low high len =
if len = 0 then []
else count_prefix low high (recur low high (len - 1)) in
recur min max length
count_prefix should return a list that is the elements of lists prefixed with the numbers low to high. If lists is empty, it should return a list of lists containing the numbers low to high. That is:
count_prefix 0 3 [] => [[0]; [1]; [2]]
count_prefix 0 3 [[10];[20]] => [[0; 10]; [0; 20]; [1; 10]; [1; 20]; [2; 10]; [2; 20]]
Fill in the definition of count_prefix.
I want to write a function rotate n l that returns a new list containing the same elements as l, "rotated" n times to the right. For example,
rotate 0 [1;2;3;4] should return [1;2;3;4]
rotate 1 [1;2;3;4] should return [4;1;2;3]
rotate 2 [1;2;3;4] should return [3;4;1;2]
rotate 3 [1;2;3;4] should return [2;3;4;1]
rotate 4 [1;2;3;4] should return [1;2;3;4]
etc.
The behavior of rotate n for n less than 0 should be the same as for n equal to 0.
I want to write this without using the list concatenation operator # from Pervasives.
Update: Here is the rotation function I wrote:
let rot1 l =
let rec iterate acc = function
[] -> []
| [x] -> x :: List.rev acc
| x :: l -> iterate (x :: acc) l
in
iterate [] l;;
But I want it to do the same thing without using List.rev.
Is there a way to do this?
Agree with Jeffrey, show us what you tried. Here's a small hint in case you need to get started. If you can write a function that performs only 1 rotation i.e. equivalent to rotate 1 l. (I call it one_rot). Then rotate can be easily defined as:
let rec rotate n l =
match n with
| 0 -> l
| _ -> rotate (n-1) (one_rot l)
Your solution is perfectly fine for me. Not sure what you have against List.rev but here's a completely stand alone one_rot. Note that we have to sacrifice tail recursion. You could probably make this quite a bit shorter too:
let rec last = function
| [] -> assert false
| [x] -> x
| x::xs -> last xs
let rec init = function
| [] -> []
| [x] -> []
| x::xs -> x::(init xs)
let one_rot l = (last l)::(init l)
This problem can be solved by combining these 3 functions:
cat(skip(list, places), take(list, places))
The implementation looks like:
let rec cat = function
([], y) -> y
| (x::xs, y) -> x :: cat (xs, y)
let rec skip = function
([], _) -> []
| (_::xs as xs1, c) -> if c > 0 then skip(xs, c - 1) else xs1
let rec take = function
([], _) -> []
| (x::xs, c) -> if c > 0 then x :: take(xs, c - 1) else []
let cycle l i =
cat (skip (l, i), take (l, i))
cycle ([1;2;3;4;5;6], 3);;
val it : int list = [4; 5; 6; 1; 2; 3]
E.g. if you have a function (fun x -> x+1) and you want to map it to [1; 2; 3]. But you only want to map it when x=1, so that the output is [2; 2; 3]. How do you do this?
Using OCaml, I tried:
let rec foo (input : int list) : int list =
match input with
| [] -> []
| hd::tl -> List.map (fun x -> if x=1 then (x+1)) input;;
And I've tried 'when' statements, but to no avail.
An else branch is missing here.
You're almost there. You just need to make a complete if/else statement:
if x=1 then (x+1) else x
OCaml requires a return value on any branch of above expression.
To be clear, when guard is irrelevant here because it is used for conditional pattern matching. Since pattern matching is redundant in this case, your function could be shortened quite a lot:
let foo input =
List.map (fun x -> if x=1 then x+1 else x) input
You can actually use a when statement, even if I prefer #pad's solution:
let foo (input : int list) : int list =
let rec aux acc input =
match input with
[] -> List.rev acc
| x :: xs when x = 1 -> aux ((x + 1) :: acc) xs
| x :: xs -> aux (x :: acc) xs
in
aux [] input