Delete elements between two occurrences in list - list

I have to make a function that take a list and return the list but without the elements betweens the occurences.
For example: [1; 2; 3; 4; 2; 7; 14; 21; 7; 5] -> [1; 2; 7; 5]
I imagined that to make this I will take the head of the list, and then see
if there is another occurrence in the tail, so I browse the list and when I found the occurrence, I delete everything between them and I keep just one of them.
First I tried something like this:
let rec remove list = match list with
| [] -> []
| h::t -> if(List.mem h t) then
(*Here I would like to go through the list element by element to
find the occurence and then delete everything between*)
else
remove t
So for the part I don't succeed to do, I made a function which allows to slice a list between two given points, just like so:
let slice list i k =
let rec take n = function
| [] -> []
| h :: t -> if n = 0 then [] else h :: take (n-1) t
in
let rec drop n = function
| [] -> []
| h :: t as l -> if n = 0 then l else drop (n-1) t
in
take (k - i + 1) (drop i list);;
(*Use: slice ["a";"b";"c";"d";"e";"f";"g";"h";"i";"j"] 2 3;;*)
I also have this function that allows me to get the index of points in the list:
let index_of e l =
let rec index_rec i = function
| [] -> raise Not_found
| hd::tl -> if hd = e then i else index_rec (i+1) tl
in
index_rec 0 l ;;
(*Use: index_of 5 [1;2;3;4;5;6] -> return 4*)
But I don't really know how to combine them to get what I expect.

here is what I made :
let rec remove liste =
let rec aux l el = match l with
| [] -> raise Not_found
| x :: xs -> if el = x then try aux xs el with Not_found -> xs
else aux xs el in
match liste with
| [] -> []
| x :: xs -> try let r = x :: aux xs x in remove r with Not_found -> x :: remove xs;;
my aux function return the list which follow the last occurence of el in l. If you have any question or if you need more explanation just ask me in comment

A version that uses an option type to tell if an element appears further on in the list:
let rec find_tail ?(eq = (=)) lst elem =
match lst with
| x :: _ when eq x elem -> Some lst
| _ :: xs -> find_tail ~eq xs elem
| [] -> None
let rec remove ?(eq = (=)) lst =
match lst with
| [x] -> [x]
| x :: xs -> begin
match find_tail ~eq xs x with
| Some tail -> x :: remove ~eq (List.tl tail)
| None -> x :: remove ~eq xs
end
| [] -> []
Also lets you specify a comparison function (Defaulting to =).

Related

OCaml Longest common sequences (deep search)

Write with OCaml Longest Common Sottosequence (Deep Search)
Consider a finite set S of strings and an integer K. Determine, if it exists, a string x of length greater than or equal to K subsequence of each string s∈S. The problem is solved by using an in-depth search.
I tried it with two strings without k, it works!
this bellow is my code:
(*trasfmorm string in list char*)
let explode s =
let rec exp i l =
if i < 0 then l
else exp (i - 1) (s.[i] :: l)
in
exp (String.length s - 1) []
(*print list of strings*)
let rec print_list_strings = function
| [] -> ()
| e::l ->
print_string e;
print_string "\n";
print_list_strings l
(*print list of char*)
let rec print_list_char = function
| [] -> print_string "\n"
| e::l ->
print_char e;
print_string " ";
print_list_char l
(*between the lists tell me which one is longer*)
let longest xs ys =
if List.length xs > List.length ys then xs
else ys
(*lcs deep*)
let rec lcs a b =
match a, b with
| [], _ | _, [] -> []
| x::xs, y::ys ->
if x = y then
x :: lcs xs ys
else
longest (lcs a ys) (lcs xs b)
(*
On input: "ABCBDAB", "ABCBDAB"
The LCS returned is "BDAB"
*)
let a = "ABCBDAB";;
let b = "ABCBDAB";;
let a = explode a;;
let b = explode b;;
print_list_char (lcs a b);;
But when I start to find the solution for s strings it seems impossible.
For the moment i write the code bellow:
(* function return n-elemt of a list *)
exception Nth
let rec nth n lista =
match (n, lista) with
| (_, []) -> raise Nth
| (0, t::_) -> t
| (n, t::c) -> nth (n-1) c;;
(* functione given input list of char output string *)
let rendi_stringa s =
String.of_seq (List.to_seq s)
(* delete first n-element of a string *)
let rec drop n = function
| [] -> []
| x::xs ->
if n <= 0 then x::xs
else drop (n-1) xs ;;
(*string into a char list*)
let explode s =
let rec exp i l =
if i < 0 then l
else exp (i - 1) (s.[i] :: l)
in
exp (String.length s - 1) []
(*read k-elemt and return a list*)
let rec leggi k =
if k=0 then []
else
let x = read_line() in
(x) :: leggi (k-1)
(*print element list*)
let rec print_list = function
| [] -> ()
| e::l ->
print_string e;
print_string "\n";
print_list l
(*funzione lista string esplosa--> lista di lista*)
let rec explode_list n lista =
if n = 0 then []
else
let x = List.hd lista in
[(explode x)] # explode_list (n-1) (List.tl lista)
(*n-esima raw e m-column of matrix*)
let pos tabla n m =
let lista = (List.nth tabla n) in
List.nth lista m;;
let subset tabella n =
let rec aux solution tot = function
| [] ->
if tot > 0 then raise NotFound
else solution
| x::rest ->
print_string x;
print_string "\n";
aux (x::solution) (tot-1) rest
in
aux [] n tabella
let subset tabella n =
let rec aux solution = function
| [] ->
if List.length solution < n then raise NotFound
else solution
| x::rest -> nuova_funzione (explode x) rest n
in
aux [] n tabella
let nuova_funzione lista_char lista_string n = function
| _, [] -> print_string "non posso piu fare niente, stringhe finite\n"
| [], _ -> print_string "ho finito confronto con la lista\n"
| [] , x::lt ->
if (lcs lista_char (explode x)) > n then
else
let longest xs ys =
if List.length xs > List.length ys then xs
else ys
(*lcs profonda*)
let rec lcs a b =
match a, b with
| [], _ | _, [] -> []
| x::xs, y::ys ->
if x = y then
x :: lcs xs ys
else
longest (lcs a ys) (lcs xs b)
(**)
(*let rec lcs stringhe num = function
| []
| List.length stringhe < num -> []
| *)
(*------------------------main--------------*)
print_string "how many strings?\n";;
let m = read_int();;
print_string "please write your strings\n";;
let lista = leggi m;;
print_string "strings wrote\n";;
print_list lista;;
explode (nth 0 c);;
let a = "ABCBDAB";;
let a = explode a;;
let b = "BDCABA";;
let b = explode b;;
let c = "BADACB";;
let c = explode c;;
My idea was to use Backtracking, but i'm stuck with logical idea, I have no idea to implement it even with pseudocode!
Any idea or advise?

replace all the n occurences in a list per a given list - ocaml

example remplace_par_liste 2 [-4;-5] [1;2;3;2;2;9] --> [1;-4;-5;3;-4;-5-4;-5;9]
I know how to do it with an occurence but not with a list.
example remplace 2 0 [1;2;3;2;2;9] --> [1; 0; 3; 0; 0; 9]
let listere = [1;2;3;2;2;9];;
let rec remplace n p liste = match liste with
[] -> []
|a::q -> (if a = n then p else a)::(remplace n p q);;
remplace 2 0 listere;;
- : int list = [1; 0; 3; 0; 0; 9]
And there is the problem, i need another funtion to insert the list l1 in the list ?
let listerel = [1;2;3;2;2;9];;
let l1 = [-4;-5];;
let rec remplace_par_liste n l1 liste = match liste with
[] -> []
(|a::q -> (if a = n then l1 else a)::(remplace_par_liste n l1 q);;)
remplace_par_liste 2 l1 listerel;;
File "", line 4, characters 113-114:
Error: This expression has type int list
but an expression was expected of type int```
I would suggest you define the second function first.
:: will let us add x to the front of the list created by recursively running the function on the tail of the list.
# will let us concatenate two lists so we can insert the values in the substitute list into the result.
let rec replace_value_with_list v sub lst =
match lst with
| [] -> []
| x::xs when x <> v -> x :: replace_value_with_list v sub xs
| x::xs -> sub # replace_value_with_list v sub xs
The first function is then much simpler, being just a specialized application of the second, putting that single value into a list.
let replace_value v sub lst =
replace_value_with_list v [sub] lst
Downsides to this implementation
I have decided to edit to mention this based on the comments. The above is not tail-recursive. Each time a function is called, it takes up a certain amount of stack space. The stack is limited. Recursively call a function or functions too many times and you will get a stack overflow error.
OCaml (and some other programming languages, primarily in the functional vein) offer tail-call optimization. If the compiler can determine that the last thing a function does is call itself or another function, then the space the caller occupies on the stack can be reused.
We can modify the existing function from ealier.
let rec replace_value_with_list v sub lst =
match lst with
| [] -> []
| x::xs when x <> v -> x :: replace_value_with_list v sub xs
| x::xs -> sub # replace_value_with_list v sub xs
This operation, for instance, makes the function non-tail-recursive:
x :: replace_value_with_list v sub xs
First we have to call replace_value_with_list v sub xs and then add x to the front of it. We can solve this issue by passing along an accumulator that builds up the list. We can hide this detail by using a local auxiliary function. Because the local function is taking care of the recursion, replace_value_with_list no longer needs to be marked as recursive.
let replace_value_with_list v sub lst =
let rec aux v sub lst acc =
match lst with
| [] -> List.rev acc
| x::xs when x <> v -> aux v sub xs (x :: acc)
| x::xs -> replace_value_with_list v sub xs (sub # acc)
in
aux v sub lst []
Note that when we call the aux function, it will build up the accumulator in the reverse order to the way we expect, so we need to reverse the accumulator on the exit condition.
However, this is still not optimal because the # operator which performs the concatenation is not tail-recursive. We can overcome this by replacing # with List.rev_append which is tail-recursive.
let replace_value_with_list v sub lst =
let rec aux v sub lst acc =
match lst with
| [] -> List.rev acc
| x::xs when x <> v -> aux v sub xs (x::acc)
| x::xs -> aux v sub xs (List.rev_append sub acc)
in
aux v sub lst []
This process of iterating over a list and accumulating a value is where folds really shine.
let rvl v sub lst =
List.(
let f acc x = if x <> v then x::acc else rev_append sub acc in
fold_left f [] lst |> rev
)

Represent a nil list and/or a list(nil)

Background
We are implementing this algorithm in F#.
Here is a little bit more information from Topor (1982) about the notation that the algorithm uses:
Formally, a 't list is either null (denoted nil) or has a hd (which is a 't) and a tl (which is a 't list)... If x is a list, we test whether it is null by writing null x... We create a new list, adding the element a at the front of an existing list x, by writing a:x... We denote the unit list containing the element a by list(a)... list(x) = x:nil.
Question
What we're wondering is how in F# to express those nil, null, and list(nil) values. For instance, should we be using the Option type, an empty list, or something else?
What We Have Tried
let rec kpermute k (xs: 't list) =
let rec mapPerm k xs ys =
match ys with
| [] -> []
| head::tail ->
let kpermuteNext = kpermute (k-1) (removeFirst head xs)
let mapPermNext = mapPerm k xs tail
mapcons head kpermuteNext mapPermNext
match k with
| 0 -> [[]]
| _ when xs.Length < k -> []
| _ -> mapPerm k xs xs
When working with lists, for list(nil) we use [[]] and for nil we use []. While that's fine, there might be a more expressive way to do it. There are also times when we use List.empty<'t list> and List.empty<'t> when the type inference needs more information.
The paper gives you all the answers: nil is []; null x is a test for whether x is the empty list; list(nil) is [[]].
The naïve translation of algorithm B to F# is as follows:
let rec minus a = function
| [] -> failwith "empty list"
| xh :: xt -> if xh = a then xt else xh :: minus a xt
let rec permute2 k x =
if k = 0 then [[]]
elif List.length x < k then []
else mapperm k x x
and mapperm k x = function
| [] -> []
| yh :: yt -> mapcons yh (permute2 (minus yh x)) (mapperm x yt)
and mapcons a ps qs =
match ps with
| [] -> qs
| ph :: pt -> a :: ph :: mapcons a pt qs

F# - splitting list into tuple of odd-even lists (by element, not position)

Example: split [1;3;2;4;7;9];;
Output: ([1;3;7;9], [2;4])
I'm new to F# and I can't figure it out.
Can't use the partition built in function.
This is what I have so far:
let rec split xs =
match xs with
| [] -> [], []
| xs -> xs, []
| xh::xt -> let odds, evens = split xt
if (xh % 2) = 0 then xh::odds, xh::evens
else xh::odds, evens
Fixed code:
let rec split xs =
match xs with
| [] -> [], []
| xh::xt -> let odds, evens = split xt
if (xh % 2) = 0 then odds, xh::evens
else xh::odds, evens
*Thanks to #TheInnerLight for pointing out my errors: unreachable case and unnecessarily modifying odds
You can use the built-in List.partition function
let splitOddEven xs =
xs |> List.partition (fun x -> x % 2 <> 0)
splitOddEven [1;3;2;4;7;9];;
val it : int list * int list = ([1; 3; 7; 9], [2; 4])
If you want a recursive implementation, I'd probably go for a tail recursive implementation like this:
let splitOddEven xs =
let rec splitOddEvenRec oddAcc evenAcc xs =
match xs with
| [] -> oddAcc, evenAcc
| xh::xt ->
if (xh % 2) = 0 then splitOddEvenRec oddAcc (xh :: evenAcc) xt
else splitOddEvenRec (xh :: oddAcc) evenAcc xt
splitOddEvenRec [] [] xs
splitOddEven [1;3;2;4;7;9]
Note that this will give you the two resulting lists in reverse order so you might wish to reverse them yourself.

List.rev and empty list []

I am not really understand about the function (parse_list) at
None -> List.rev is and None -> []
let try_parse parse x = try Some (parse x) with Error _ -> None;;
let parse_list parse =
let rec aux is = function
| [] -> List.rev is, []
| (hd :: tl) as xs ->
match try_parse parse hd with
| Some i -> aux (i::is) tl
| None -> List.rev is, xs
in aux [];;
and
let parse_list parse =
let rec aux is = function
| [] -> List.rev is, []
| (hd :: tl) as xs ->
match try_parse parse hd with
| Some i -> aux (i::is) tl
| None -> [], xs
in aux [];;
Are they different? could you please give me an example if they are different? Thank you very much
Yes, they are different.
In the first one, when the parse function will fail, the function parse_list will return a partial list of "parsed" expression (List.rev is).
In the second one, when the parse function will fail, you'll get an empty list from parse_list ([]).
Look this example with a parse function which will keep only integers lesser than 3:
let test_parse x = if x < 3 then x else raise Error "error";;
With the first implementation you'll get:
# parse_list test_parse [1; 2; 3; 4; 5];;
- : int list * int list = ([1; 2], [3; 4; 5])
wit the second one, you'll get:
# parse_list test_parse [1; 2; 3; 4; 5];;
- : int list * int list = ([], [3; 4; 5])