Traversing a tree in Pre-order - clojure

I am new to clojure as well as to Functional Programming. I am trying to traverse a tree in pre-order using:
(def preordercoll [])
(deftrace preorder [mytree]
(if-not (empty? mytree)
(do (println "position"(value mytree))
(cons (value mytree) (preorder (left-child mytree)))
(cons (value mytree) (preorder (right-child mytree))))
)preordercoll) )
(preorder [45[65 [90 nil nil] [81 nil nil]] [72[82 nil nil][96 nil nil]]])
I am unable to append values of node in some list, like I tried using 'conj' operation on global variable preordercoll, but yes it doesn't work like object oriented , so I tried using cons, but only few values are returned, that too in improper order. Can anyone guide me what mistake am making?
I also thought of using Partial function but could not find how to supply value of node in recursive manner. Am not asking for code but please draw me in right direction to get collection of values in pre-order.

you're on the right track, just have the nesting of the cons calls a little off. First a note on evaluation of forms in clojure. One of the key ideas is that every form evaluates to something* which is why there is no "return" statement in the language, because you could say everything would be a return statement so what's the point in having it. In the case of a do expression the return value of the expression is the last statement so:
(do 1 2 3)
returns (evaluates to) 3. In the do expression in your code it returns the result of the second cons, and the first cons has no effect.
(do (println "position"(value mytree))
(cons (value mytree) (preorder (left-child mytree))) ;; <-- this does nothing
(cons (value mytree) (preorder (right-child mytree))))
instead it sounds like you would like an expression that starts with the result of calling preorder on the left tree, then concatinates the result of calling preorder on the right tree, then attaches the current node's value to the front of that.
(let [left-side (preorder (left-child mytree))
right-side (preorder (left-child mytree))
this-value (value mytree)]
(do (println "position" this-value)
(cons this-value (concat right-side left-side))
*(for the pedants) "except the ignore reader maco #_"

Related

Returning smallest item in a list in Scheme

Note: I am doing this for homework. I'm not looking for the algorithm to solve my problem, just trying to understand how Scheme works.
I'm new to scheme and trying to write a small program to find the smallest item in a list. The program is working in the since that it is finding the correct answer (so the logic is somewhat sound), but I only know this because an error is coming up that it's trying to treat my answer as a function and call it.
(DEFINE (startmin mylist)
(
(repeatmin (CAR mylist) (CDR mylist))
))
(DEFINE (repeatmin curmin mylist)
(
(IF (NULL? mylist) ;If the list is empty
;This is where I'm at a loss. I want a way for this value to be
;sent out once the list is empty
curmin ;return the current minimum
(IF (< curmin (CAR mylist)) ;if the current minimum is less than the head of the list
(repeatmin curmin (CDR mylist)) ;recurse with curmin
(repeatmin (CAR mylist) (CDR mylist)) ;otherwise recurse with the head of the list.
)
)
))
I'm really at a loss of how I get the value, once found, back out of the recursion as it keeps trying to treat the value as a function.
Your parentheses are off. If you write
((if ...))
it means that the result from if is a function that immediately should be called once the value is cmoputed. It seems like you are using parentheses as if they are blocks, like {} in C, but they are not. In fact (begin ...) is a block in Scheme. And of course a function, let and cond terms have implicit begin.. Thus
(define (func . args)
(begin
x
y))
Is the same as
(define (func . args)
x
y)
Also please format your code correctly. Indentation helps you read the code and the nesting. I really don't pay attention to the parentheses, just the position which is crucial. Choose an editor that does this for you. Eg. DrRacket is a nice one I use.

Why am I getting variable 'list' has no value?

I am trying to understand why I am getting this error, as I am fairly new to lisp. I want to create a function that takes a number n from the user and creates a list of up to five numbers based on that number. The function then takes the first number in the list and sends it to the end of the list.
Example
> (my_func 1)
> (2 3 4 5 1)
This is what I have so far, I am able to get the function to return a list, however I am unsure on how to send the first element to the back of the list.
(defun my_rotate (y)
(labels ((var (list) (loop for i from y to list collect i)))
(var 5) (append (rest list)(list (first list))))
)
Let's start by formatting the code "properly", this makes it much easier to see the structure of the code:
(defun my_rotate (y)
(labels ((var (list)
(loop for i from y to list collect i)))
(var 5)
(append (rest list) ;; This form is not in a lexical context
(list (first list))))) ;; where list is bound
We can clearly see that the reason we're getting an error is because list simply isn't bound, so the local function var is not actually useful (it's called, but throws the value away, since it has no side effects, it could in theory be optimized away).
The simplest fix is to move the append call outside the labels, drop the labels form, then change the name of the input argument to list.
Your question isn't entirely clear to me, but if I understand correctly, something like this should work:
(defun my_rotate (y)
(let ((list (loop for i from y to (+ 4 y) collect i))) ;; create the list you want
(append (rest list) (subseq list 0 1)))) ;; move first element to end

Ignore/Delete Repeat Symbols in a Frequency List in Scheme [duplicate]

This is extremely easy if I can use an array in imperative language or map (tree-structure) in C++ for example. In scheme, I have no idea how to start this idea? Can anyone help me on this?
Thanks,
Your question wasn't very specific about what's being counted. I will presume you want to create some sort of frequency table of the elements. There are several ways to go about this. (If you're using Racket, scroll down to the bottom for my preferred solution.)
Portable, pure-functional, but verbose and slow
This approach uses an association list (alist) to hold the elements and their counts. For each item in the incoming list, it looks up the item in the alist, and increments the value of it exists, or initialises it to 1 if it doesn't.
(define (bagify lst)
(define (exclude alist key)
(fold (lambda (ass result)
(if (equal? (car ass) key)
result
(cons ass result)))
'() alist))
(fold (lambda (key bag)
(cond ((assoc key bag)
=> (lambda (old)
(let ((new (cons key (+ (cdr old) 1))))
(cons new (exclude bag key)))))
(else (let ((new (cons key 1)))
(cons new bag)))))
'() lst))
The incrementing is the interesting part. In order to be pure-functional, we can't actually change any element of the alist, but instead have to exclude the association being changed, then add that association (with the new value) to the result. For example, if you had the following alist:
((foo . 1) (bar . 2) (baz . 2))
and wanted to add 1 to baz's value, you create a new alist that excludes baz:
((foo . 1) (bar . 2))
then add baz's new value back on:
((baz . 3) (foo . 1) (bar . 2))
The second step is what the exclude function does, and is probably the most complicated part of the function.
Portable, succinct, fast, but non-functional
A much more straightforward way is to use a hash table (from SRFI 69), then update it piecemeal for each element of the list. Since we're updating the hash table directly, it's not pure-functional.
(define (bagify lst)
(let ((ht (make-hash-table)))
(define (process key)
(hash-table-update/default! ht key (lambda (x) (+ x 1)) 0))
(for-each process lst)
(hash-table->alist ht)))
Pure-functional, succinct, fast, but non-portable
This approach uses Racket-specific hash tables (which are different from SRFI 69's ones), which do support a pure-functional workflow. As another benefit, this version is also the most succinct of the three.
(define (bagify lst)
(foldl (lambda (key ht)
(hash-update ht key add1 0))
#hash() lst))
You can even use a for comprehension for this:
(define (bagify lst)
(for/fold ((ht #hash()))
((key (in-list lst)))
(hash-update ht key add1 0)))
This is more a sign of the shortcomings of the portable SRFI 69 hashing library, than any particular failing of Scheme for doing pure-functional tasks. With the right library, this task can be implemented easily and functionally.
In Racket, you could do
(count even? '(1 2 3 4))
But more seriously, doing this with lists in Scheme is much easier that what you mention. A list is either empty, or a pair holding the first item and the rest. Follow that definition in code and you'll get it to "write itself out".
Here's a hint for a start, based on HtDP (which is a good book to go through to learn about these things). Start with just the function "header" -- it should receive a predicate and a list:
(define (count what list)
...)
Add the types for the inputs -- what is some value, and list is a list of stuff:
;; count : Any List -> Int
(define (count what list)
...)
Now, given the type of list, and the definition of list as either an empty list or a pair of two things, we need to check which kind of list it is:
;; count : Any List -> Int
(define (count what list)
(cond [(null? list) ...]
[else ...]))
The first case should be obvious: how many what items are in the empty list?
For the second case, you know that it's a non-empty list, therefore you have two pieces of information: its head (which you get using first or car) and its tail (which you get with rest or cdr):
;; count : Any List -> Int
(define (count what list)
(cond [(null? list) ...]
[else ... (first list) ...
... (rest list) ...]))
All you need now is to figure out how to combine these two pieces of information to get the code. One last bit of information that makes it very straightforward is: since the tail of a (non-empty) list is itself a list, then you can use count to count stuff in it. Therefore, you can further conclude that you should use (count what (rest list)) in there.
In functional programming languages like Scheme you have to think a bit differently and exploit the way lists are being constructed. Instead of iterating over a list by incrementing an index, you go through the list recursively. You can remove the head of the list with car (single element), you can get the tail with cdr (a list itself) and you can glue together a head and its tail with cons. The outline of your function would be like this:
You have to "hand-down" the element you're searching for and the current count to each call of the function
If you hit the empty list, you're done with the list an you can output the result
If the car of the list equals the element you're looking for, call the function recursively with the cdr of the list and the counter + 1
If not, call the function recursively with the cdr of the list and the same counter value as before
In Scheme you generally use association lists as an O(n) poor-man's hashtable/dictionary. The only remaining issue for you would be how to update the associated element.

Clojure (or any functional language): is there a functional way of building flat lists by a recursive function?

I've got a recursive function building a list:
(defn- traverse-dir
"Traverses the (source) directory, preorder"
[src-dir dst-root dst-step ffc!]
(let [{:keys [options]} *parsed-args*
uname (:unified-name options)
[dirs files] (list-dir-groomed (fs/list-dir src-dir))
... recursive call of traverse-dir is the last expression of dir-handler
(doall (concat (map-indexed (dir-handler) dirs) (map-indexed (file-handler) files))))) ;; traverse-dir
The list, built by traverse-dir, is recursive, while I want a flat one:
flat-list (->> (flatten recursive-list) (partition 2) (map vec))
Is there a way of building the flat list in the first place? Short of using mutable lists, that is.
I don't quite understand your context with a dir-handler that is called with nothing and returns a function which expects indices and directories, list-dir-groomed and all of that, but I'd recommend a look at tree-seq:
(defn tree-seq
"Returns a lazy sequence of the nodes in a tree, via a depth-first walk.
branch? must be a fn of one arg that returns true if passed a node
that can have children (but may not). children must be a fn of one
arg that returns a sequence of the children. Will only be called on
nodes for which branch? returns true. Root is the root node of the
tree."
{:added "1.0"
:static true}
[branch? children root]
(let [walk (fn walk [node]
(lazy-seq
(cons node
(when (branch? node)
(mapcat walk (children node))))))]
(walk root)))
My go-to use here is
(tree-seq #(.isDirectory %) #(.listFiles %) (clojure.java.io/as-file file-name))
but your context might mean that doesn't work. You can change to different functions for getting child files if you need to sanitize those, or you can just use filter on the output. If that's no good, the same pattern of a local fn from nodes into pre-walks that handles children by recursively mapcatting itself over them seems pretty applicable.

How do you make a binary search tree in Clojure?

In Scheme, I can use define-struct to make a binary search tree, but how do you do it in Clojure?
You can use structmaps. To define one:
(defstruct bintree :left :right :key)
To make an instance:
(struct-map bintree :left nil :right nil :key 0)
You can then access the values in the struct like this:
(:left tree)
etc.
Or you can create new accessor functions:
(def left-branch (accessor bintree :left))
and use it:
(left-branch tree)
I don't know Clojure, but I bet it's the same way you do it in Scheme without define-struct ... just cons together the left and right branches. To find something, recurse until you hit an atom.
Seriously, though, structmaps sound like what you want. I found this page. Look for structmaps about half way down.
The simplest way would be to use the tree that is already defined in language (every sorted-map is a tree really, if you just need different function to compare keys, use sorted-map-by).
;;define function for comparing keys
(defn compare-key-fn [key1 key2] (< key1 key2) )
;;define tree and add elements
(def my-tree
(-> ;;syntax sugar
(sorted-map-by compare-key-fn) ;;this returns empty tree with given function to compare keys
(assoc 100 "data for key = 100") ;;below we add elements to tree
(assoc 2 "data for key = 2")
(assoc 10 "data for key = 10")
(assoc -2 "data for key = -1")))
;;accesing elements by key
(prn "element for key 100 =" (my-tree 100))
;;"erasing" elements from tree - in reality, what we are really doing, is returning a new tree that contains all elements of the old one, except the element we've just erased.
(def my-new-tree
(dissoc my-tree 2))
(prn my-new-tree) ;; to verify, that element 2 is "erased"