Write a function that combines the two lists provided. Items in the output list are to alternate. You must not use library functions (e.g. "length", "reverse", "append") of complexity greater than O(1).
My code:
let rec zip(aList, bList) list =
let rec first(aLst, bLst) list =
if(aLst = [] && bLst = []) then []
else if(aLst = []) then second(aLst,bLst)
else aLst.hd :: second(aLst.tl, bLst)
let rec second(aLst, bLst) list =
if(aLst = [] && bLst = []) then []
else if(bLst = []) then first(aLst,bLst)
else bLst.hd :: first(aLst, bLst.tl);;
zip([1;2;3;4;5], [-6]);;
zip([1;2;3;4;5],[]);;
zip([-6],[1;2;3;4;5]);;
The problem:
let rec second(aLst, bLst) list =
Error: Syntax error
I'm also afraid of rec - is it gonna work properly?
A common recursive pattern for alternation is to swap the arguments in recursive calls, eg.
let rec zip a b =
match a with
| [] -> b
| x :: a' -> x :: zip b a' (* swap arguments *)
zip [-6;-5;-4] [1;2;3];;
(* - : int list = [-6; 1; -5; 2; -4; 3] *)
The syntax for a nested let is
let v = expr0 in expr
You forgot both the in and the final expr.
let rec zip(aList, bList) list =
let rec first(aLst, bLst) list =
if(aLst = [] && bLst = []) then []
else if(aLst = []) then second(aLst,bLst)
else aLst.hd :: second(aLst.tl, bLst)
in
let rec second(aLst, bLst) list =
if(aLst = [] && bLst = []) then []
else if(bLst = []) then first(aLst,bLst)
else bLst.hd :: first(aLst, bLst.tl)
in
first (aLst, bLst)
;;
Next problem is that first and second are mutually recursive. This requires the use of and:
let rec zip(aList, bList) list =
let rec first(aLst, bLst) list =
if(aLst = [] && bLst = []) then []
else if(aLst = []) then second(aLst,bLst)
else aLst.hd :: second(aLst.tl, bLst)
and second(aLst, bLst) list =
if(aLst = [] && bLst = []) then []
else if(bLst = []) then first(aLst,bLst)
else bLst.hd :: first(aLst, bLst.tl)
in
first (aLst, bLst)
;;
Next what is up with (aLst, bLst) list? What is the "list" supposed to be there? Remove those across the board.
And last ocaml lists are not objects. Ocaml has objects but methods are called with #. Neither are lists records that have labels hd and tl. So aLst.hd makes no sense. You have to use List.hd aLst instead. Even better would be pattern matching but you don't seem to have learned about that yet.
Put it all together and you get:
let rec zip(aList, bList) =
let rec first(aLst, bLst) =
if(aLst = [] && bLst = []) then []
else if(aLst = []) then second(aLst,bLst)
else List.hd aLst :: second(List.tl aLst, bLst)
and second(aLst, bLst) =
if(aLst = [] && bLst = []) then []
else if(bLst = []) then first(aLst,bLst)
else List.hd bLst :: first(aLst, List.tl bLst)
in
first (aList, bList)
;;
# zip([1;3;5], [2;4;6]);;
- : int list = [1; 2; 3; 4; 5; 6]
Related
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?
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 =).
I have two lists that contain this datatype:
data Student = Student {firstName::String, lastName::String, age::Int}
deriving (Show, Read, Eq)
I need to make another list that will have unique elements from both of this list.
Ideally this list would contain only firstNames as they can only differ in this one field firstName.
I sort of solved, my solution goes like this:
listOfChanges :: [Student] -> [Student] -> [String]
listOfChanges list1 list2 =
let c = intersect list1 list2
b = union list1 list2
in listEvent(nSame b c)
nSame (x:xs) ys = if x `elem` ys
then nSame xs ys
else x:nSame xs (delete x ys)
nSame [] _ = []
nSame _ [] = []
extractName::Student -> String
extractName (Student firstName _ _) = firstName
listEvent :: [Student] -> [String]
listEvent list = map extractName list
But I would like to convert final list to list of type:
data StudentsFirstNameChangeEvent = StudentsFirstNameChangeEvent {oldName::String, newNames::String}
deriving (Show, Read, Eq)
My final list:
["Alicja","Batrek","Damian","AlicjaX","BatrekX","DamianX"]
"Alicja","Batrek","Damian" - oldNames.
"AlicjaX","BatrekX","DamianX" - newNames.
When it actually should be:
[StudentsFirstNameChangeEvent {oldName = "Alicja", newName = "Alicjax"},StudentsFirstNameChangeEvent {oldName = "Bartek", newName = "Bartekx"}, ...]
enter code here
I think im done with haskell, but this is my final progress:
correctSplit :: [String] -> [[String]]
correctSplit list =
let x = length list
x1 = (x `div` 2)
in splitEvery x1 list
splitEvery _ [] = []
splitEvery n list = first : (splitEvery n rest)
where
(first,rest) = splitAt n list
proList :: [Student] -> [Student] -> [String]
proList list1 list2 =
let x = listOfChanges list1 list2
x2 = correctSplit x
x3 = x2 !! 0
x4 = x2 !! 1
in merge x3 x4
merge :: [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = x : y : merge xs ys
And the final list is now:
["Alicja","AlicjaX","Batrek","BatrekX","Damian","DamianX"]
But I still have no idea how to convert either of those list into the type I need.
Well and it turns out that correct way to process this is much shorter:
listOfChanges :: [Student] -> [Student] -> [StudentsFirstNameChangeEvent]
listOfChanges list1 list2 =
let mask = intersect list1 list2
x1 = list1 \\ mask
x2 = list2 \\ mask
in changeList x1 x2
changeList :: [Student] -> [Student] -> [StudentsFirstNameChangeEvent]
changeList a b = zipWith StudentsFirstNameChangeEvent (map firstName a) (map firstName b)
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
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