Last active
March 29, 2024 01:29
-
-
Save vdeemann/8071ab92d7d89b3c556611a6af37f587 to your computer and use it in GitHub Desktop.
the-little-schemer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
(require racket/trace) | |
(define o+ | |
(lambda (n m) | |
(cond | |
((zero? m) n) | |
(else (add1 (o+ n (sub1 m))))))) | |
;(trace o+) | |
;(o+ 46 12) ; 58 | |
(define o- | |
(lambda (n m) | |
(cond | |
((zero? m) n) | |
(else (sub1 (o- n (sub1 m))))))) | |
; Example of o- | |
; | |
;(trace o-) | |
;(o- 14 3) ; 11 | |
;(o- 17 9) ; 8 | |
(define addtup | |
(lambda (tup) | |
(cond | |
((null? tup) 0) | |
(else (o+ (car tup) (addtup (cdr tup))))))) | |
; Examples of addtup | |
; | |
;(addtup '(3 5 2 8)) ; 18 | |
;(addtup '(15 6 7 12 3)) ; 43 | |
(define o* | |
(lambda (n m) | |
(cond | |
((zero? m) 0) | |
(else (o+ n (o* n (sub1 m))))))) | |
;(o* 5 3) ; 15 | |
;(o* 13 4) ; 52 | |
(define o> | |
(lambda (n m) | |
(cond | |
((zero? n) #f) | |
((zero? m) #t) | |
(else | |
(o> (sub1 n) (sub1 m)))))) | |
; Examples of o> | |
; | |
;(o> 12 133) ; #f (false) | |
;(o> 120 11) ; #t (true) | |
;(o> 6 6) ; #f | |
; The o< function compares n with m and returns true if n<m | |
; | |
(define o< | |
(lambda (n m) | |
(cond | |
((zero? m) #f) | |
((zero? n) #t) | |
(else | |
(o< (sub1 n) (sub1 m)))))) | |
; Examples of o< | |
; | |
;(o< 4 6) ; #t | |
;(o< 8 3) ; #f | |
;(o< 6 6) ; #f | |
(define o= | |
(lambda (n m) | |
(cond | |
((o> n m) #f) | |
((o< n m) #f) | |
(else #t)))) | |
; Examples of o= | |
; | |
;(o= 5 5) ; #t | |
;(o= 1 2) ; #f | |
(define o/ | |
(lambda (n m) | |
(cond | |
((o< n m) 0) | |
(else (add1 (o/ (o- n m) m)))))) | |
; Example of o/ | |
; | |
;(o/ 15 4) ; 3 | |
(define atom? ; | |
(lambda (x) ; | |
(and (not (pair? x)) (not (null? x))))) | |
#| | |
; my number? function (does not work with strings) | |
; what is the definition of a number? | |
; numbers are considered integers in this case and they are counting numbers | |
; so this function should sub1 to reach 0 as a terminating case | |
(define number? | |
(lambda (n) | |
(cond | |
((zero? (sub1 n)) #t) | |
((zero? n) #t) | |
(else (number? (sub1 n))) | |
))) | |
(trace number?) | |
(number? 2) | |
(number? 0) | |
(number? 'tomato) | |
|# | |
; The no-nums function returns a new lat with all numbers removed | |
; | |
(define no-nums | |
(lambda (lat) | |
(cond | |
((null? lat) '()) | |
((number? (car lat)) (no-nums (cdr lat))) | |
(else | |
(cons (car lat) (no-nums (cdr lat))))))) | |
; Example of no-nums | |
; | |
;(no-nums '(5 pears 6 prunes 9 dates)) ; '(pears prunes dates) | |
; The eqan? function determines whether two arguments are te same | |
; It uses eq? for atoms and = for numbers | |
; | |
(define eqan? | |
(lambda (a1 a2) | |
(cond | |
((or (number? a1) (number? a2)) #f) | |
((and (number? a1) (number? a2)) (= a1 a2)) | |
(else | |
(eq? a1 a2))))) | |
; Examples of eqan? | |
; | |
;(eqan? 3 3) ; #t | |
;(eqan? 3 4) ; #f | |
;(eqan? 'a 'a) ; #t | |
;(eqan? 'a 'b) ; #f |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
(require racket/trace) | |
(define atom? | |
(lambda (x) | |
(and (not (pair? x)) (not (null? x))))) | |
(define rember* | |
(lambda (a l) | |
(cond | |
((null? l) '()) | |
((atom? (car l)) | |
(cond | |
((eq? (car l) a) | |
(rember* a (cdr l))) | |
(else | |
(cons (car l) (rember* a (cdr l)))))) | |
(else | |
(cons (rember* a (car l)) (rember* a (cdr l))))))) | |
(trace rember*) | |
(trace atom?) | |
(rember* | |
'cup | |
'((coffee) cup ((tea) cup) (and (hick)) cup)) | |
;==> '((coffee) ((tea)) (and (hick))) | |
(rember* | |
'sauce | |
'(((tomato sauce)) ((bean) sauce) (and ((flying)) sauce))) | |
;==> '(((tomato)) ((bean)) (and ((flying)))) | |
#| | |
# python while-loop using ChatGPT to be converted tail-recursively | |
def rember_star(a, lst): | |
def helper(a, lst): | |
acc = [] | |
while lst: | |
if isinstance(lst[0], list): | |
acc.append(helper(a, lst[0])) | |
elif lst[0] == a: | |
pass | |
else: | |
acc.append(lst[0]) | |
lst = lst[1:] | |
return acc | |
return helper(a, lst) | |
# Test input where the element to remove is present in the list | |
print(rember_star(2, [1, [2, 3], 4, [5, 6]])) # Output: [1, [3], 4, [5, 6]] | |
# Test input where the element to remove is not present in the list | |
print(rember_star(7, [1, [2, 3], 4, [5, 6]])) # Output: [1, [2, 3], 4, [5, 6]] | |
# Test input where the list is empty | |
print(rember_star(2, [])) # Output: [] | |
# Test input where the list contains only the element to remove | |
print(rember_star(2, [2, 2, 2])) # Output: [] | |
# Test input where the list contains nested sublists | |
print(rember_star(2, [1, [2, [2, 3]], 4, [5, 6]])) # Output: [1, [[3]], 4, [5, 6]] | |
To make the `rember*` function tail-recursive, you can use an accumulator parameter to accumulate the result while traversing the list. Here's the modified version: | |
```scheme | |
(define rember* | |
(lambda (a l) | |
(letrec ((helper (lambda (a l acc) | |
(cond | |
((null? l) (reverse acc)) | |
((atom? (car l)) | |
(if (eq? (car l) a) | |
(helper a (cdr l) acc) | |
(helper a (cdr l) (cons (car l) acc)))) | |
(else | |
(helper a (cdr l) (cons (helper a (car l) '()) acc))))))) | |
(helper a l '())))) | |
``` | |
In this modified version: | |
- We introduce a helper function `helper` that takes an additional parameter `acc` as an accumulator. | |
- The `helper` function accumulates the result in `acc` as it traverses the list `l`. | |
- When a non-atomic element is encountered, the `helper` function recursively calls itself with `(car l)` and accumulates the result in the `acc`. | |
- After traversing the entire list, we return the accumulated result, which is reversed to maintain the original order of elements. | |
This version of `rember*` is tail-recursive because the recursive call `(helper a (cdr l) ...)` is the last operation performed in each branch of the recursion. | |
|# | |
; tail-recursive solution from ChatGPT | |
(define tail-rember* | |
(lambda (a l) | |
(letrec ((helper (lambda (a l acc) | |
(cond | |
((null? l) (reverse acc)) | |
((atom? (car l)) | |
(if (eq? (car l) a) | |
(helper a (cdr l) acc) | |
(helper a (cdr l) (cons (car l) acc)))) | |
(else | |
(helper a (cdr l) (cons (helper a (car l) '()) acc))))))) | |
(helper a l '())))) | |
(trace tail-rember*) | |
(tail-rember* | |
'cup | |
'((coffee) cup ((tea) cup) (and (hick)) cup)) | |
;==> '((coffee) ((tea)) (and (hick))) | |
(tail-rember* | |
'sauce | |
'(((tomato sauce)) ((bean) sauce) (and ((flying)) sauce))) | |
;==> '(((tomato)) ((bean)) (and ((flying)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment