I ran into this error when I try to evaluate the last line below: "No message. [Thrown class java.lang.NullPointerException]"
(defn my-insertion-sort [lst]
(loop [list lst result '()]
(if-not (seq? list) result
(recur (rest list) (my-insert (first list) result)))))
(defn my-insert [n lst]
(cond (nil? lst) (list n)
(> (first lst) n) (conj lst n)
:else
(conj (my-insert n (rest lst)) (first lst))))
(my-insertion-sort '(2 1 3))
Where goes wrong with "my-insertion-sort" function?
(defn my-insertion-sort [lst]
(loop [list lst result '()]
(if (empty? list) result
(recur (rest list) (my-insert (first list) result)))))
(defn my-insert [n lst]
(cond
(empty? lst) (list n)
(> (first lst) n) (conj lst n)
:else (conj (my-insert n (rest lst)) (first lst))))
Related
I'm reading the book The Little Schemer, I implement the functions in Clojure, How to rewrite this function as a tail-recursive function in Clojure?
(defn rember*
[a lat]
(cond
(empty? lat) []
(clojure.inspector/atom? (first lat))
(if (= a (first lat))
(rember* a (rest lat))
(cons (first lat)
(rember* a (rest lat))))
:else
(cons (rember* a (first lat))
(rember* a (rest lat)))))
Here is a translation of your code to a version that uses a loop and two lists instead of recursion in order to maintain program state:
(defn rember* [a lat]
(loop [[[op-type a lat] & rest-ops] (list [:rember a lat])
data '()]
(case op-type
nil (first data)
:value (recur rest-ops (cons a data))
:rember (cond
(empty? lat) (recur rest-ops (cons '() data))
(clojure.inspector/atom? (first lat))
(if (= a (first lat))
(recur (cons [:rember a (rest lat)] rest-ops) data)
(recur (into rest-ops [[:cons]
[:rember a (rest lat)]
[:value (first lat)]])
data))
:else (recur (into rest-ops [[:cons]
[:rember a (rest lat)]
[:rember a (first lat)]])
data))
:cons (let [[a b & data] data]
(recur rest-ops (cons (cons b a) data))))))
I agree, loop-recur is the more clojuresk answer!
But for a tail-recursive version, you could also do:
(def atom? (complement coll?))
(defn rember*
([a lat] (rember* a lat []))
([a lat acc]
(cond (empty? lat) (seq acc) ;; or just `acc` when result should be vector
(atom? (first lat)) (if (= a (first lat))
(rember* a (rest lat) acc)
(rember* a (rest lat) (conj acc (first lat))))
:else (rember* a (rest lat) (conj acc (rember* a (first lat)))))))
With this, you can easily build loop-recur by replacing the recursive function call using recur. However note that the last call of rember* cannot be placed by recur - because you cannot nest recur calls.
(defn rember* [a lat]
(loop [a a
lat lat
acc []]
(cond (empty? lat) (seq acc)
(atom? (first lat)) (if (= a (first lat))
(recur a (rest lat) acc)
(recur a (rest lat) (conj acc (first lat))))
:else (recur a (rest lat) (conj acc (rember* a (first lat)))))))
This assignment for a class I'm in has me pretty confused. I was able to get most of the function working but this one part is what's keeping me from completing it. I have two functions which is what I need one is to find the highest number value in a list (largest-num) and the other situates the list and is what refers to it (max-lon). I get the following error largest-num: expects only 1 argument, but found 2 and im not quite sure how to fix it. Code is listed:
(define (max-lon a-lon)
(local [
(define ACUMM (void))
(define lst (void))
;; lon number → number
;; Purpose: Return max(max of given list, given number)
;; Accumulator Invariant: accum = maximum in L - lst
(define (max-helper)
(if(empty? lst)
ACUMM
(begin
(set! ACUMM (largest-num (first lst) ACUMM))
(set! lst (rest lst))
(max-helper))))]
(if (empty? a-lon)
(error 'max-lon "An empty lon does not have a maximum.")
(begin
(set! ACUMM(first a-lon))
(set! lst (rest a-lon))
(max-helper)))))
(define (largest-num lst)
(cond
[(empty? (rest lst)) (first lst)]
[(< (first lst) (first (rest lst))) (largest-num (rest lst))]
[else (largest-num (cons (first lst) (rest (rest lst))))]))
Any suggestions would be great, thank you
largest-num can be simplified a lot more since all it has to do is compare two numbers which is ACUMM which is the accumulator/place in the list and first lst is what holds the highest number rather than processing the whole list which I assumed at first, here is fixed code:
(define (max-lon a-lon)
(local [
(define ACUMM (void))
(define lst (void))
(define (max-helper)
(if(empty? lst)
ACUMM
(begin
(set! ACUMM (largest? ACUMM (first lst)))
(set! lst (rest lst))
(max-helper))))]
(if (empty? a-lon)
(error 'max-lon "An empty lon does not have a maximum.")
(begin
(set! ACUMM(first a-lon))
(set! lst (rest a-lon))
(max-helper)))))
(define (largest? a b)
(if (> a b) a b))
(define (largest-num lst (acc -inf.0))
(cond ((empty? lst) acc)
((and acc (> (car lst) acc)) (largest-num (cdr lst) (car lst)))
(else (largest-num (cdr lst) acc))))
I am trying to define the rule 3 of "MIU System" of "Gödel, Escher, Bach" (Douglas Hofstadter), which says:
Replace any III with a U
Example:
MIIIIU → MUIU and MIIIIU → MIUU
Main code:
(define (rule-tree lst)
(if (<= 3 (counter lst #\I))
(append (delete #\I lst) (list #\U))
(append lst empty)))
(define (delete x lst)
(cond [(empty? lst) lst]
[(eq? (first lst) x) (delete x (rest lst))]
[else (append (list (first lst)) (delete x (rest lst)))]))
(define (counter lst target)
(if (empty? lst)
0
(+ (counter (rest lst) target)
(let ((x (first lst)))
(if (list? x)
(counter x target)
(if (eqv? x target) 1 0))))))
With this expression there is no problem:
>(rule-tree '(#\M #\I #\I #\I))
'(#\M #\U)
But I don't know how to determine the position that the "U" should take when finding the 3 "I".
Any suggestion will be very helpful :)
Here is an alternative recursive version, where repl2 encodes the information “we have just encountered one #\I”, while repl3 encodes the information “we have just encountered two #\I”:
(define (repl lst)
(cond ((empty? lst) lst)
((eqv? (first lst) #\I) (repl2 (rest lst)))
(else (cons (first lst) (repl (rest lst))))))
(define (repl2 lst)
(cond ((empty? lst) (list #\I))
((eqv? (first lst) #\I) (repl3 (rest lst)))
(else (cons #\I (cons (first lst) (repl (rest lst)))))))
(define (repl3 lst)
(cond ((empty? lst) (list #\I #\I))
((eqv? (first lst) #\I) (cons #\U (repl (rest lst))))
(else (cons #\I (cons #\I (cons (first lst) (repl (rest lst))))))))
Of course this solution is some kind of hack and cannot scale to a greater number of repetitions. But looking at the structure of this solution and simply generalizing the three functions we can produce a general solution:
(define (repl lst n from to)
(define (helper lst k)
(cond ((empty? lst) (repeat from (- n k)))
((eqv? (first lst) from)
(if (= k 1)
(cons to (helper (rest lst) n))
(helper (rest lst) (- k 1))))
(else (append (repeat from (- n k))
(cons (first lst) (helper (rest lst) n))))))
(define (repeat x n)
(if (= n 0)
'()
(cons x (repeat x (- n 1)))))
We define a function repl that takes a list, the number of copies to replace (n), the element to replace (from) and the element that must be substituted (to). Then we define a helper function to do all the work, and that has as parameters the list to be processed and the number of copies that must be still found (k).
Each time the function encounters a copy it checks if we have finished with the number of copies and substitutes the element, restarting its work, otherwise it decrements the number of copies to find and continues.
If it founds an element different from from it recreates the list with the elements “consumed” until this point (maybe 0) with repeat and then continues its work.
Note that the previous version of the helper function had an error in the final case, when lst is null. Instead of returning simply the empty list, we must return the possibly skipped from elements.
I have a deeply nested list and I want to delete a given element from all its occurrences in the list. I have this code:
(defn eliminate [value lst]
(defn sub-eliminate [lst]
(def currentItem (first lst))
(if-not (empty? lst)
(if (seq? currentItem)
(cons (sub-eliminate currentItem) (sub-eliminate (rest lst)))
(if (= value currentItem)
(sub-eliminate (rest lst))
(cons currentItem (sub-eliminate (rest lst)))
)
)
'()
)
)
(sub-eliminate lst)
)
But, it doesn't delete at inner levels. Why??
My guess is that you're using vectors as sequences.
(eliminate 3 [3 3])
;()
(eliminate 3 [3 [3]])
;([3])
This would have been trivial to find had you shown us an example: tut, tut!
What's going on?
Although vectors are seqable, they are not sequences:
(seq? [])
;false
At the outer level, you treat lst as a sequence, so first and rest work, since they wrap their argument in an implicit seq. But seq? will fail on any immediately enclosed vector, and those further in won't even be seen.
If you replace seq? with sequential?, lists and vectors will work.
(sequential? [])
;true
More serious, as #noisesmith noted, is your use of def and defn at inner scope. Replace them with let or letfn.
You could also improve your style:
Replace (if-not (empty? lst) ... ) with (if (seq lst) ...).
Use cond to flatten your nested ifs. This requires inverting
the test in (1), so removes the need for it.
Use recur for the tail-recursive case where you find value, as
#Mark does.
If you don't want to see the result, look away now:
(defn eliminate [value lst]
(letfn [(sub-eliminate [lst]
(let [current-item (first lst)]
(cond
(empty? lst) '()
(sequential? current-item) (cons (sub-eliminate current-item)
(sub-eliminate (rest lst)))
(= value current-item) (recur (rest lst))
:else (cons current-item (sub-eliminate (rest lst))))))]
(sub-eliminate lst)))
There is a remaining tender spot:
You invoke (first lst) before you know that lst is not empty. No
harm done: you'll just get nil, which you ignore.
An Alternative Apporach using Destructuring
You can often use destructuring to abbreviate recursive processing of sequences. I'd be inclined to express your function thus:
(defn eliminate [x xs]
((fn rem-x [xs]
(if-let [[y & ys] (seq xs)]
(if (= x y)
(recur ys)
(cons
(if (sequential? y) (rem-x y) y)
(rem-x ys)))
()))
xs))
For the sake of learning take a look at this function:
(define rember*
(lambda (x l)
(cond ((null? l) '())
((atom? (car l))
(if (eq? (car l) x)
(rember* x (cdr l))
(cons (car l)
(rember* x (cdr l)))))
(else (cons (rember* x (car l))
(rember* x (cdr l)))))))
This is a simple recursive function from book 'The Little Schemer', which is a good source to learn how to write such recursive functions.
Let's see if we can translate it into Clojure:
(defn rember* [x l]
(cond (empty? l) '()
(seq? (first l)) (cons (rember* x (first l))
(rember* x (rest l)))
:else (if (= (first l) x)
(recur x (rest l))
(cons (first l)
(rember* x (rest l))))))
user> (rember* 'x '((x y) x (z (((((x))))))))
;; => ((y) (z ((((()))))))
(defn expel [victim xs]
(mapcat (fn [x]
(cond
(sequential? x) [(expel victim x)]
(= x victim) []
:else [x]))
xs))
I'm pretty new to closure and I don't understand why I'm getting this error message at runtime. Here is my code:
(defn invert [lst]
(if (empty? lst)
()
(cons (invert-helper lst) (invert (rest lst)))))
(defn invert-helper [lst]
(list (nth lst 1) (first lst)))
This should fix the problem:
(defn invert-helper [lst]
(list (nth lst 1) (first lst)))
(defn invert [lst]
(if (empty? lst)
()
(cons (invert-helper lst) (invert (rest lst)))))
That is: the invert-helper function must be defined before its first use in invert.
Another option, apart from defining all the functions before using them, may be declaring invert-helper before invert:
(declare invert-helper)
(defn invert [lst]
(if (empty? lst)
()
(cons (invert-helper lst) (invert (rest lst)))))
(defn invert-helper [lst]
(list (nth lst 1) (first lst)))
You're also calling (nth lst 1) where lst may have only one element - this will throw an exception.