From 6fb03cda1c299ee674daff468cd1c06d369d369c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petar=20Kapri=C5=A1?= Date: Tue, 18 Mar 2025 19:19:30 +0100 Subject: [PATCH] Add remaining solutions to exercises in subsection 2.3.3 --- chapter-2/ex-2.63.txt | 16 +++++++ chapter-2/ex-2.64.txt | 22 +++++++++ chapter-2/ex-2.65.scm | 101 ++++++++++++++++++++++++++++++++++++++++++ chapter-2/ex-2.66.scm | 19 ++++++++ 4 files changed, 158 insertions(+) create mode 100644 chapter-2/ex-2.63.txt create mode 100644 chapter-2/ex-2.64.txt create mode 100644 chapter-2/ex-2.65.scm create mode 100644 chapter-2/ex-2.66.scm diff --git a/chapter-2/ex-2.63.txt b/chapter-2/ex-2.63.txt new file mode 100644 index 0000000..0164b33 --- /dev/null +++ b/chapter-2/ex-2.63.txt @@ -0,0 +1,16 @@ +a) +From my understanding, yes, the lists produced are always going to be equal? +given the same tree + +b) +No, they don't, remember than when we `append` two lists, the cons cells for +the first list have to all be reconstructed, which is an additional O(n) +steps, where n is len(first-list). + +This means that when we break up a tree in (tree->list-1 tree) T(n) = T(n/2) + +O(n) + T(n/2) + +tree->list-2 has one cons operation, which is constant, for each entry, which +means the order of growth is O(n) + +On the other hand, tree->list-1 has order of growth: O(n log n) diff --git a/chapter-2/ex-2.64.txt b/chapter-2/ex-2.64.txt new file mode 100644 index 0000000..ea8bee1 --- /dev/null +++ b/chapter-2/ex-2.64.txt @@ -0,0 +1,22 @@ +a) +partial-tree takes a list elts, and n, a number of starting elements which it +will process, it arranges these n elements into a tree and returns a list with +2 elements. The first is a tree of the first n elements, the second is a list +of the remaining elements. The arrangement is done by making a tree out of +(n-1)/2 elements recursively, then adding the one element at the start of the +remainder-list as the current entry, then taking the other half of the n +elements, and recursively arranging them as well. + +(list->tree '(1 3 5 7 9 11)) +== + 5 + / \ + 1 9 + \ / \ + 3 7 11 + +b) +Since only the top-level list has its length calculated O(n), while all the +lower ones have theirs calculated in constant time. And in general, every +specific call of partial-tree has a number of constant operations, the total +would be O(n) diff --git a/chapter-2/ex-2.65.scm b/chapter-2/ex-2.65.scm new file mode 100644 index 0000000..c1ab9f8 --- /dev/null +++ b/chapter-2/ex-2.65.scm @@ -0,0 +1,101 @@ +#lang sicp + +; the helper functions: + +(define (entry tree) (car tree)) +(define (left-branch tree) (cadr tree)) +(define (right-branch tree) (caddr tree)) +(define (make-tree entry left right) + (list entry left right)) + +(define (element-of-set? x set) + (cond ((null? set) false) + ((= x (entry set)) true) + ((< x (entry set)) + (element-of-set? x (left-branch set))) + ((> x (entry set)) + (element-of-set? x (right-branch set))))) + +(define (adjoin-set x set) + (cond ((null? set) (make-tree x '() '())) + ((= x (entry set)) set) + ((< x (entry set)) + (make-tree (entry set) + (adjoin-set x (left-branch set)) + (right-branch set))) + ((> x (entry set)) + (make-tree (entry set) (left-branch set) + (adjoin-set x (right-branch set)))))) + +(define (tree->list-2 tree) + (define (copy-to-list tree result-list) + (if (null? tree) + result-list + (copy-to-list (left-branch tree) + (cons (entry tree) + (copy-to-list + (right-branch tree) + result-list))))) + (copy-to-list tree '())) + +(define tree->list tree->list-2) + +(define (list->tree elements) + (car (partial-tree elements (length elements)))) + +(define (partial-tree elts n) + (if (= n 0) + (cons '() elts) + (let ((left-size (quotient (- n 1) 2))) + (let ((left-result + (partial-tree elts left-size))) + (let ((left-tree (car left-result)) + (non-left-elts (cdr left-result)) + (right-size (- n (+ left-size 1)))) + (let ((this-entry (car non-left-elts)) + (right-result + (partial-tree + (cdr non-left-elts) + right-size))) + (let ((right-tree (car right-result)) + (remaining-elts + (cdr right-result))) + (cons (make-tree this-entry + left-tree + right-tree) + remaining-elts)))))))) + + +; the exercise itself + +(define (union-olist set1 set2) + (cond ((null? set1) set2) + ((null? set2) set1) + ((< (car set1) (car set2)) (cons (car set1) + (union-olist (cdr set1) set2))) + ((= (car set1) (car set2)) (cons (car set1) + (union-olist (cdr set1) (cdr set2)))) + ((> (car set1) (car set2)) (cons (car set2) + (union-olist set1 (cdr set2)))))) + +(define (intersection-olist set1 set2) + (if (or (null? set1) (null? set2)) + '() + (let ((x1 (car set1)) (x2 (car set2))) + (cond ((= x1 x2) + (cons x1 (intersection-olist (cdr set1) + (cdr set2)))) + ((< x1 x2) + (intersection-olist (cdr set1) set2)) + ((< x2 x1) + (intersection-olist set1 (cdr set2))))))) + +(define (union-set set1 set2) + (list->tree + (union-olist (tree->list set1) + (tree->list set2)))) + +(define (intersection-set set1 set2) + (list->tree + (intersection-olist (tree->list set1) + (tree->list set2)))) \ No newline at end of file diff --git a/chapter-2/ex-2.66.scm b/chapter-2/ex-2.66.scm new file mode 100644 index 0000000..ee56450 --- /dev/null +++ b/chapter-2/ex-2.66.scm @@ -0,0 +1,19 @@ +#lang sicp + +(define (entry tree) (car tree)) +(define (left-branch tree) (cadr tree)) +(define (right-branch tree) (caddr tree)) +(define (make-tree entry left right) + (list entry left right)) + +(define (key record) + (car record)) + +(define (lookup given-key set-of-records) + (cond ((null? set-of-records) false) + ((= given-key (key (entry set-of-records))) + (entry set-of-records)) + ((< given-key (key (entry set-of-records))) + (lookup given-key (left-branch set-of-records))) + ((> given-key (key (entry set-of-records))) + (lookup given-key (right-branch set-of-records))))) \ No newline at end of file