Counting nodes in two different subtrees in clojure - clojure

Very new to Clojure and I haven't got a clue how to do this, i need to traverse a premade binary search tree and count the number of nodes in 2 difference subtrees like this question
https://uva.onlinejudge.org/external/116/11615.pdf
Thank you for any help at all, Just need a push to get started
(defn familytree [tree i x]
(cond
(= (first(tree) i) )
(count (zip/children))
(= (first(tree) x))
(count (zip/children))
:else
(familytree (rest tree)x i)
))
Input data
(def test1 '[ 1 [ 2 [ 4 [8 9 ] 5 [ 10 11 ]] 3 [ 6 [ 12 13 ] 7 [ 14 15 ]]]])

Cameron
Start with deciding which Clojure persistent data type you will store the information in. Once that is decided:
Take a look at Clojure zippers.
Take a look at Clojure walk
As you know about recursion, depending on how big a tree it is, you may elect to forego somethings like a zipper for straight forward recursion. In this case for, loop and reduce may be applicable.
Updated
Here is my understanding of the requirements:
Input tree will be in a vector/nested vector structure
Each vector in the tree has a 'node identifier' (in your case a number)
Require a function that counts the children for a node when a node matches some criteria
Should be able to specify multiple nodes for which counts will be returned
Given that, I've decided to use a zipper as it reasonably demonstrates the break down of logic to attain the requirement goals. I've also abstracted aspects to make it so the predicate for counting children may change.
You will need to read up on clojure.zip (there is a wealth of information on the inter-web for this.
The Counter
Now that the core traversal is covered (zippers) lets start with the counting function. As per requirements: regardless on how I arrive at a node I want to count the children of the node:
(defn count-children-at-node
"Takes a zipper location and counts
elements of it's chidren vector. Uses flatten on the
children to sequence all the elements for counting.
Returns a tuple identifiying the node and it's children count"
[loc]
(let [cnodes (zip/right loc)]
[:node (zip/node loc)
:count (if (nil? cnodes) ; test for no children
0
(count (flatten (zip/node cnodes))))]))
The Workhorse
This is where traversal occurs. It will be exhaustive so as to find all possible nodes of interest. Counts will also be inclusive (see results below). I also want to accumulate my results and have a flexible predicate function to test for inclusion in the results:
(defn find-nodes-to-count
"Accumulate results of performing a reduction function on a node in
the tree that matches the predicate criteria"
[acc predfn redfn loc]
(if (zip/end? loc)
acc
(if (predfn (zip/node loc))
(recur (conj acc (redfn loc)) predfn redfn (zip/next loc))
(recur acc predfn redfn (zip/next loc)))))
The Wrapper
With my core counter and traversal mechanisms in place, use a easy wrapping function to exercise the core:
(defn nodes-counter
"Takes a tree collection and variable number of node identifiers
and return an accumulation of tuples, each identifying the node and it's children
count"
[coll & nodevals]
(find-nodes-to-count
[] ; accumultator
#(contains? (into #{} nodevals) %) ; predicate function
count-children-at-node ; reduction function
(zip/vector-zip coll))) ; the tree collection
Test/Verify
Some REPL examples of calling nodes-counter with node identifier variations:
(def mytree [1 [2 [4 [8 9] 5 [ 10 11 ]] 3 [ 6 [ 12 13 ] 7 [ 14 15 ]]]])
(nodes-counter mytree 16) ; => []
(nodes-counter mytree 15) ; => [[:node 15 :count 0]]
(nodes-counter mytree 2 4) ; => [[:node 2 :count 6] [:node 4 :count 2]]
(nodes-counter mytree 4 2) ; => [[:node 2 :count 6] [:node 4 :count 2]]

Related

How to generate all the permutations of elements in a list one at a time in Lisp?

I already have the code to generate all the permutations for a list of elements. However, I realized that if I want to manipulate the lists that are generated, I would need to traverse this list. This list can be potentially massive and therefore expensive to keep. I wanted to know if there was a way to generate the permutations by each call so that I can check if the list matches with what I need and if not I will generate the next permutation. (Each time the function will return a list one at a time.)
My code:
(defun allPermutations (list)
(cond
((null list) nil)
((null (cdr list)) (list list))
(t (loop for element in list
append (mapcar (lambda (l) (cons element l))
(allPermutations (remove element list)))))))
General principle
Suppose you have the following range function:
(defun range (start end &optional (step 1))
(loop for x from start below end by step collect x))
You can accept another parameter, a function, and call it for each element:
(defun range-generator (callback start end &optional (step 1))
(loop for x from start below end by step do (funcall callback x)))
This gives the caller control over the iteration process:
(block root
(range-generator (lambda (v)
(print v)
(when (>= v 10)
(return-from root)))
0 300))
0
1
2
3
4
5
6
7
8
9
10
See RETURN, BLOCK.
Permutations
If you want to avoid allocating too much memory, you can arrange for your code to allocate intermediate data-structures once and reuse them for each call to the callback. Here is an annotated example:
(defun permutations% (list callback)
(when list
(let* (;; Size of input list
(size (length list))
;; EMPTY is a sentinel value which is guaranteed to
;; never be equal to any element from LIST.
(empty (gensym "SENTINEL"))
;; Working vector containing elements from LIST, or
;; EMPTY. This vector is mutated to remember which
;; element from the input LIST was already added to the
;; permutation.
(items (make-array size :initial-contents list))
;; Working vector containing the current
;; permutation. It contains a FILL-POINTER so that we
;; can easily call VECTOR-PUSH and VECTOR-POP to
;; add/remove elements.
(permutation (make-array (length items) :fill-pointer 0)))
;; Define a local recursive function named POPULATE, which
;; accepts a COUNT argument. The count starts at SIZE and
;; decreases at each recursive invocation, allowing the
;; function to know when it should end.
(labels ((populate (count)
(if (plusp count)
;; Loop over ITEMS by index
(dotimes (item-index size)
(let ((item (svref items item-index)))
;; We found an ITEM which is not yet
;; present in PERMUTATION.
(unless (eq item empty)
;; Push that element
(vector-push item permutation)
;; Replace current value in ITEMS by EMPTY
(setf (svref items item-index) empty)
;; POPULATE will recursively populate
;; the remaining elements in
;; PERMUTATION and call CALLBACK. Once
;; it is done, it will return here.
(populate (1- count))
;; There are other items to process in
;; current loop. Reset the state to how
;; it was before calling POPULATE.
;; Replace the EMPTY value by the
;; original ITEM at current index.
(setf (svref items item-index) item)
;; Remove ITEM from PERMUTATION.
(vector-pop permutation))))
;; We filled PERMUTATION with SIZE elements.
;; Call CALLBACK with PERMUTATION. Note: the
;; callback function is always given the same
;; vector, but its content changes over
;; time. The value passed to CALLBACK is thus
;; valid only during the time we are
;; executing CALLBACK. If the caller needs to
;; keep a copy of the current permutation, it
;; should COPY-LIST the value.
(funcall callback permutation))))
;; Initiate recursive function with current SIZE.
(populate size)))))
The function accepts a list and a callback, which is a function accepting one parameter, the current permutation. Note that this parameter is valid only during the dynamic extent of the call, because once the call returns, the same data-structure that was passed to the callback is modified.
As explained above, you can call any function, in particular closure which refers to other variable in the lexical environment. Here, the anonymous lambda increment the count variable, which allows to count the number of permutations, without storing them in a list and getting the size of the list:
(time
(let ((count 0))
(permutations% '(a b c d e f g h i j k) (lambda (p) (incf count)))
count))
=> 39916800
Evaluation took:
6.455 seconds of real time
6.438200 seconds of total run time (6.437584 user, 0.000616 system)
99.74% CPU
17,506,444,509 processor cycles
0 bytes consed
In the above report, 0 bytes consed represents the approximate number of memory allocated (not counting stack allocation).
You can also offer a safer version of the function which copies each permutation before sending it to the callback function.
(defun permutations (list callback)
(permutations% list (lambda (permutation)
(funcall callback (coerce permutation 'list)))))
See also
See also the answer from Will Ness, which manages to handle the set of remaining elements with a list, thus avoiding the need to filter through EMPTY elements.
Here's a way (following the code structure by #coredump from their answer; runs about 4x faster on tio.run):
(defun permutations (list callback)
(if (null list)
(funcall callback #())
(let* ((all (cons 'head (copy-list list))) ; head sentinel FTW!
(perm (make-array (length list))))
(labels
((g (p i &aux (q (cdr p))) ; pick all items in arbitrary order:
(cond
((cdr q) ; two or more items left:
(loop while q do ; for each item in q:
(setf (svref perm i) (car q)) ; grab the item
(rplacd p (cdr q)) ; pluck it out
(g all (1+ i)) ; get the rest!
(rplacd p q) ; then, put it back
(pop p) ; and advance
(pop q))) ; the pointers
(T ; one last item left in q:
(setf (svref perm i) (car q)) ; grab the last item
(funcall callback perm))))) ; and call the callback
(g all 0)))))
Testing:
; [20]> (permutations '(1 2 3) #'(lambda (x) (princ x) (princ #\ )))
; #(1 2 3) #(1 3 2) #(2 1 3) #(2 3 1) #(3 1 2) #(3 2 1)
; [58]> (let ((acc (list))) (permutations '(1 2 3) #'(lambda (x)
; (push (coerce x 'list) acc))) (reverse acc))
; ((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1))
; [59]> (let ((acc (list))) (permutations '() #'(lambda (x)
; (push (coerce x 'list) acc))) (reverse acc))
; (NIL)
This uses recursion to build the n nested loops computational structure for the n-long input list, at run time, with the fixed i = 0, 1, ..., n-1 in each nested loop being the position in the result-holding permutation array to put the picked item into. And when all the n positions in the array are filled, once we're inside the innermost loop (which isn't even a loop anymore as it has just one element left to process), the user-supplied callback is called with that permutation array as its argument. The array is reused for each new permutation.
Implements the "shrinking domains" paradigm as in this high-level pseudocode with list splicing and pattern matching:
perms [] = [[]]
perms xs = [[x, ...p]
FOR [as, [x, ...bs]] IN (splits xs) -- pluck x out
FOR p IN perms [...as, ...bs]] -- and recurse
(where splits of a list produces all possible pairs of its sublists which, appended together, reconstitute the list; in particular, splits [] = [ [[],[]] ] and splits [1] = [ [[],[1]] , [[1],[]] ]); or, in a simple imperative pseudocode,
for item1 in list:
domain2 = remove item1 from list by position
for item2 in domain2:
domain3 = remove item2 from domain2 by position
for item3 in domain3:
......
......
for item_n in domain_n:
(callback
(make-array n :initial-contents
(list item1 item2 ... item_n)))
but in the real code we do away with all the quadratic interim storage used by this pseudocode, completely, by surgically manipulating the list structure. About the only advantage of the linked lists is their O(1) node removal capability; we might as well use it!
update: special-casing the last two elements of a permutation as well (by unrolling the last loop into the corresponding two calls to the callback) gives about ~ 1.5x additional speedup.
(In case the TIO link ever rots, here's a pastebin with the working code, or a github gist.)
update: this technique is known as recursive-backtracking, creating the n nested loops backtracking computational structure by recursion.

Clojure tree node based on depth

I've been struggling with a recursion problem and I'm running out of ideas. Basically, I have a tree representation that looks like this:
{1 {:root nil} 2 {:root 1} 3 {:root 1} 4 {:root 2} 5 {:root 1} 6 {:root 4}}
And I have to build a new tree out of the last one which indicates parent/child relationship levels. A valid output would be:
{ 1 [3 1] 2 [1] 3 [] 4 [1] 5 [] 6 [] }
Where each node has an array of a count of items by level of relationship. So node 1 has 3 direct children (2 3 5) and one grandchild (4). Node 2 has only one child (4), node 4 has one direct child (6) and all the others are empty (have no children).
I found some questions like this one that actually helped but aren't exactly what I was looking for. I'm also new to function programming and any help is going to be appreciated.
I'm going to assume that there is an error in your sample output above and that it should really be:
{ 1 [3 1 1] 2 [1 1] 3 [] 4 [1] 5 [] 6 [] }
Your sample output did not account for the fact that 6 is a great-grandchild of 1 and a grandchild of 2.
I'll detail a solution here. We'll start out by writing a function which, given a tree and a vertex in that tree, calculates the path from that vertex to the top of the tree:
(defn path-to-top [tree v]
(if (nil? v)
'()
(cons v (path-to-top tree (:root (get tree v))))))
Next up, let us write a function which takes such a path from the vertex to the top of the tree and associates with each vertex on the distance of that vertex from the starting vertex:
(defn steps-indexed-path
([upward-path steps]
(if (= upward-path '())
'()
(cons [(first upward-path) steps] (steps-indexed-path (rest upward-path) (+ steps 1)))))
([upward-path]
(steps-indexed-path upward-path 0)))
Where the first function returned a list of vertices, this function returns a list of vectors in which the first entry is a vertex and the second entry is the number of steps from the first vertex on the path to the given vertex.
Alright, when we apply this function to each of the vertices in the tree, we will have (in some nested form) for each vertex v and for each descendant w of v the data [v <# steps from v to w>]. For each of these data, we should add 1 to the <# steps from v to w> component of the vector associated with v in our final solution. Before we move to the vector stage, let us just associate levels with counts:
(defn count-descendants [tree]
(let [markers (reduce concat '() (map steps-indexed-path (map (partial path-to-top tree) (keys tree))))]
(reduce (fn [counter [vertex generation]] (assoc counter vertex (assoc (get counter vertex {}) generation (+ (get (get counter vertex {}) generation 0) 1)))) {} markers)))
This produces a hash-map whose keys are the vertices of v and such that the value corresponding to each vertex v is another hash-map in which the keys are the different possible generations of descendants of that vertex in the tree, and the values are the number of descendants at each generation.
All we have to do now is turn the output of the previous function into the format specified by you:
(defn sanitize-descendant-counts [association]
(let [max-depth (apply max (keys association))]
(map (fn [i] (get association i 0)) (range 1 (+ max-depth 1)))))
(defn solve-problem [tree]
(let [descendant-counts (count-descendants tree)]
(apply merge (map (fn [v] (hash-map v (vec (sanitize-descendant-counts (get descendant-counts v))))) (keys descendant-counts)))))
This is what I get as output when I run this code on your example:
{1 [3 1 1], 4 [1], 6 [], 3 [], 2 [1 1], 5 []}
You can access all the code here, including what you need to run on your example. Hope that helps!
I will try to outline a possible approach, stressing the recursion core, and glossing over smaller details. There are quite a few of those smaller details, and some of them aren't exactly trivial, but they have nothing to do with the recursion itself, and would just clutter the answer.
Let's abstract from the details of your tree representation. Think about a tree as a collection of nodes, where each node may be either a leaf (no children,) or a branch otherwise. Assume we have two functions branch? and children. Either receives one parameter - a node. branch? is a predicate with an obvious meaning, children returns a sequence of children of the node. (It is the same contract as expected by tree-seq core function.) I leave it to you to code branch? and children. (You may want to change your tree representation to make it easier to code these functions.)
Let's try to create a function levels that given a node will return a sequence of number of descendants by levels - children, grandchildren and so on. So we would expect for your tree
(levels 1)
;; => (3 1 1)
(levels 2)
;; => (1 1)
(You got a typo, by the way. Node 1 has a grand-grandchild - it's 6)
And here's the core - levels:
(defn levels
[node]
(if (branch? node)
(cons (count (children node)) (sum-up-levels (map levels (children node))))
[]))
This is the meat of the recursion. The base case is the leaf - when branch? returns false we know there are no children, so the levels are empty - []. Otherwise, we count the children and cons that number (i.e. add to the list) of the summed up levels below. Summing up means summing the numbers by levels - total number of children, then total number of grandchildren and so on. And here we have the recursion - we descend down to the children, invoking levels recursively for every child using map.
The sum-up-levels function is a bit annoying to code. I am leaving so much for you to fill in that I'd probably just give my code of it here (certainly not the shortest possible, but I don't have more time to polish it.)
(defn reduce-through
[f & colls]
(when-let [colls (seq (filter seq colls))]
(cons (reduce f (map first colls))
(apply reduce-through f (map rest colls)))))
(defn sum-up-levels
[levels]
(apply reduce-through + levels))
After having levels defined, it's easy to get the result in the form you need. Try it (a hint - use tree-seq.)
(defn children-depths [parents]
(let [children ; let's first build an inverted index
(reduce-kv (fn [children node {parent :root}]
(update children parent conj node))
{} parents)
depths (fn depths [node]
(if-some [nodes (children node)]
(into [(count nodes)]
; pads and sums
(reduce #(map + (concat %1 (repeat 0)) (depths %2))
nil nodes))
[]))] ; no descendants -> empty
(into {} (for [node (keys parents)] [node (depths node)]))))
=> (children-depths {1 {:root nil} 2 {:root 1} 3 {:root 1} 4 {:root 2} 5 {:root 1} 6 {:root 4}})
{1 [3 1 1], 2 [1 1], 3 [], 4 [1], 5 [], 6 []}
One obvious improvement would be to avoid recomputing depths of children.

Append to clojure vector from within loop

I have:
(defn keep?
(def sum [])
(loop [i 0]
(when (< i 10)
(conj sum 10)
(recur (inc i))))
sum
)
This just gives me and empty vector even though I am conj-ing 10 onto sum. Is this because it is not in-scope within the Loop? How would I achieve the same outcome. (btw, this example is deliberately simplified)
Thanks
conj does not modify its argument. In fact, without resorting to evil reflection tricks, nothing will modify a vector, it's an immutable data structure. This is one of the fundamental principles of Clojure.
In functional programming, instead of modifying data, we replace it with another immutable value. So you need to use the return value of conj, or it is effectively a noop.
(defn keep?
[]
(loop [i 0 sum []]
(if (< i 10)
(recur (inc i) (conj sum 10))
sum)))
Also, the second arg to defn must always be a vector.
conj is not destructive, it does not alter that collection, returns a new collection with the designated state (reference).
To achieve the desired result, you may:
Define sum in a loop-form, like i is defined, instead of using def
recur (inc i) (conj sum 10) to rebind sum to a new one on every iteration, so that state is built up to what you expect
Once the condition in when is not met, just return sum from your loop and it will bubble up to become the return value of this function. Uh hang on, when does not have an "else-branch", a possible alternative is if
Like so:
(defn keep? []
(loop [i 0
sum []]
(if (< i 10)
(recur (inc i)
(conj sum 10))
sum)))
Just to supplement the other answers, I almost never use the loop function. Here are a few ways to do it using the for function:
; return a lazy sequence
(for [i (range 10) ]
i)
;=> (0 1 2 3 4 5 6 7 8 9)
; return a concrete vector
(vec
(for [i (range 10) ]
i))
;=> [0 1 2 3 4 5 6 7 8 9]
; 'into' is very nice for converting one collection into another
(into #{}
(for [i (range 10) ]
i))
;=> #{0 7 1 4 6 3 2 9 5 8} ; hash-set is unique but unordered

find all subsets of an integer collection that sums to n

i'm trying to find a function that, given S a set of integer and I an integer, return all the subsets of S that sum to I
is there such a function somewhere in clojure-contrib or in another library ?
if no, could anyone please give me some hints to write it the clojure way?
Isn't this the subset sum problem, a classic NP-complete problem?
In which case, I'd just generate every possible distinct subset of S, and see which subsets sums to I.
I think it is the subset sum problem, as #MrBones suggests. Here's a brute force attempt using https://github.com/clojure/math.combinatorics (lein: [org.clojure/math.combinatorics "0.0.7"]):
(require '[clojure.math.combinatorics :as c])
(defn subset-sum [s n]
"Return all the subsets of s that sum to n."
(->> (c/subsets s)
(filter #(pos? (count %))) ; ignore empty set since (+) == 0
(filter #(= n (apply + %)))))
(def s #{1 2 45 -3 0 14 25 3 7 15})
(subset-sum s 13)
; ((1 -3 15) (2 -3 14) (0 1 -3 15) (0 2 -3 14) (1 2 3 7) (0 1 2 3 7))
(subset-sum s 0)
; ((0) (-3 3) (0 -3 3) (1 2 -3) (0 1 2 -3))
These "subsets" are just lists. Could convert back to sets, but I didn't bother.
You can generate the subsets of a set like this:
(defn subsets [s]
(if (seq s)
(let [f (first s), srs (subsets (disj s f))]
(concat srs (map #(conj % f) srs)))
(list #{})))
The idea is to choose an element from the set s: the first, f, will do. Then we recursively find the subsets of everything else, srs. srs comprises all the subsets without f. By adding f to each of them, we get all the subsets with f. And together, that's the lot. Finally, if we can't choose an element because there aren't any, the only subset is the empty one.
All that remains to do is to filter out from all the subsets the ones that sum to n. A function to test this is
(fn [s] (= n (reduce + s)))
It is not worth naming.
Putting this together, the function we want is
(defn subsets-summing-to [s n]
(filter
(fn [xs] (= n (reduce + xs)))
(subsets s)))
Notes
Since the answer is a sequence of sets, we can make it lazier by changing concat into lazy-cat. map is lazy anyway.
We may appear to be generating a lot of sets, but remember that they share storage: the space cost of keeping another set differing by a single element is (almost) constant.
The empty set sums to zero in Clojure arithmetic.

Clojure: How to replace an element in a nested list?

I have this deeply nested list (list of lists) and I want to replace a single arbitrary element in the list. How can I do this ? (The built-in replace might replace many occurrences while I need to replace only one element.)
As everyone else already said, using lists is really not a good idea if you need to do this kind of thing. Random access is what vectors are made for. assoc-in does this efficiently. With lists you can't get away from recursing down into the sublists and replacing most of them with altered versions of themselves all the way back up to the top.
This code will do it though, albeit inefficiently and clumsily. Borrowing from dermatthias:
(defn replace-in-list [coll n x]
(concat (take n coll) (list x) (nthnext coll (inc n))))
(defn replace-in-sublist [coll ns x]
(if (seq ns)
(let [sublist (nth coll (first ns))]
(replace-in-list coll
(first ns)
(replace-in-sublist sublist (rest ns) x)))
x))
Usage:
user> (def x '(0 1 2 (0 1 (0 1 2) 3 4 (0 1 2))))
#'user/x
user> (replace-in-sublist x [3 2 0] :foo)
(0 1 2 (0 1 (:foo 1 2) 3 4 (0 1 2)))
user> (replace-in-sublist x [3 2] :foo)
(0 1 2 (0 1 :foo 3 4 (0 1 2)))
user> (replace-in-sublist x [3 5 1] '(:foo :bar))
(0 1 2 (0 1 (0 1 2) 3 4 (0 (:foo :bar) 2)))
You'll get IndexOutOfBoundsException if you give any n greater than the length of a sublist. It's also not tail-recursive. It's also not idiomatic because good Clojure code shies away from using lists for everything. It's horrible. I'd probably use mutable Java arrays before I used this. I think you get the idea.
Edit
Reasons why lists are worse than vectors in this case:
user> (time
(let [x '(0 1 2 (0 1 (0 1 2) 3 4 (0 1 2)))] ;'
(dotimes [_ 1e6] (replace-in-sublist x [3 2 0] :foo))))
"Elapsed time: 5201.110134 msecs"
nil
user> (time
(let [x [0 1 2 [0 1 [0 1 2] 3 4 [0 1 2]]]]
(dotimes [_ 1e6] (assoc-in x [3 2 0] :foo))))
"Elapsed time: 2925.318122 msecs"
nil
You also don't have to write assoc-in yourself, it already exists. Look at the implementation for assoc-in sometime; it's simple and straightforward (compared to the list version) thanks to vectors giving efficient and easy random access by index, via get.
You also don't have to quote vectors like you have to quote lists. Lists in Clojure strongly imply "I'm calling a function or macro here".
Vectors (and maps, sets etc.) can be traversed via seqs. You can transparently use vectors in list-like ways, so why not use vectors and have the best of both worlds?
Vectors also stand out visually. Clojure code is less of a huge blob of parens than other Lisps thanks to widespread use of [] and {}. Some people find this annoying, I find it makes things easier to read. (My editor syntax-highlights (), [] and {} differently which helps even more.)
Some instances I'd use a list for data:
If I have an ordered data structure that needs to grow from the front, that I'm never going to need random-access to
Building a seq "by hand", as via lazy-seq
Writing a macro, which needs to return code as data
For the simple cases a recursive substitution function will give you just what you need with out much extra complexity. when things get a little more complex its time to crack open clojure build in zipper functions: "Clojure includes purely functional, generic tree walking and editing, using a technique called a zipper (in namespace zip)."
adapted from the example in: http://clojure.org/other_libraries
(defn randomly-replace [replace-with in-tree]
(loop [loc dz]
(if (zip/end? loc)
(zip/root loc)
(recur
(zip/next
(if (= 0 (get-random-int 10))
(zip/replace loc replace-with)
loc)))))
these will work with nested anything (seq'able) even xmls
It sort of doesn't answer your question, but if you have vectors instead of lists:
user=> (update-in [1 [2 3] 4 5] [1 1] inc)
[1 [2 4] 4 5]
user=> (assoc-in [1 [2 3] 4 5] [1 1] 6)
[1 [2 6] 4 5]
So if possible avoid lists in favour of vectors for the better access behaviour. If you have to work with lazy-seq from various sources, this is of course not much of an advice...
You could use this function and adapt it for your needs (nested lists):
(defn replace-item
"Returns a list with the n-th item of l replaced by v."
[l n v]
(concat (take n l) (list v) (drop (inc n) l)))
A simple-minded suggestion from the peanut gallery:
copy the inner list to a vector;
fiddle that vector's elements randomly and to your heart's content using assoc;
copy the vector back to a list;
replace the nested list in the outer list.
This might waste some performance; but if this was a performance sensitive operation you'd be working with vectors in the first place.