Login
7 branches 0 tags
Ben (X13/Arch) Simplified things a little 0643405 9 days ago 1260 Commits
nujel / stdlib / collections / tree.nuj
;;; Nujel - Copyright (C) 2020-2021 - Benjamin Vincent Schulenburg
;;; This project uses the MIT license, a copy should be included under /LICENSE
;;;
;;; Some functions about trees

(defn tree/zip (keys values)
      "Return a tree where KEYS point to VALUES"
      (def ret {})
      (doseq (key keys ret)
	     (set! ret key (car values))
	     (cdr! values)))

(defn tree/+= (t k v)
      "Increment value at K in T by V"
      (set! t k (+ v (int (or (ref t k) 0)))))

(defmacro tree/-= (t k v)
          "Decrement value at K in T by V"
          `(tree/+= ~t ~k (- ~v)))

(defmacro tree/++ (t k)
          "Increment value at K in T by 1"
          `(tree/+= ~t ~k 1))

(defmacro tree/-- (t k)
          "Increment value at K in T by 1"
          `(tree/-= ~t ~k 1))

(defn tree/equal? (a b)
      "Compares two trees for equality"
      (if (and (tree? a)
               (tree? b))
          (and (= (:key* a)
                  (:key* b))
               (equal? (:value* a)
                       (:value* b))
               (tree/equal? (:left* a)
                            (:left* b))
               (tree/equal? (:right* a)
                            (:right* b)))
          (equal? a b)))

(defn tree/reduce (l o s)
      "Combine all elements in l using operation o and starting value s"
      (list/reduce (:values l) o s))

(defn tree/filter (l f)
      "Return a new tree with all elements from L where F returns true"
      (def ret {})
      (doseq (e (:keys l) ret)
             (def t (ref l e))
             (when (f t)
                   (set! ret e t))))

(defn tree/merge (a b)
      "Merge two trees together, if a key is contained in both trees the on in B gets priority"
      (when-not b (return (if a (:clone a) {})))
      (when-not a (return (:clone b)))
      (def ret (:clone a))
      (doseq (k (:keys b) ret)
             (set! ret k (ref b k))))