In the clojure documentation it says:
Usage: (reduced x)
Wraps x in a way such that a reduce will terminate with the value x
I am trying to return from a reduce function with a boolean and a vector values.
(def bp (reduce (fn [[balanced stack] singlenum]
(def stack2 (conj stack singlenum))
(println stack2)
(if (= 2 singlenum)
(reduced [false stack2])
)
[balanced stack2]
)
[true (vector)] [1 2 3 4]
))
bp evaluates as [true [1 2 3 4]], I was expecting [false [1 2]]. The reduced did not terminate the reduce function. I was attempting to terminate the reduce function with a specific values.
You have the correct logic there. I just revised your usage of if and def.
if - I moved [balanced stack2] to the else part. Otherwise reduced will never be detected.
def - the def inside fn should be replaced with let
(def bp (reduce (fn [[balanced stack] singlenum]
(let [stack2 (conj stack singlenum)]
(println stack2)
(if (= 2 singlenum)
(reduced [false stack2])
[balanced stack2])))
[true (vector)]
[1 2 3 4]))
| | | | | stack=> []
| | | | | singlenum=> 1
| | | | (conj stack singlenum)=> [1]
| | | | stack2=> [1]
[1]
| | | (println stack2)=> nil
| | | | | singlenum=> 1
| | | | (= 2 singlenum)=> false
| | | | | balanced=> true
| | | | | stack2=> [1]
| | | (if (= 2 singlenum) (reduced #) [balanced stack2])=> [true [1]]
| | (let [stack2 #] (println stack2) (if # # #))=> [true [1]]
| | | | | stack=> [1]
| | | | | singlenum=> 2
| | | | (conj stack singlenum)=> [1 2]
| | | | stack2=> [1 2]
[1 2]
| | | (println stack2)=> nil
| | | | | singlenum=> 2
| | | | (= 2 singlenum)=> true
| | | | | | stack2=> [1 2]
| | | | (reduced [false stack2])=> #reduced[{:status :ready, :val [false [1 2]]} 0x5fbdbb78]
| | | (if (= 2 singlenum) (reduced #) [balanced stack2])=> #reduced[{:status :ready, :val [false [1 2]]} 0x5fbdbb78]
| | (let [stack2 #] (println stack2) (if # # #))=> #reduced[{:status :ready, :val [false [1 2]]} 0x5fbdbb78]
(reduce (fn # #) [true #] [1 2 3 4])=> [false [1 2]]
Related
After solving my error with values-list and being able to run my program until the end, I found that my diagonal check seems to have a logic error. My input is as follows:
(THREAT? '(1 3) '((1 0)(2 4)(3 0)(4 0)(5 0)(6 0)(7 0)(8 0)))
The first argument being a board space that we are testing is ok or not to place a queen and the second argument is the state of the board, y values 1-8 determine the column positions of a piece and a 0 value would indicate that x value row would hold no piece. My code is as follows:
(defun diagonal(point1 point2)
(= (abs (- ( car point1 ) ( car point2 )))
(abs (- ( cadr point1 ) ( cadr point2 ))))
)
(defun THREAT?(x y)
; Checks threat on the vertical
(when (not (eq (values-list (cdr (nth (- (car x) 1 ) y )) ) '0 ) )
(return-from THREAT? t)
)
(loop for i from 0 to (list-length y)
; Checks threat on the horizontal
when (eq (values-list ( cdr x )) (values-list (cdr (nth i y))) )
do (return-from THREAT? t)
; With the help of the diagonal function checks along the diagonal
when (diagonal x (nth i y) )
do (return-from THREAT? t)
)
)
If my understanding is correct my program should loop through every single element of y. It will pass the x and the current y pair to the diagonal function. The diagonal function will minus the two and absolute value them and check if they are equal (if they are diagonal then they should be ex. (1 2) and (2 3) are diagonal and therefore |1 - 2| = 1 and |2 - 3| = 1). The diagonal function should return true if these numbers are equivalent. The corresponding when statement should only activate when it receives a true from the diagonal function and yet it seems to always return true, even when I give the program a completely blank board. How do I fix diagonal to correctly determine a threat on the board? Any and all help is greatly appreciated!
I have rewritten your code to better Lisp style.
much better naming.
procedures with useful names make comments redundant
individual procedures are better testable
got rid of the VALUES-LIST nonsense
get rid of all CAR, CDR, CADR. Use FIRST and SECOND.
introduced accessors for x and y components of a point
got rid of the strange control flow with RETURN-FROM, replaced it with a simple OR
actually directly iterate over a list, instead of using NTH all the time
EQ is not for comparing number equality, use = instead
don't place parentheses alone on a line.
indent and format the code correctly
don't put spaces between parentheses
put a space between an atom and an open parenthesis
Code:
(defun get-x (point)
(first point))
(defun get-y (point)
(second point))
(defun diagonal? (point1 point2)
(= (abs (- (get-x point1) (get-x point2)))
(abs (- (get-y point1) (get-y point2)))))
(defun vertical? (point)
(not (zerop (get-y point))))
(defun horizontal? (point1 point2)
(= (get-y point1)
(get-y point2)))
(defun threat? (point list-of-columns)
(or (vertical? (nth (1- (get-x point)) list-of-columns))
(loop for point2 in list-of-columns
when (or (horizontal? point point2)
(diagonal? point point2))
return t)))
Example
Now we can trace the three threat predicates:
? (trace vertical? diagonal? horizontal?)
NIL
Now you can call your example:
? (threat? '(1 3) '((1 0) (2 4) (3 0) (4 0) (5 0) (6 0) (7 0) (8 0)))
0> Calling (VERTICAL? (1 0))
<0 VERTICAL? returned NIL
0> Calling (HORIZONTAL? (1 3) (1 0))
<0 HORIZONTAL? returned NIL
0> Calling (DIAGONAL? (1 3) (1 0))
<0 DIAGONAL? returned NIL
0> Calling (HORIZONTAL? (1 3) (2 4))
<0 HORIZONTAL? returned NIL
0> Calling (DIAGONAL? (1 3) (2 4))
<0 DIAGONAL? returned T
T
This should help, so that you can better debug your code... Look at the trace output.
A version which does not use empty column descriptions
(defun get-x (point)
(first point))
(defun get-y (point)
(second point))
(defun diagonal? (point1 point2)
(= (abs (- (get-x point1) (get-x point2)))
(abs (- (get-y point1) (get-y point2)))))
(defun vertical? (point list-of-columns)
(let ((point2 (find (get-x point) list-of-columns :key #'get-x)))
(and point2 (not (zerop (get-y point2))))))
(defun horizontal? (point1 point2)
(= (get-y point1)
(get-y point2)))
(defun threat? (point list-of-columns)
(or (vertical? point list-of-columns)
(loop for point2 in list-of-columns
when (or (horizontal? point point2)
(diagonal? point point2))
return t)))
(defun print-board (board)
(format t "~%+-+-+-+-+-+-+-+-+")
(dotimes (y 8)
(terpri)
(dotimes (x 8)
(format t "|~a" (if (member (list x y) board :test #'equal) "x" " ")))
(format t "|~%+-+-+-+-+-+-+-+-+")))
Example:
CL-USER 138 > (threat? '(1 2) '((2 4)))
NIL
CL-USER 139 > (print-board '((1 2) (2 4)))
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| |x| | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | |x| | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
NIL
Another example:
CL-USER 140 > (threat? '(1 2) '((2 4) (4 5)))
T
CL-USER 141 > (print-board '((1 2) (2 4) (4 5)))
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| |x| | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | |x| | | | | |
+-+-+-+-+-+-+-+-+
| | | | |x| | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
NIL
Suppose we define a relation matches via the following table:
|-----+-----+-----+-----+-----|
| | *A* | *B* | *C* | *D* |
|-----+-----+-----+-----+-----|
| *A* | | X | X | |
|-----+-----+-----+-----+-----|
| *B* | X | | | X |
|-----+-----+-----+-----+-----|
| *C* | X | | | |
|-----+-----+-----+-----+-----|
| *D* | | X | | |
|-----+-----+-----+-----+-----|
By this, it is meant that (in pseduo-code)
(matches A) ;=> (B C)
(matches B) ;=> (A D)
(matches C) ;=> (C)
(matches D) ;=> (B)
In core.logic, I think I would know how to make individualized functions which could approximate the behavior of matches:
(defn matches-A
(run* [q]
(membero q [B C]))) ;=> (B C)
...and so forth for matches-B and matches-C.
Question: How could I generalize, i.e., matches-A to a single function matches as above? In particular, I'd be interested in making it so that you could run queries like (matches "not A"), (matches "B and C") and (matches "C or D") (in pseudo-code) to get results like (A D), (A), and (A B) respectively. Is this possible?
NOTE: I'm using clojurescript instead of clojure. I'm not sure if that would impact the answer at all.
You can use conde to solve this task:
(ns qradv.welcome
(:require [cljs.core.logic :as l]))
;; |-----+-----+-----+-----+-----|
;; | | *A* | *B* | *C* | *D* |
;; |-----+-----+-----+-----+-----|
;; | *A* | | X | X | |
;; |-----+-----+-----+-----+-----|
;; | *B* | X | | | X |
;; |-----+-----+-----+-----+-----|
;; | *C* | X | | | |
;; |-----+-----+-----+-----+-----|
;; | *D* | | X | | |
;; |-----+-----+-----+-----+-----|
(defn matches [x]
(l/run* [y]
(l/conde
[(l/== x "A") (l/membero y ["B" "C"])]
[(l/== x "B") (l/membero y ["A" "D"])]
[(l/== x "C") (l/membero y ["C"])]
[(l/== x "D") (l/membero y ["B"])])))
(prn (matches "A"))
(prn (matches "B"))
(prn (matches "C"))
(prn (matches "D"))
Output:
("B" "C")
("A" "D")
("C")
("B")
While learning clojure, I was very surprised to find out that these two objects are different types:
(list? `(inc)) ;; true
(list? `(inc 1)) ;; false
In theory, I understand why the second form returns false, that object
is actually a clojure.lang.Cons. In practice, though, I don't
understand why that is happening.
Why does the reader read `(inc) different from `(inc 1)? What is happening under the hood?
When the reader encounters a syntax-quoted form, that turns out to be a collection, it will iterate over each element and call syntax-quote recursively. The result is consed, beginning with nil.
So it comes down to the question why the following holds:
> (list? (cons 'inc nil))
true
> (list? (cons 'inc (cons 1 nil)))
false
This seems to be a matter of definition.
list? is actually a function of very limited usefulness. In fact I have yet to see Clojure code that used list? without it being at best a poor choice, more often the cause of a bug.
If you want to know if something is "listy", seq? is a great choice.
in action:
user=> (pprint/print-table (for [item [[] () `(a) `(a b) (seq [1])]]
{'item (pr-str item)
'seq? (seq? item)
'list? (list? item)
'type (type item)}))
| item | seq? | list? | type |
|-----------------+-------+-------+------------------------------------------------|
| [] | false | false | class clojure.lang.PersistentVector |
| () | true | true | class clojure.lang.PersistentList$EmptyList |
| (user/a) | true | true | class clojure.lang.PersistentList |
| (user/a user/b) | true | false | class clojure.lang.Cons |
| (1) | true | false | class clojure.lang.PersistentVector$ChunkedSeq |
I'm trying to print out my binary tree but Clojure is giving me a hard time printing out the sequences properly.
So, I have a list of nodes '(1 2 3) for example.
In each iteration I want to print out the node with a number of spaces before and after each element.
(defn spaces [n]
(apply str (repeat n " ")))
Great, this seems to work.
So, suppose I have a list of nodes '(:a :b :c) I want to print out on one line, with as said, the spaces.
(println (map #(str (spaces before) % (spaces (dec before))) nodes))
I have a list of items. Using the map I get a list of string objects. Great, so I can print them!
But this gives me this:
(clojure.lang.LazySeq#d0b37c31 clojure.lang.LazySeq#105879a9 clojure.lang.LazySeq#8de18242)
So I googled how to print lazy sequences and I came around to using print-str command. According to the docs this prints to a string which then gets returned.
(println (print-str (map #(str (spaces before) % (spaces (dec before))) nodes)))
But this gives me this:
(clojure.lang.LazySeq#d0b37c31 clojure.lang.LazySeq#105879a9 clojure.lang.LazySeq#8de18242)
No change.. Hrm. Any help is greatly appreciated.
user> (str (map inc (range 10)))
"clojure.lang.LazySeq#c5d38b66"
user> (pr-str (map inc (range 10)))
"(1 2 3 4 5 6 7 8 9 10)"
The toString method of LazySeq is called by str, and this avoids realizing the lazy sequence of values by opaquely showing the Object identity. The pr-str function calls the print-dup multimethod of an object, which is designed to get the version of a thing that could be understood by the reader (so for a LazySeq the literal value that would make an equal LazySeq).
For pretty formatting of structures, do check out the clojure.pprint namespace which comes with clojure.core, which has pprint, print-table, and various functions for customizing the behavior of pretty printing.
user> (require '[clojure.pprint :as pprint :refer [pprint print-table]])
nil
user> (pprint [:a [:b :c :d [:e :f :g] :h :i :j :k] :l :m :n :o :p :q [:r :s :t :u :v] [:w [:x :y :z]]])
[:a
[:b :c :d [:e :f :g] :h :i :j :k]
:l
:m
:n
:o
:p
:q
[:r :s :t :u :v]
[:w [:x :y :z]]]
nil
user> (print-table (map #(let [start (rand-int 1e6)] (zipmap % (range start (+ start 10)))) (repeat 5 [:a :b :c :d :e :f :g :h :i :j])))
| :a | :c | :b | :f | :g | :d | :e | :j | :i | :h |
|--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
| 311650 | 311652 | 311651 | 311655 | 311656 | 311653 | 311654 | 311659 | 311658 | 311657 |
| 67627 | 67629 | 67628 | 67632 | 67633 | 67630 | 67631 | 67636 | 67635 | 67634 |
| 601726 | 601728 | 601727 | 601731 | 601732 | 601729 | 601730 | 601735 | 601734 | 601733 |
| 384887 | 384889 | 384888 | 384892 | 384893 | 384890 | 384891 | 384896 | 384895 | 384894 |
| 353946 | 353948 | 353947 | 353951 | 353952 | 353949 | 353950 | 353955 | 353954 | 353953 |
nil
I'm working through the 4clojure.com problems (this is from problem 33), and I can't for the life of me figure out how this works:
(#(for [x %, i (range %2)] x) [1 2 3] 2) ; --> '(1 1 2 2 3 3)
I can see that for binds x to [1 2 3] and then does something twice (i is bound to '(0 1)), but I'd expect an answer like '([1 2 3] [1 2 3]). It looks like this code is somehow doing a mapcat on the output.
The docstring for for includes the following: Collections are iterated in a nested fashion, rightmost fastest.... This gives me the intuition that i is taking on the values 0, 1, 2 for x, but I can't say I understand what's going on.
Can somebody explain what's going on in a way that improves my mental model of how for works? Many thanks!
When you fill in the function arguments you get the following:
(for [x [1 2 3]
i (range 2)]
x)
;; => (1 1 2 2 3 3)
Where:
(range 2) ;; => (0 1)
The rightmost item the docstring is referring to is i, which has two elements. So, if you unroll the loop, x and i would progress like the following table:
(clojure.pprint/print-table
(for [x [1 2 3] i (range 2)] {:x x :i i}))
| :x | :i |
|----+----|
| 1 | 0 |
| 1 | 1 |
| 2 | 0 |
| 2 | 1 |
| 3 | 0 |
| 3 | 1 |
The result of for is a list containing the results returned for every iteration of the loop. In this case you are just returning x, so your resulting list would correspond to only the x column in the above table.