From 17ebc4a8a9224cc0d11a1444907d4596e71b69c0 Mon Sep 17 00:00:00 2001 From: Julian T Date: Tue, 14 Sep 2021 16:22:03 +0200 Subject: Make last exercises for PP lecture 1 --- sem7/pp/lec1/exercises.scm | 83 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 5 deletions(-) (limited to 'sem7/pp/lec1/exercises.scm') diff --git a/sem7/pp/lec1/exercises.scm b/sem7/pp/lec1/exercises.scm index 9be35e2..6220982 100644 --- a/sem7/pp/lec1/exercises.scm +++ b/sem7/pp/lec1/exercises.scm @@ -3,7 +3,7 @@ '() (cons from (make-list-ft (1+ from) to)))) -;; Exercise 1.3 (proper lists) +;;# 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. @@ -14,17 +14,17 @@ ;;? 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. - -;;? Is your function efficient? What is the time complexity? -;; This runs over all the elements in the list, so O(n). ;; 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) +;;# 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)) @@ -32,5 +32,78 @@ ((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. -- cgit v1.2.3