Merge two "list in list" in scheme - list

I don't know how to exactly express my question in language. Pardon my ambiguous words in the title
My question is:
If you have
a = [[1, 2], [3, 4], [5, 6]....], b = [[1, 3], [4, 8], ....]
How to merge a and b like
[[1,2], [3, 4], [5, 6], [1, 3], [4, 8]....]
in scheme??
I have already tried using car or write a function my self to solve it, but all failed. I was thinking to use (cons a b), but it'll give me [[[1, 2], [3, 4]...], [[1, 3], [4, 8]...]] which is not what I want.
I tried to write a recursive function, but still I'll get the similar trouble as (cons a b)
Thanks!

As pointed out in the comments, you're looking for append. This is how the code in the question would look like in Scheme:
(define a '((1 2) (3 4) (5 6)))
(define b '((1 3) (4 8)))
(append a b)
=> '((1 2) (3 4) (5 6) (1 3) (4 8))
If you want to implement your own version of append it's simple enough:
(define (my-append lst1 lst2)
(if (null? lst1)
lst2
(cons (car lst1)
(my-append (cdr lst1) lst2))))
(my-append a b)
=> '((1 2) (3 4) (5 6) (1 3) (4 8))

Related

In clojure how to map over overlapping pairs?

Say I have the sequence:
[1 2 3 4 5]
And I want to map over them in the pairs:
[(1, 2), (2, 3), (3, 4), (4, 5)]
I have tried:
(map f (partition 2 [1 2 3 4]))
But this results in the sequence of pairs:
[(1, 2), (3, 4)]
How can I get the desired functionality?
By default partiton returns non-overlapping partitions, but you can supply a step argument to provide the offset at which partitions are created:
clojure.core/partition
([n coll] [n step coll] [n step pad coll])
Returns a lazy sequence of lists of n items each, at offsets step
apart. If step is not supplied, defaults to n, i.e. the partitions
do not overlap. If a pad collection is supplied, use its elements as
necessary to complete last partition upto n items. In case there are
not enough padding elements, return a partition with less than n items.
This will do what you want:
(partition 2 1 [1 2 3 4 5 6 7 8]))
; #=> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8))
An alternative would be map both with the list you have and the rest of the list. E.g.:
(user=> (let [l [1 2 3 4 5]] (map list l (rest l)))
((1 2) (2 3) (3 4) (4 5))
I would do it as follows
; first generate data
; (that is if you really are talking about all the ints)
(map (juxt identity inc) [1 2 3 4 5])
=> ([1 2] [2 3] [3 4] [4 5] [5 6])
; inline example
(map (comp
(fn [[a b]] (println a b)) ; this would be your f
(juxt identity inc)) [1 2 3 4 5])
; using your function f
(map (comp
f
(juxt identity inc)) [1 2 3 4 5])
This also works independent of the order of numbers in your vector:
(let [a [5 4 3 2 1] b (rest a)] (map vector a b))
will yield:
([5 4] [4 3] [3 2] [2 1])

What is the Clojure way to implement for-loop?

In this question, you are given a value V and a list of unique integers. Your job is to find the number of distinct subsets of size 4 that sum up to V. Each element in the list can be used only once. If none of such subset can be found, output 0 instead.
For example, if the integers are [3, 4, 5, 6, 7, 8, 9, 10] and the value is 30, the output should be 5. The subsets are:
[3, 8, 9, 10]
[4, 7, 9, 10]
[5, 6, 9, 10]
[5, 7, 8, 10]
[6, 7, 8, 9].
It is not hard to solve this question, the most direct way is to nest for-loop four times. What's the Clojure way to do it?
Here is how I would've done it:
(ns example.solve
(:require [clojure.math.combinatorics :as combo]))
(defn solve
[s n v]
(filter (comp (partial = v)
(partial reduce +))
(combo/combinations s n)))
I'm using math.combinatorics in my example, because it's a simplest way to get all combinations of 4 elements from a list.
Here is an example of using solve:
=> (solve [3 4 5 6 7 8 9 10] 4 30)
((3 8 9 10) (4 7 9 10) (5 6 9 10) (5 7 8 10) (6 7 8 9))
I would use clojure.map.combinatorics/combinations to get all 4-element subsets and then filter out those that do not sum up to V.
Interestingly, this problem admits a (doubly?) recursive solution which involves only summing and counting (without actually generating the subsets.)
If you look at the initial element 3, then part of the solution is the number of sums taken from 3 elements in the rest of the sequence where the sum is 27, which is a smaller form of the same problem and can thus be solved recursively. The bottom of the recursion is when you are looking for sums produced from 1 element, which boils down to a simple check to see if the desired sum is in the list.
The other part of the solution involves looking at the next element 4, looking for sums in the rest of the list beyond the 4 equal to 26, and so on... This part can also be treated recursively.
Putting this together as a recursive function looks like the following, which produces the desired answer 5 for the example sequence.
(defn solve [xs n len]
(if (seq xs)
(if (= len 1)
(if (some #{n} xs) 1 0)
(+ (solve (rest xs)
(- n (first xs))
(dec len))
(solve (rest xs)
n
len)))
0))
(solve [3 4 5 6 7 8 9 10] 30 4)
;=> 5
In terms of directly answering the question, here is how you could do it using indexes and a for loop:
(defn solve-for [xs v]
(for [ndx0 (range 0 (- (count xs) 3))
ndx1 (range (inc ndx0) (- (count xs) 2))
ndx2 (range (inc ndx1) (- (count xs) 1))
ndx3 (range (inc ndx2) (count xs))
:when (= v (+ (xs ndx0) (xs ndx1) (xs ndx2) (xs ndx3)))]
(list (xs ndx0) (xs ndx1) (xs ndx2) (xs ndx3))))
FWIW, this turns out to be about 70% faster than the approach using clojure.math.combinatorics but twice as slow as the doubly-recursive solution.

Clojure - pairs from nested lists

I'm trying to make traversing nested lists to collect pairs more idiomatic in Clojure
(def mylist '(
(2, 4, 6)
(8, 10, 12)))
(defn pairs [[a b c]]
(list (list a c)(list b c)))
(mapcat pairs mylist)
;((2 6) (4 6) (8 12) (10 12))
Can this be made more elegant?
Your code is good, but I would use vectors instead of lists
(defn pairs [[x1 x2 y]]
[[x1 y] [x2 y]])
(mapcat pairs mylist)
Just to add more solutions (not elegant or intuitive; do not use ;) ):
(mapcat
(juxt (juxt first last) (juxt second last))
[[2 4 6] [8 10 12]])
;; => ([2 6] [4 6] [8 12] [10 12])
Or this one:
(mapcat
#(for [x (butlast %) y [(last %)]] [x y])
[[2 4 6] [8 10 12]])
;; => ([2 6] [4 6] [8 12] [10 12])

Append a list to a sequence of lists

I have a sequence of lists:
(def s '((1 2) (3 4) (5 6)))
And I want to append another list to the tail of this sequence, i.e.
(concat-list s '(7 8))
=> '((1 2) (3 4) (5 6) (7 8))
Various approaches that (obviously) don't work:
(cons '((1 2)) '(3 4))
=> (((1 2)) 3 4)
(conj '(3 4) '((1 2)))
=> (((1 2)) 3 4)
(concat '((1 2)) '(3 4))
=> ((1 2) 3 4)
;; close, but wrong order...
(conj '((1 2)) '(3 4))
=> ((3 4) (1 2))
;; Note: vectors work - do I really have to convert entire
;; structure from lists to vectors and back again?
(conj [[1 2]] [3 4])
=> [[1 2] [3 4]]
What are some possible implementations of concat-list, or does there exist library function that does this?
If you find this collection is usually growing to the right, then you should start it off as a vector and keep it that way.That will be the most efficient and convenient.
However, if this collection mostly grows to the left and only rarely to the right, concat is probably your best option:
(concat '((1 2)) ['(3 4)])
Note that concat returns a lazy sequence, not a persistent list.
If the collection is large and grows frequently on both ends, you may want a more advanced collection type like a finger tree or a flexvec.
There may be a better solution, but here's one way:
user=> s
((1 2) (3 4) (5 6))
user=> s2
(7 8)
user=> (concat s (cons s2 '()))
((1 2) (3 4) (5 6) (7 8))

Clojure partition by filter

In Scala, the partition method splits a sequence into two separate sequences -- those for which the predicate is true and those for which it is false:
scala> List(1, 5, 2, 4, 6, 3, 7, 9, 0, 8).partition(_ % 2 == 0)
res1: (List[Int], List[Int]) = (List(2, 4, 6, 0, 8),List(1, 5, 3, 7, 9))
Note that the Scala implementation only traverses the sequence once.
In Clojure the partition-by function splits the sequence into multiple sub-sequences, each the longest subset that either does or does not meet the predicate:
user=> (partition-by #(= 0 (rem % 2)) [1, 5, 2, 4, 6, 3, 7, 9, 0, 8])
((1 5) (2 4 6) (3 7 9) (0 8))
while the split-by produces:
user=> (split-with #(= 0 (rem % 2)) [1, 5, 2, 4, 6, 3, 7, 9, 0, 8])
[() (1 5 2 4 6 3 7 9 0 8)]
Is there a built-in Clojure function that does the same thing as the Scala partition method?
I believe the function you are looking for is clojure.core/group-by. It returns a map of keys to lists of items in the original sequence for which the grouping function returns that key. If you use a true/false producing predicate, you will get the split that you are looking for.
user=> (group-by even? [1, 5, 2, 4, 6, 3, 7, 9, 0, 8])
{false [1 5 3 7 9], true [2 4 6 0 8]}
If you take a look at the implementation, it fulfills your requirement that it only use one pass. Plus, it uses transients under the hood so it should be faster than the other solutions posted thus far. One caveat is that you should be sure of the keys that your grouping function is producing. If it produces nil instead of false, then your map will list failing items under the nil key. If your grouping function produces non-nil values instead of true, then you could have passing values listed under multiple keys. Not a big problem, just be aware that you need to use a true/false producing predicate for your grouping function.
The nice thing about group-by is that it is more general than just splitting a sequence into passing and failing items. You can easily use this function to group your sequence into as many categories as you need. Very useful and flexible. That is probably why group-by is in clojure.core instead of separate.
Part of clojure.contrib.seq-utils:
user> (use '[clojure.contrib.seq-utils :only [separate]])
nil
user> (separate even? [1, 5, 2, 4, 6, 3, 7, 9, 0, 8])
[(2 4 6 0 8) (1 5 3 7 9)]
Please note that the answers of Jürgen, Adrian and Mikera all traverse the input sequence twice.
(defn single-pass-separate
[pred coll]
(reduce (fn [[yes no] item]
(if (pred item)
[(conj yes item) no]
[yes (conj no item)]))
[[] []]
coll))
A single pass can only be eager. Lazy has to be two pass plus weakly holding onto the head.
Edit: lazy-single-pass-separate is possible but hard to understand. And in fact, I believe this is slower then a simple second pass. But I haven't checked that.
(defn lazy-single-pass-separate
[pred coll]
(let [coll (atom coll)
yes (atom clojure.lang.PersistentQueue/EMPTY)
no (atom clojure.lang.PersistentQueue/EMPTY)
fill-queue (fn [q]
(while (zero? (count #q))
(locking coll
(when (zero? (count #q))
(when-let [s (seq #coll)]
(let [fst (first s)]
(if (pred fst)
(swap! yes conj fst)
(swap! no conj fst))
(swap! coll rest)))))))
queue (fn queue [q]
(lazy-seq
(fill-queue q)
(when (pos? (count #q))
(let [item (peek #q)]
(swap! q pop)
(cons item (queue q))))))]
[(queue yes) (queue no)]))
This is as lazy as you can get:
user=> (let [[y n] (lazy-single-pass-separate even? (report-seq))] (def yes y) (def no n))
#'user/no
user=> (first yes)
">0<"
0
user=> (second no)
">1<"
">2<"
">3<"
3
user=> (second yes)
2
Looking at the above, I'd say "go eager" or "go two pass."
It's not hard to write something that does the trick:
(defn partition-2 [pred coll]
((juxt
(partial filter pred)
(partial filter (complement pred)))
coll))
(partition-2 even? (range 10))
=> [(0 2 4 6 8) (1 3 5 7 9)]
Maybe see https://github.com/amalloy/clojure-useful/blob/master/src/useful.clj#L50 - whether it traverses the sequence twice depends on what you mean by "traverse the sequence".
Edit: Now that I'm not on my phone, I guess it's silly to link instead of paste:
(defn separate
[pred coll]
(let [coll (map (fn [x]
[x (pred x)])
coll)]
(vec (map #(map first (% second coll))
[filter remove]))))