convert strings in list to numbers in racket? - lisp

Calling all racket developers, I am a newbie to racket language and function languages in general. Long story short, I have a nested list that contains numbers and string and I want to convert string elements to numbers.
Example: If I have list like this
'( 3 "3"( 1 "1"()( 2 "2" () ()))( 5 "5" () () ))
I want to converted to '( 3 3( 1 1()( 2 2 () ()))( 5 5 () () ))
While maintaining the same shape, therefore I wrote this function
(define (mapBst BST someFunct )
(if (null? BST) '()
(someFunct (car(cdr BST)) (mapBST someFunct (cdr (car BST))))
)
)
(mapBst '( 3 "3"( 1 "1"()( 2 "2" () ()))( 5 "5" () () )) string->number)
But I am getting this error : cdr: contract violation
expected: pair?
given: 3
Any clue why I am getting this error or what I did wrong, any suggestions will help. Thank you in advance

I suggest this:
(define (mapBST BST someFunct)
(cond [(null? BST)
'()]
[(list? (car BST))
(cons (mapBST (car BST) someFunct)
(mapBST (cdr BST) someFunct))]
[else
(cons (someFunct (car BST))
(mapBST (cdr BST) someFunct))]))
Example:
> (mapBST '( 3 "3"( 1 "1"()( 2 "2" () ()))( 5 "5" () () ))
(λ (x) (if (string? x) (string->number x) x)))
'(3 3 (1 1 () (2 2 () ())) (5 5 () ()))

Related

Filter out any value other than a number

I am trying to come up with a procedure that filters out any value other than a number. For example:
'(1 2 (a) 3) => '(1 2 () 3) or '(1 2 (a 10 11 (b 2 (c))) 3) => '(1 2 (10 11 (2 ())) 3)
This is what I have so far but it doesn't really work because it replaces the non numbers with an empty list instead of nothing:
(define (filter-numbers lst)
(if (null? lst)
'()
(if (list? lst)
(cons
(filter-numbers (car lst))
(filter-numbers (cdr lst)))
(if (number? lst)
lst
'())))
)
The procedure outputs the following:
> (filter-numbers '(1 2 (a) 3))
'(1 2 (()) 3)
instead of: '(1 2 () 3)
You need to check if an element in a sublist is a number before deciding to cons it to the output or not. I think it's easier if we restructure the code a bit; also some tips: don't use list?, prefer pair? as it's faster (unlike list? it doesn't have to traverse the whole list). And prefer cond instead of nesting ifs, your code will be easier to read. This is what I mean:
(define (filter-numbers lst)
(cond ((null? lst) lst)
((not (pair? (car lst)))
; check the element while still in a list, if we wait
; until we reach an atom it's too late to filter it out
(if (number? (car lst))
; either add the element to the output or skip it
(cons (car lst) (filter-numbers (cdr lst)))
(filter-numbers (cdr lst))))
(else (cons
(filter-numbers (car lst))
(filter-numbers (cdr lst))))))
It works as expected:
(filter-numbers '(1 2 (a) 3))
=> (1 2 () 3)
(filter-numbers '(1 2 (a 10 11 (b 2 (c))) 3))
=> '(1 2 (10 11 (2 ())) 3)

loop through tree and sum all values in racket?

I am try to write some generic method that takes two arguments (tree , function)to iterate over tree node and pass tree node to method
for example i have this method called fold that take binary search tree as first argument and function as second argument while argument method takes four arguments (key value left-node-key right-node-key).
(define (fold tree function)
(cond
[(null? tree) (function '() '() '() '())]
[(number? (car tree))
(+ (funct (car tree) (cadr tree) (caaddr tree) (car(cadddr tree)))
(fold (cddr(caddr tree)) function)
(fold (cddr(cadddr tree)) function)
)]
[else (function '() '() '() '())]
)
)
here is some methods that could be passed to above fold method :
first method could be sumAll
(define (sumAll key value leftValue rightValue)
(if (null? key)
0
(+ key leftValue rightValue)
)
)
second method could be findMinimum
(define (findMinimum key value leftValue rightValue)
(if (null? key)
'()
(if (null? leftValue)
key
leftValue
)
)
)
use:
(define tr '(20 "20" (18 "18" ()(19 "19" () ())) (21 "21" (15 "15" () ()) ()) ))
(fold tr sumAll ) ; should return: 93
(fold tr findMinimum ) ; should return: 15
but i am getting this error from fold method:
+: contract violation
expected: number?
given: '()
argument position: 2nd
other arguments...:
any clue why i am getting this error.
You can make fold abstract enough by accepting any procedure proc and a base case value init, and have the procedure apply the argument function over all nodes as follows:
(define (fold proc init lst)
(cond
[(null? lst) init]
[else
(proc (car lst)
(fold proc init (caddr lst))
(fold proc init (cadddr lst)))]))
Then, with the following binary search tree example definition:
(define BST '(20 "20" (18 "18" () (19 "19" () ())) (21 "21" (15 "15" () ()) ())))
you can use the procedure as:
(fold + 0 BST) ; find sum
=> 93
(fold min 1000 BST) ; find min
=> 15

Lambda function distinct parameters

I'm trying to create lambda functions that use the same code but have different Internal parameters.
To clarify, I'm putting here the code:
(defun testes ()
(setf lol '())
(loop for i in (list 1 2 3 4 5 )
do (loop for j in (list 1 2 3 4 5)
do (setf lol (append lol (list (cons i j))))))
lol
)
(defun mainff ()
(setf lol (testes))
(setf res ())
(print lol)
(loop for i in lol
do (setf res (append res (list #'(lambda ()
(print i)
))))
)
res
)
(defun fun()
(setf res (mainff))
(loop for i in res
do (funcall i)
)
)
Returning to the inicial question, i in the append of res must be unique to each lambda that is created. However it only saves the last value that it assumes (5 5). Any way to solve this?
Use LET to create a different binding for each i.
(loop for element in list
...
(let ((i element))
(lambda ()
(print i)))
...
)

Map! procedure in Racket

The map! procedure should modify the existing list to have the values of the operator applied to the original values.
For example:
(define a '(1 2 3 4 5))
(define double (lambda (x) (* x 2)))
(map! double a)
returns
done
Then when a is evaluated, a should return
(2 4 6 8 10)
map! procedure must do that work.
(define (map! operator given-list)
(if (null? given-list) 'done
(<the procedure that does the modification>)))
My guess1:
(map (lambda (x) (set! x (operator x))) given-list)
(map! double a)
returns:
'(#<void> #<void> #<void> #<void> #<void>)
My guess2:
(cons (operator (car given-list)) (map! double (cdr given-list)))
(map! double a)
returns:
'(2 4 6 8 10 . done)
My guess3:
(set! given-list (map operator given-list))
(map! double a)
returns:
'(2 4 6 8 10)
My guess4:
(let ((element (car given-list)))
(set! element (operator given-list) (map! operator (cdr given-list)))
(map! double a)
returns:
'done
but, when "a" is evaluated, it still says:
'(1 2 3 4 5)
What do I have to do for this?????
You cannot use set! for this. You need to use set-car! on the cons cell you're changing. Here's how you might write it:
(define (map! f lst)
(let loop ((rest lst))
(unless (null? rest)
(set-car! rest (f (car rest)))
(loop (cdr rest)))))
If you have SRFI 1, it's even easier (if we ignore for a moment that SRFI 1 already defines map! ;-)):
(define (map! f lst)
(pair-for-each (lambda (pair)
(set-car! pair (f (car pair))))
lst))

LISP Lists sublist

function that only deletes the first element of each sublist in the list. For example,
Test 1:
List is (10 (1 2 3) (90 100) 122 156)
Output should be: (10 (2 3) (100) 122 156)
I know how to delete an element from the list but i don't know which function is used to delete element from the sublist
(defun butfirst (lst)
(mapcar
(lambda (e) (if (consp e) (cdr e) e))
lst))
(butfirst '(10 (1 2 3) (90 100) 122 156))
=> (10 (2 3) (100) 122 156)
yet another offer: without iteration, with a recursive algorithm.
(defun butfirst (lst)
(cond
((null lst) '())
((consp (car lst))
(cons (cdr (car lst))
(butfirst (cdr lst))))
(t (cons (car lst)
(butfirst (cdr lst))))))