1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
(define (make-list-ft from to)
(if (> from to)
'()
(cons from (make-list-ft (1+ from) to))))
;;# Exercise 1.3 (proper lists)
;;? Program own version of list?, thus proper-list?
;; This is done by running to the end of list, always checking if pair.
;; If last element is '() its a proper list, otherwize its not.
(define (proper-list? list)
(if (pair? list)
(proper-list? (cdr list))
(null? list)))
;;? Can you write your predicate without using if or cond?
;; Hmm i cant see how this would be done, as we are using recursion which requires a stop condition.
;; Hmm reading through the solution, i see that we can use other conditional functions like `or` and `and`.
;; Lets try that
(define (proper-list? list)
(or (null? list) (and (pair? list) (proper-list? (cdr list)))))
;;? Is your function efficient? What is the time complexity?
;; This runs over all the elements in the list, so O(n).
;; Okay thats just his solution
;;# Exercise 1.5 (every second element)
;; Hmm the text mentions that we could write it with (every-nth-element)
(define (every-nth-element n list)
(let recur ((list list) (index 0))
(cond ((null? list) '())
((zero? (modulo index n)) (cons (car list) (recur (cdr list) (1+ index))))
(else (recur (cdr list) (1+ index))))))
;; With letrec
(define (every-nth-element n list)
(letrec ([recur (lambda (list index)
(cond [(null? list) '()]
[(zero?
(modulo index n)) (cons (car list) (recur (cdr list) (1+ index)))]
[else (recur (cdr list) (1+ index))]))])
(recur list 0)))
(define (every-2th-element list)
(every-nth-element 2 list))
;;# Exercise 1.6 (Creation of association list)
;;? Program a function pair-up that constructs an association list from a list of keys and a list of values
;;? Think of a reasonable solution in case the length of the key list is different from the length of the value list.
(define (pair-up keys values)
(cond [(null? keys) '()]
[(null? values) '()]
[else (cons (cons (car keys) (car values))
(pair-up (cdr keys) (cdr values)))]))
;;# Exercise 1.7 (Association list and property lists)
;;? Program a function that converts an association list to a property list.
(define (assoc->prop lst)
(if (null? lst)
'()
(let ([elem (car lst)])
(cons (car elem) (cons (cdr elem) (assoc->prop (cdr lst)))))))
;;? Next, program the function that converts a property list to an association list.
(define (prop->assoc lst)
(if (null? lst)
'()
(cons (cons (car lst) (cadr lst)) (prop->assoc (cddr lst)))))
;;# Exercise 1.8
;;? The function should return the value of key in property-list. Like assoc, get-prop should return #f if key is not found in property-list.
;;? How will you handle the case where the property list is malformed - a property list with an odd number of elements?
(define (get-prop lst index)
(cond [(null? lst) #f]
[(null? (cdr lst)) #f]
[(eqv? (car lst) index) (cadr lst)]
[else (get-prop (cddr lst) index)]
))
;;? Discuss pros and cons of property lists and get-prop, compared to association lists and assoc.
;; I don't see many pros of property lists, feels kind of like a hack.
;; If you get a snippet of a property list, it's impossible to know where keys and values are.
;; One pro is that they are easier to write out by hand.
;;? Does the #f value, returned in cases where we do not find the key, bother you?
;; YEEEES WTF
;; What if you want to store booleans, with the possability of having false values.
;; Then you have to wrap booleans in something else, like a one element list.
;;# Exercise (list tail counterpart)
;;? Program your own version of list-tail. Call it my-list-tail.
(define (my-list-tail lst index)
(cond [(null? lst) '()]
[(zero? index) lst]
[else (my-list-tail (cdr lst) (1- index))]
))
;;? Next, program a function list-prefix which is a prefix counterpart to list-tail. (list-prefix lst n) returns a prefix of the list of length n.
(define (list-prefix lst index)
(cond [(null? lst) '()]
[(zero? index) (cons (car lst) '())]
[else (cons (car lst) (list-prefix (cdr lst) (1- index)))]
))
;;? Reflect on the difference between these two functions. Which one is most expensive in terms of memory allocation?
;; list-prefix builds up a copy of the existing array with consts.
;; Therefore a new const is created at each recursive step of the evaluation, which requires more space.
;; my-list-tail can just return the existing tail, without allocating a new array.
|