Related
Here I am again facing some problems with Clojure. I have two vectors of vectors.
[[a b c] [d e f] [g h i]]
and
[[a b] [d e] [g h] [j k]]
And I wanna merge these two in a way that the final vector would be something like this:
[[a b c] [d e f] [g h i] [j k l]]
In the output, the last item [j k l], the L is a constant value when there is no value to merge (because it has no corresponding item in the first vector.
How can I do such thing?
P.S.: I am new to Clojure and I appreciate a elaborated answer so that I could understand better. Also, sorry if this is a trivial question.
In general:
break the problem into separable parts
give things names
compose the parts
So in this case your problem can be broken down into:
splitting the lists into the overlapping and non-overlapping parts
choosing the best of each of the overlapping parts
padding the non-overlapping parts to the correct length
combining them back together.
So if I make a couple assumptions about your problem here is an example of breaking it down and building it back up:
user> (def a '[[a b c] [d e f] [g h i]])
#'user/a
user> (def b '[[a b] [d e] [g h] [j k]])
#'user/b
make a function to choose the correct pair of the overlapping parts. I chose length though you can merge these however you want:
user> (defn longer-list [x y]
(if (> (count x) (count y))
x
y))
#'user/longer-list
make a function to pad out a list that's too short
user> (defn pad-list [l min-len default-value]
(into l (take (- min-len (count l)) (repeat default-value))))
#'user/pad-list
Make a function that uses these two functions to split and then recombine the parts of the problem:
user> (defn process-list [a b]
(let [a-len (count a)
b-len (count b)
longer-input (if (> a-len b-len)
a
b)
shorter-input (if (< a-len b-len)
a
b)]
(concat (map longer-list longer-input shorter-input)
(map #(pad-list % 3 'l) (drop (count shorter-input) longer-input)))))
#'user/process-list
and then test it :-)
user> (process-list a b)
([a b c] [d e f] [g h i] [j k l])
There are more details to work out, like what happens when the lists-of-lists are the same length, and if they are not subsets of each other. (and yes you can smash this down to a "one liner" too)
I'd take a look at clojure.core.matrix (see here); It has some nice operations which could help you with this.
i would generally go with the following approach:
fill collections up to the size of the longest one
map both of them, filling every item of the collection up to the size of the longest, mapping items to select the resulting value.
It is better to illustrate it with code:
first of all let's make up some helper functions:
(defn max-count [coll1 coll2] (max (count coll1) (count coll2)))
it's name says for itself.
(defn fill-up-to [coll size] (take size (concat coll (repeat nil))))
this one fills the collection with nils up to some size:
user> (fill-up-to [1 2 3] 10)
(1 2 3 nil nil nil nil nil nil nil)
now the merge function:
(defn merge-colls [v1 v2 default-val]
(let [coll-len (max-count v1 v2)
comp-len (max-count (first v1) (first v2))]
(mapv (fn [comp1 comp2]
(mapv #(or %1 %2 default-val)
(fill-up-to comp1 comp-len)
(fill-up-to comp2 comp-len)))
(fill-up-to v1 coll-len)
(fill-up-to v2 coll-len))))
the outer mapv operates on collections made from initial parameters filled up to the length of the longest one (coll-len), so in context of the question it will be:
(mapv some-fn [[a b c] [d e f] [g h i] nil]]
[[a b] [d e] [g h] [j k]])
the inner mapv operates on inner vectors, filled up to the comp-len (3 in this case):
(mapv #(or %1 %2 default-val) '[a b c] '[d e nil])
...
(mapv #(or %1 %2 default-val) '[nil nil nil] '[j k nil])
let's test it:
user> (let [v1 '[[a b c] [d e f] [g h i]]
v2 '[[a b] [d e] [g h] [j k]]]
(merge-colls v1 v2 'l))
[[a b c] [d e f] [g h i] [j k l]]
ok it works just as we wanted.
now if you look at the merge-colls, you may notice the repetition of the pattern:
(mapv some-fn (fill-up-to coll1 size)
(fill-up-to coll2 size))
we can eliminate the duplication by moving this pattern out to a function:
(defn mapv-equalizing [map-fn size coll1 coll2]
(mapv map-fn (fill-up-to coll1 size) (fill-up-to coll2 size)))
and rewrite our merge:
(defn merge-colls [v1 v2 default-val]
(let [coll-len (max-count v1 v2)
comp-len (max-count (first v1) (first v2))]
(mapv-equalizing (fn [comp1 comp2]
(mapv-equalizing #(or %1 %2 default-val)
comp-len comp1 comp2))
coll-len v1 v2)))
test:
user> (let [v1 '[[a b c] [d e f] [g h i]]
v2 '[[a b] [d e] [g h] [j k]]]
(merge-colls v1 v2 'l))
[[a b c] [d e f] [g h i] [j k l]]
ok. now we can shorten it by removing collection size bindings, as we need these values just once:
(defn merge-colls [v1 v2 default-val]
(mapv-equalizing
(partial mapv-equalizing
#(or %1 %2 default-val)
(max-count (first v1) (first v2)))
(max-count v1 v2) v1 v2))
in repl:
user> (let [v1 '[[a b c] [d e f] [g h i]]
v2 '[[a b] [d e] [g h] [j k]]]
(merge-colls v1 v2 'l))
[[a b c] [d e f] [g h i] [j k l]]
I created a function and helper function that find the number of repeating elements in a list, and what those elements.
let rec _encode l x =
match l with
| [] -> 0
| head::rest -> (if head = x then 1 else 0) + encode rest x
let encode l x = ((_encode l x), x)
In this case, I have to specify what that element is for it to search.
So this is a two part question. 1) How do I do it to return a list of tuples, with format (int * 'a) list, where int is the # of rep, and 'a is the element that is repeating.
2) How would I implement this using fold_right?
I was thinking something along the lines of:
let encode (l : 'a list) : (int * 'a) list = fold_right (fun (x,hd) lst ->
match x with
| [] -> 0
| hd :: rest -> if hd x then (x+1, hd) else (x, hd)) l []
Your attempt looks very confused:
It doesn't use lst, hd (the first one), or rest.
x is used as a list (match x with []) and a number (x+1).
The elements of x (list) are functions that return bools?? (... hd::rest -> ... if hd x)
The function sometimes returns a number (0) and sometimes a tuple ((x, hd)).
Here's how I'd do it:
let encode l =
let f x = function
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
in
fold_right f l []
Which is the same as:
let encode l =
let f x z = match z with
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
in
fold_right f l []
Which is the same as:
let encode l =
fold_right (fun x z ->
match z with
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
) l []
I'm writing a function that take a pair of lists, if the length of two lists are equal then create a pair of each element from each list, but my function doesn't work and the compiler say there is a syntax error
Could someone explain why there is a syntax error at the semicolon at the end of my function?
This is my code:
let define_tuple a b =
(a, b);;
let zip (a, b) =
if List.length (fst (a, b)) != List.length (fst (a, b))
then
printf_string "lengths of 2 lists need to be equal"
else
let rec create_tuples (a, b) =
if List.length (List.tl (fst (a, b))) = 0 && List.length (List.tl (snd (a, b))) != 0
then
[]
else
List.append define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b))) create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b)));;
zip ([1; 2; 3], [2; 3; 4]);;
There are quite a few possible improvements and errors in your code and I list them all in the following:
No. 1
If you write your code in a file and try to compile / run your file, then you don't need ;; in the end for every function.
No. 2
let define_tuple a b = (a, b);;
You don't need to define such a function, instead, you can directly use (a, b).
No. 3
let zip (a, b) =
if List.length (fst (a, b)) != List.length (fst (a, b)) then
printf_string "lengths of 2 lists need to be equal"
else
let rec create_tuples (a, b) =
if List.length (List.tl (fst (a, b))) = 0 && List.length (List.tl (snd (a, b))) != 0
then
[]
else
List.append define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b))) create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b)));;
3.1
For your first if ... else ..., it is not correct as the if branch returns unit and else branch returns list.
In OCaml, if and else or any branch of pattern matching should returns the same type.
3.2
Because of 3.1, I suggest you write an exception for the non-equal lengths case. In this way, the whole function still returns list and code is more readable and users of your function can also get the chance to "catch" your exception case.
3.3
for function create_tuples,
let rec create_tuples (a, b) =
if List.length (List.tl (fst (a, b))) = 0 && List.length (List.tl (snd (a, b))) != 0
then
[]
else
List.append define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b))) create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b)));;
3.3.1
List.length (List.tl (fst (a, b))) = 0
You don't need to use fst (a,b), instead, just a is enough because a is already known.
It is the same for your snd usage.
Basically you don't need fst and snd all over your code.
3.3.1.1
You should check whether a and b's lengths are 0 or not, not the tl of them.
3.3.2
You also don't need (a,b) a tuple as the parameters for create_tuples, instead, you can use create_tuples a b. It is better because your code doesn't need to create a tuple for a pair of parameters.
3.3.3
List.append define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b))) create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b)))
First of all, List.append is to append one list to another list. In your case, you are adding an element to a list, so you should use ::.
You should use () to include a function application if you want the value of the function application to be used.
for example, you should do (define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b)))):: (create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b)))).
If you consider the previous points together, you can do
(List.hd a, List.hd b)::(create_tuples (List.tl a) (List.tl b))
3.4
You have defined function create_tuples, but did you really use it in your code? No.
So at the end, you should do
in create_tuples a b
No. 4
You should use <> to check inequality.
The full refined/corrected code is
exception Non_equal_list_length
let zip a b =
if List.length a <> List.length b then raise Non_equal_list_length
else
let rec create_tuples a b =
if List.length a = 0 && List.length b = 0 then []
else (List.hd a, List.hd b)::(create_tuples (List.tl a) (List.tl b))
in
create_tuples a b
Some more improvements:
You can use pattern matching directly on lists
You should always take tail-recursive in consideration
Final improved code:
exception Non_equal_list_length
let zip a b =
let rec zipping acc = function
| [], [] -> List.rev acc
| hd1::tl1, hd2::tl2 -> zipping ((hd1,hd2)::acc) (tl1,tl2)
| _ -> raise Non_equal_list_length
in
zipping [] (a,b)
The expression let a = b is valid only at the topmost level of a module, where it defines names to be exported from the module. Everywhere else this expression is used to introduce a local variable (or variables), and it has the form let a = b in c. You're missing the in keyword, and the expression in which you want to use your local variable create_tuples.
(There are some other errors that you will find when you get the syntax in order.)
Update
Here's a simple example of a function that uses a helper function declared with let a = b in c:
let myrev l =
let rec irev sofar = function
| [] -> sofar
| hd :: tl -> irev (hd :: sofar) tl
in
irev [] l
I am have some problems with recursion in Lazy Computations. I need calculation the square root by Newton Raphson method. I do not know how to apply a lazy evaluation. This is my code:
let next x z = ((x + z / x) / 2.);
let rec iterate f x =
List.Cons(x, (iterate f (f x)));
let rec within eps list =
let a = float (List.head list);
let b = float (List.head (List.tail list));
let rest = (List.tail (List.tail (list)));
if (abs(a - b) <= eps * abs(b))
then b
else within eps (List.tail (list));
let lazySqrt a0 eps z =
within eps (iterate (next z) a0);
let result2 = lazySqrt 10. Eps fvalue;
printfn "lazy approach";
printfn "result: %f" result2;
Of course, stack overflow exception.
You're using F# lists which has eager evaluation. In your example, you need lazy evaluation and decomposing lists, so F# PowerPack's LazyList is appropriate to use:
let next z x = (x + z / x) / 2.
let rec iterate f x =
LazyList.consDelayed x (fun () -> iterate f (f x))
let rec within eps list =
match list with
| LazyList.Cons(a, LazyList.Cons(b, rest)) when abs(a - b) <= eps * abs(b) -> b
| LazyList.Cons(a, res) -> within eps res
| LazyList.Nil -> failwith "Unexpected pattern"
let lazySqrt a0 eps z =
within eps (iterate (next z) a0)
let result2 = lazySqrt 10. Eps fvalue
printfn "lazy approach"
printfn "result: %f" result2
Notice that I use pattern matching which is more idiomatic than head and tail.
If you don't mind a slightly different approach, Seq.unfold is natural here:
let next z x = (x + z / x) / 2.
let lazySqrt a0 eps z =
a0
|> Seq.unfold (fun a ->
let b = next z a
if abs(a - b) <= eps * abs(b) then None else Some(a, b))
|> Seq.fold (fun _ x -> x) a0
If you need lazy computations, then you have to use appropriate tools. List is not lazy, it is computed to the end. Your iterate function never ends, so the entire code stack overflows in this function.
You may use Seq here.
Note: Seq.skip almost inevitably leads you to an O(N^2) complexity.
let next N x = ((x + N / x) / 2.);
let rec iterate f x = seq {
yield x
yield! iterate f (f x)
}
let rec within eps list =
let a = Seq.head list
let b = list |> Seq.skip 1 |> Seq.head
if (abs(a - b) <= eps * abs(b))
then b
else list |> Seq.skip 1 |> within eps
let lazySqrt a0 eps z =
within eps (iterate (next z) a0);
let result2 = lazySqrt 10. 0.0001 42.;
printfn "lazy approach";
printfn "result: %f" result2;
// 6.4807406986501
Yet another approach is to use LazyList from F# PowerPack. The code is available in this article. Copying it to my answer for sake of integrity:
open Microsoft.FSharp.Collections.LazyList
let next N (x:float) = (x + N/x) / 2.0
let rec repeat f a =
LazyList.consDelayed a (fun() -> repeat f (f a))
let rec within (eps : float) = function
| LazyList.Cons(a, LazyList.Cons(b, rest)) when (abs (a - b)) <= eps -> b
| x -> within eps (LazyList.tail x)
let newton_square a0 eps N = within eps (repeat (next N) a0)
printfn "%A" (newton_square 16.0 0.001 16.0)
Some minor notes:
Your next function is wrong;
The meaning of eps is relative accuracy while in most academic books I've seen an absolute accuracy. The difference between the two is whether or not it's measured against b, here: <= eps * abs(b). The code from FPish treats eps as an absolute accuracy.
Having list append implementation in Prolog -
append([],X,X).
append([H|T1],X,[H|T2]) :-
append(T1,X,T2).
Which gives on -
append([a,b,c],[d,e,f],X).
The output -
X = [a,b,c,d,e,f].
I wonder how does it work , I tried to trace function calling but I didn't understand how T2 , which is the tail of a list , can be has as tail of X which in append([a,b,c],[d,e,f],X) calling had not defined yet .
Can you clear up this recursion for me ?
It comes down to how Unification works in Prolog. Basically:
atoms unify only when they are identical
variables unify with anything and
compounds unify when each component can unify
So you call: append([a, b, c], [d, e, f], Y) which is your first goal. Note that just to make things easier to see I changed your variable name from X to Y.
This has to be unified with a fact or a rule: Let us see if it will unify with append([], X, X)?
(1) append([a, b, c], [d, e, f], Y)
(2) append([], X, X)
Both (1) and (2) has the same functor (append) so that is good, and they both have 3 arguments so that is also good. But to unify each corresponding argument must unify. So the first list [a, b, c] in (1) will attempt to unify with the empty list in (2) but they cannot because the list in (1) is not an empty list. So unification fails.
We can then try to unify with append([H|T1],X,[H|T2]).
(1) append([a, b, c], [d, e, f], Y)
(2) append([H|T1],X,[H|T2])
This time the list [a, b, c] in (1) will attempt to unify with the list [H|T1] in (2). To make this possible the variable H can bind with the atom a (H -> a) and the list T1 can bind with the tail of the list in (1), T1 -> [b, c]. So the first argument works so what we have is:
(1) append([a, b, c], [d, e, f], Y)
(2)' append([a, b, c],X,[a|T2])
The second argument will also unify because X is a variable and will bind to anything. X -> [d, e, f] so we have:
(1) append([a, b, c], [d, e, f], Y)
(2)'' append([a, b, c],[d, e, f],[a|T2])
And finally the last argument unifies because Y -> [a|T2]. So now that it unifies with the head of a rule, we need to work out the body of the rule: We now end up with append([b, c], [d, e, f], T2) as the goal.
Starting from the first fact again we look for the clause that this goal will bind to. By the same explanation above it will not unify with the first clause but will unify with the second with the bindings: H -> b, T1 -> [c], X -> [d, e, f] and T2 -> [b|T2'].
We are left with the goal: append([c], [d, e, f], T2'). Again it does not unify with the first clause and unifies with the second with the bindings: H -> c, T1 -> [], X -> [d, e, f], T2' -> [c|T2''].
The goal is now: append([], [d, e, f], T2'').
Lets see what happens when we try to unify this with clause 1:
(1) append([], [d, e, f], T2'')
(2) append([],X,X)
The two empty lists unify, X -> [d, e, f] and since T2''->X then T2'' -> [d, e, f]. Now the tricky part is keeping track of the recursive calls so far and now walking back along the recursion to see the final result. recall that T2' -> [c | T2''] so T2' is actually [c, d, e, f]. And recall that T2 -> [b| T2'] so T2 is actually [b, c, d, e, f].
And finally Y -> [a|T2] so Y is [a, b, c, d, e, f]. Since Y is an external variable it is displayed now that the original goal is satisfied.