Debugging thread macro -> or ->> in Clojure - debugging

I want to understand how works the following code that is designed for the problem: "Given a sequence of integers, find a continuous subsequence which maximizes the sum of its elements"
defn max-subseq-sum [coll]
(->> (take-while seq (iterate rest coll)) ; tails (1)
(mapcat #(reductions conj [] %)) ; inits (2)
(apply max-key #(reduce + %)))) ; max sum
so I'd like to see the output of forms (1), (2) and others. I can set breakpoints in Cursive but yet I don't know how to get these values.
I have tried to define a locale variables, for example
(defn max-subseq-sum [coll]
(->> (take-while seq (iterate rest coll)) ; tails
(let [d #(reductions conj [] %)]
d ) ; inits
(apply max-key #(reduce + %)))
)
(max-subseq-sum [-1, -2, 3, 5, 6, -2, -1, 4, -4, 2, -1])
But i still don't understand how to see d, for example
How to solve this problem?

A simple function that prints and returns its input can be inserted into the chain:
(defn debug [x]
(println x)
x)
(defn max-subseq-sum [coll]
(->> (take-while seq (iterate rest coll))
(debug)
(mapcat #(reductions conj [] %))
(apply max-key #(reduce + %))))
(max-subseq-sum [-1, -2, 3, 5, 6, -2, -1, 4, -4, 2, -1])
([-1 -2 3 5 6 -2 -1 4 -4 2 -1] (-2 3 5 6 -2 -1 4 -4 2 -1) (3 5 6 -2 -1 4 -4 2 -1) (5 6 -2 -1 4 -4 2 -1) (6 -2 -1 4 -4 2 -1) (-2 -1 4 -4 2 -1) (-1 4 -4 2 -1) (4 -4 2 -1) (-4 2 -1) (2 -1) (-1))
=> [3 5 6 -2 -1 4]
Or, if you want better tracking and don't mind a bit of bulk, you can use a macro that includes the expression in the printout:
(defmacro debugM [expr]
`(let [x# ~expr] ; Save the result of the expression so it isn't evaluated twice
(println '~expr "\n\t" x#)
x#))
(defn max-subseq-sum [coll]
(->> (take-while seq (iterate rest coll))
(debugM)
(mapcat #(reductions conj [] %))
(apply max-key #(reduce + %))))
(max-subseq-sum [-1, -2, 3, 5, 6, -2, -1, 4, -4, 2, -1])
(take-while seq (iterate rest coll))
([-1 -2 3 5 6 -2 -1 4 -4 2 -1] (-2 3 5 6 -2 -1 4 -4 2 -1) (3 5 6 -2 -1 4 -4 2 -1) (5 6 -2 -1 4 -4 2 -1) (6 -2 -1 4 -4 2 -1) (-2 -1 4 -4 2 -1) (-1 4 -4 2 -1) (4 -4 2 -1) (-4 2 -1) (2 -1) (-1))
=> [3 5 6 -2 -1 4]

There is a nice library called debux
(use '[debux.core])
(defn max-subseq-sum [coll]
(dbg (->> (take-while seq (iterate rest coll)) ; tails (1)
(mapcat #(reductions conj [] %)) ; inits (2)
(apply max-key #(reduce + %)))))
(max-subseq-sum [1 2 3])
dbg: (->> (take-while seq (iterate rest coll)) (mapcat (fn* [p1__1991#] (re ... =>
| (take-while seq (iterate rest coll)) =>
| ([1 2 3] (2 3) (3))
| (mapcat (fn* [p1__1991#] (reductions conj [] p1__1991#))) =>
| ([] [1] [1 2] [1 2 3] [] [2] [2 3] [] [3])
| (apply max-key (fn* [p1__1992#] (reduce + p1__1992#))) =>
| [1 2 3]

I could do by injecting ((fn [x] (println x) x)).
(->> [1 2 3 4 5]
(filter even?)
((fn [x] (println x) x))
first)
that shows
(2 4)
2

Related

reduce a nested vector to another one in Clojure

What is an idiomatic way of handling such stuff in Clojure?
I have:
(def data1
[1 [2 3]])
(def data2
[1 [[2 [3 [4]]]
[22 33]]])
I want to get:
[1 2 3]
and
[[1 2 3 4]
[1 22 33]]
respectively. The nested levels of inner vectors may be of different lengths.
I cannot wrap my head around the nature of such inputs and looking for help. Basically a function should map an input (which is a vector) to an output (vector, also) which, in essence, is a vector of all the "routes" from its head to the innermost elements. This is a vague explanation, will be grateful for a better one.
(defn transform [[f & r]]
(let [rr (apply concat r)]
(if (= (flatten rr) rr)
(vec (cons f rr))
(mapv #(if (vector? %)
(vec (cons f (flatten %)))
[f %])
rr))))
; Test Cases
(transform [1 [2 3]]) => [1 2 3]
(transform [1 [[2 [3 [4]]] [22 33]]]) => [[1 2 3 4] [1 22 33]]
(transform [1 [[2 [3 [4]]] [22 33] 44]]) => [[1 2 3 4] [1 22 33] [1 44]
(transform [1]) => [1]
(transform [1 [2]]) => [1 2]
(defn transform [v]
(let [[x & [xs]] v]
(loop [r xs
res []]
(cond
(empty? r) res
(vector? (first r)) (recur (rest r)
(conj res
(into
(conj [] x)
(flatten (first r)))))
:else (into (conj res x) r)))))
(def data1
[1 [2 3]])
(def data2
[1 [[2 [3 [4]]]
[22 33]]])
(def data3
[1 [[20 25 [30 [40 [50]]]]
[2 3 [4 5 [6 7 [8 9]]]]
[[60] 70 [80 [90 100 [110 120 130 [140 150]]]]]]])
; user=> (transform data1)
; [1 2 3]
; user=> (transform data2)
; [[1 2 3 4] [1 22 33]]
; user=> (transform data3)
; [[1 20 25 30 40 50] [1 2 3 4 5 6 7 8 9] [1 60 70 80 90 100 110 120 130 140 150]]

Scheme - Secuence of numbers that sum 0 in a list

I'm trying to implement a recursive function (sums cero) that given a list of integers, it prints all possible secuences of consecutive numbers that sum up 0
Example 1:
(sum-zero ‘(4 2 -3 -1 0 4))
=> (-3 -1 0 4)
(0)
Example 2:
(sum-zero ‘(3 4 -7 3 1 3 1 -4 -2 -2))
=> (3 4 -7)
(4 -7 3)
(-7 3 1 3)
(3 1 -4)
(3 1 3 1 -4 -2 -2)
(3 4 -7 3 1 3 1 -4 -2 -2)
You function needs to have a helper that has arguments for 1. the list of available numbers, 2. the current numbers, 3. the list of results of combination that sum to zero so far. Here is how I would have done it, with some parts left out to keep us from doing your homework:
(define (sum-zero lst)
;; insert e such that the resulting list i ssorted
;; (insert 3 '(1 3 4)) ; ==> (1 3 3 4)
(define (insert e lst)
<implement>)
;; main logic
(define (helper lst acc res)
(if (null? lst)
res
(let* ((new-acc (insert (car lst) acc))
(res (if <should add new-acc to res>
(cons new-acc res)
res)))
;; call the helper skipping the current element in the result
;; and use that as the result on the secon call the includes it
(helper (cdr lst)
new-acc
(helper (cdr lst) acc res)))))
;; notice () is already in the results
(helper lst '() '(())))
Testing it is straightforward. I got some more results than you though but I believe it is correct:
(sum-zero '(3 4 -7 3 1 3 1 -4 -2 -2))
; ==> ((-7 -4 -2 -2 1 1 3 3 3 4)
; (-7 -4 -2 3 3 3 4)
; (-7 -2 -2 1 1 3 3 3)
; (-7 -4 1 1 3 3 3)
; (-7 -2 3 3 3)
; (-7 -2 -2 1 3 3 4)
; (-7 -4 1 3 3 4)
; (-7 -2 1 1 3 4)
; (-7 3 4)
; (-4 -2 1 1 4)
; (-4 -2 -2 1 3 4)
; (-2 -2 4)
; (-4 4)
; (-7 1 3 3)
; (-4 -2 -2 1 1 3 3)
; (-4 -2 3 3)
; (-2 1 1)
; (-2 -2 1 3)
; (-4 1 3)
; ())

Kadane's Algorithm in Scheme (Racket)

I understand the logic behind how Kadane's Algorithm (maximum sum of all sequential sub-arrays in an array) works in "pseudo-code," and I'm sure I could implement it as a function in C or C++. However, I'm trying to implement it using lists in Scheme (Racket; the file extension is .rkt), which I have no experience with.
The end result I'm looking for is...
Input: (maxsum `(1 4 -2 1))
Output: 5
So far I've developed two helper functions I may be able to use within the maxsum function.
(1) size: returns the number of elements in a list.
(define size
(lambda (list)
(cond
[(not (list? list)) 0]
[(null? list) 0]
[else (+ 1 (size (cdr list)))]
)
)
)
(2) sum: returns the sum of all elements in a list.
(define sum
(lambda (list)
(cond
[(not (list? list)) 0]
[(null? list) 0]
[else (+ (car list) (sum (cdr list)))]
)
)
)
How would I go about defining/designing the maxsum function?
Here is a version patterned after the Phyton code on wikipedia:
(define (maxsum lst)
(define (aux lst max-ending-here max-so-far)
(if (null? lst)
max-so-far
(let ((new-max-ending-here (max 0 (+ (car lst) max-ending-here))))
(aux (cdr lst) new-max-ending-here (max max-so-far new-max-ending-here)))))
(aux lst 0 0))
(maxsum '(1 4 -2 1)) ; => 5
(maxsum '(-2 1 -3 4 -1 2 1 -5 4)) ; => 6
It is tail recursive, so it will be compiled into an efficient iterative program.
Almost literal translation of [Python code][1] to Racket:
(define (max_subarray A)
(define-values (max_ending_here max_so_far) (values 0 0))
(for ((x (in-list A)))
(set! max_ending_here (max 0 (+ max_ending_here x)))
(set! max_so_far (max max_so_far max_ending_here)))
max_so_far)
Testing:
(max_subarray `(1 4 -2 1))
(max_subarray '(-2 1 -3 4 -1 2 1 -5 4))
Output:
5
6
Please note that recursive functions are generally preferred over iterative ones in Racket and use of "set!" is discouraged here.
Following uses higher functions like apply and map for different steps:
(define (maxsum lst)
(define subarrays
(for*/list ((start (length lst))
(len (range 1 (- (add1(length lst)) start))))
(take (drop lst start) len)))
(define sumlist (map (λ (x) (apply + x)) subarrays))
(apply max sumlist))
Following is more verbose form:
(define (maxsum lst)
(define subarrays
(for*/list ((start (length lst))
(len (range 1 (- (add1(length lst)) start))))
(take (drop lst start) len)))
(displayln "\n----- SUBARRAYS ---------")
(displayln subarrays)
(define sumlist (map (λ (x) (apply + x)) subarrays))
(displayln "----- SUMS OF SUBARRAYS ---------")
(displayln sumlist)
(display "MAX SUM:")
(apply max sumlist))
Testing:
(maxsum `(1 4 -2 1))
(maxsum '(-2 1 -3 4 -1 2 1 -5 4))
Output:
----- SUBARRAYS ---------
((1) (1 4) (1 4 -2) (1 4 -2 1) (4) (4 -2) (4 -2 1) (-2) (-2 1) (1))
----- SUMS OF SUBARRAYS ---------
(1 5 3 4 4 2 3 -2 -1 1)
MAX SUM:5
----- SUBARRAYS ---------
((-2) (-2 1) (-2 1 -3) (-2 1 -3 4) (-2 1 -3 4 -1) (-2 1 -3 4 -1 2) (-2 1 -3 4 -1 2 1) (-2 1 -3 4 -1 2 1 -5) (-2 1 -3 4 -1 2 1 -5 4) (1) (1 -3) (1 -3 4) (1 -3 4 -1) (1 -3 4 -1 2) (1 -3 4 -1 2 1) (1 -3 4 -1 2 1 -5) (1 -3 4 -1 2 1 -5 4) (-3) (-3 4) (-3 4 -1) (-3 4 -1 2) (-3 4 -1 2 1) (-3 4 -1 2 1 -5) (-3 4 -1 2 1 -5 4) (4) (4 -1) (4 -1 2) (4 -1 2 1) (4 -1 2 1 -5) (4 -1 2 1 -5 4) (-1) (-1 2) (-1 2 1) (-1 2 1 -5) (-1 2 1 -5 4) (2) (2 1) (2 1 -5) (2 1 -5 4) (1) (1 -5) (1 -5 4) (-5) (-5 4) (4))
----- SUMS OF SUBARRAYS ---------
(-2 -1 -4 0 -1 1 2 -3 1 1 -2 2 1 3 4 -1 3 -3 1 0 2 3 -2 2 4 3 5 6 1 5 -1 1 2 -3 1 2 3 -2 2 1 -4 0 -5 -1 4)
MAX SUM:6

How do I use a treemap for a 2 dimensional keys?

I want to map a large number of tuples. My map looks something like:
{[1 2] :thing}
Except there may be a few million of them. I have a feeling that a tree-map might be a good thing to test so I'm trying to get it working. I can't seem to get the comparison function right though.
(defn compare
[[x y] [xx yy]]
(cond
(and (= x xx) (= y yy)) 0
(and (<= x xx) (<= y yy)) -1
(and (<= x xx) (> y yy)) -1
(and (> x xx) (<= y yy)) 1
(and (> x xx) (> y yy)) 1))
Some trivial inputs seem to work
user=> (compare [1 1] [1 1])
0
user=> (compare [1 1] [2 2])
-1
user=> (compare [1 2] [2 1])
-1
user=> (compare [2 1] [1 2])
1
But if I create inputs that cover all combinations, the map should consider them all different.
(def inputs
"All tuples of [0-4, 5-10]."
(clojure.math.combinatorics/cartesian-product
(range 0 4)
(range 5 10)))
(def input-pairs
"All possible pairs of tuples"
(clojure.math.combinatorics/cartesian-product inputs inputs))
If I test the comparison function, it returns zero only when the two vectors are structurally identical.
user=> (doseq [[a b] input-pairs]
#_=> (when (zero? (compare a b)) (prn a b)))
(0 5) (0 5)
(0 6) (0 6)
(0 7) (0 7)
(0 8) (0 8)
(0 9) (0 9)
(1 5) (1 5)
etc
So I think my compare function is correct. Using it in the treemap, however, gives some strange results:
(def inputs-kvs
"Inputs in the format that the hash-map and sorted-map constructor understand"
(mapcat #(vector % (apply str %))
(clojure.math.combinatorics/cartesian-product
(range 0 4)
(range 5 10))))
Putting these in a hashmap gives the correct answer
(count (apply assoc (hash-map) inputs-kvs))
=> 20
But putting them in the treemap with the given comparison:
(def structure (sorted-map-by compare))
(count (apply assoc structure inputs-kvs))
=> 4
(apply assoc structure inputs-kvs)
=> {(0 5) "25", (1 6) "36", (2 7) "37", (3 5) "39"}
"25" has been stored in the (0 5) slot. But the compare function doesn't say that (0 5) and (2 5) are the same:
=> (compare [0 5] [2 5])
-1
What am I doing wrong? Can I make this work? Is it even meaningful to project a 2-dimensional space onto a 1-dimensional one?
(To head off a question you may have, yes I've tried a 2-dimensional structure, e.g. (sorted-map 1 (sorted-map 2 :value)), but I'm trying to find alternatives with better performance)
Clojure already comes with it's own compare:
user=> (doc compare)
-------------------------
clojure.core/compare
([x y])
Comparator. Returns a negative number, zero, or a positive number
when x is logically 'less than', 'equal to', or 'greater than'
y. Same as Java x.compareTo(y) except it also works for nil, and
compares numbers and collections in a type-independent manner. x
must implement Comparable
Which behaves the same as OPs own function, but most likely is more efficient:
user=> (compare [1 1] [1 1])
0
user=> (compare [1 1] [2 2])
-1
user=> (compare [2 1] [1 2])
1
The behaviour is documented in the Section about Vectors (IPersistentVector) in the Data Structures docs:
Vectors are compared first by length, then each element is compared in order.
So you can just use sorted-map-by compare from core, or since that's the default anyway just sorted-map for your data structure:
user=> (def m (into {} (let [r #(- (rand-int 10) (rand-int 10))] (for [a (range -1 2) b (range -1 2)] [[(r) (r)] (str a b)]))))
#'user/m
user=> (>pprint m)
{[-7 -4] "10",
[-3 5] "01",
[-5 -7] "00",
[5 2] "11",
[-3 1] "-10",
[7 -4] "-11",
[0 -6] "0-1",
[3 1] "-1-1",
[-8 -1] "1-1"}
nil
user=> (>pprint (into (sorted-map-by compare) m))
{[-8 -1] "1-1",
[-7 -4] "10",
[-5 -7] "00",
[-3 1] "-10",
[-3 5] "01",
[0 -6] "0-1",
[3 1] "-1-1",
[5 2] "11",
[7 -4] "-11"}
nil
user=> (>pprint (into (sorted-map) m))
{[-8 -1] "1-1",
[-7 -4] "10",
[-5 -7] "00",
[-3 1] "-10",
[-3 5] "01",
[0 -6] "0-1",
[3 1] "-1-1",
[5 2] "11",
[7 -4] "-11"}
nil
user=> (assert (= (into (sorted-map-by compare) m) (into (sorted-map) m)))
nil
I just added (vec %) to keep the tuples vectors - should not change anything.
As you can see it works here.
Might it be you have a some older REPL stuff laying around - especially since you alias clojure.core/compare ?
; using your compare function
(def inp (mapcat #(vector (vec %) (apply str %))
(clojure.math.combinatorics/cartesian-product (range 0 4) (range 5 10))))
; => ([0 5] "05" [0 6] "06" [0 7] "07" [0 8] "08" ...
(count inp)
; => 40
(apply assoc structure inp)
; => {[0 9] "09", [0 8] "08", [0 7] "07", [0 6] "06", ....
(count (apply assoc structure inp))
; => 20

How to diff/substract two lists in Clojure

Example:
1 1 1 3 3 4 4 5 5 6 L1
1 3 3 4 5 L2
1 1 4 5 6 Res
Constraints:
The diff/subtract is defined as the "set" of elements from L1 minus (∖) L2
L2 is always a subset (⊆) of L1
The elements in L1 and L2 can have duplicates
The elements are primitives (int, string) and all of the same type
(clojure.set/difference) doesn't help here because of (3).
(defn diff [s1 s2]
(mapcat
(fn [[x n]] (repeat n x))
(apply merge-with - (map frequencies [s1 s2]))))
For example, given
(def L1 [1 1 1 3 3 4 4 5 5 6])
(def L2 [1 3 3 4 5 ])
then
(diff L1 L2)
;(1 1 4 5 6)
Here is one way to do it.
Steps:
1.Find the frequencies for each list
2.Diff the frequencies
3.Repeat each element for the remaining value of frequency.
(defn myminus [s1 s2]
(let [g1 (frequencies s1)
g2 (frequencies s2)
m (merge-with - g1 g2)
r (mapcat #(repeat (second %) (first %)) m)]
r))
If inputs are in order, as they appear to be, then you can do this lazily
(defn sdiff
[[x & rx :as xs] [y & ry :as ys]]
(lazy-seq
(cond
(empty? xs) nil
(empty? ys) xs
:else (case (compare x y)
-1 (cons x (sdiff rx ys))
0 (sdiff rx ry)
+1 (sdiff xs ry)))))
Given example:
(def L1 [1 1 1 3 3 4 4 5 5 6])
(def L2 [1 3 3 4 5])
(sdiff L1 L2) ;=> (1 1 4 5 6)
Lazy-sequence of numbers that are not Fibonacci numbers. (Notice we don't require constraint #2 -- the repeated 1's in the Fibonacci numbers do not cause a problem.)
(defn fibs [] (map first (iterate (fn [[c n]] [n (+ c n)]) [0 1])))
(take 20 (sdiff (range) (fibs)))
;=> (4 6 7 9 10 11 12 14 15 16 17 18 19 20 22 23 24 25 26 27)
Since L2 is always a subset of L1 you can group-by on both lists and just emit the key as many times as the difference is between the counts of each grouping.
(def L1 (list 1 1 1 3 3 4 4 5 5 6))
(def L2 (list 1 3 3 4 5 ))
(defn diff [l1 l2]
(let [a (group-by identity l1)
b (group-by identity l2)]
(mapcat #(repeat
(-
(count (second %))
(count (get b (key %))))
(key %)) a)))
(diff L1 L2)
;;(1 1 4 5 6)
(defn diff-subtract
"The diff-subtract is defined as the sum of elements from L1 minus L2"
[list1 list2]
(let [l1 (into {} (map #(vector (first %) %) (partition-by identity (sort list1))))
l2 (into {} (map #(vector (first %) %) (partition-by identity (sort list2))))]
(-> (map
#(repeat (- (count (l1 %)) (count (l2 %))) %)
(range 1 (inc (apply max (map first l1)))))
flatten)))
(diff-subtract [1 1 1 3 3 4 4 5 5 6] [1 3 3 4 5]) => (1 1 4 5 6)

Resources