Scheme Function checking balanced parenthesis - scheme

I am trying to check for balanced parenthesis in scheme with a string as given input but what I have is not working correctly and I do not know why. Any insight on what I need to change? Thanks.
(define (balanced? st)
(define lst (string->list st))
(display lst)
(if (equal? (string-length st) 0)
#t
(counter lst 0)
))
(define (counter lst count)
(cond
((and (= count 0) (= (length lst) 0) #t))
((and (not(= count 0)) (= (length lst) 0) #f))
((equal? (first lst) "(") (counter (cdr lst) (+ count 1)))
((equal? (first lst) ")") (counter (cdr lst) (- count 1)))
(counter (cdr lst) count)
)
)

The last clause of cond needs else as the condition.
(define (counter lst count)
(cond
((and (= count 0) (= (length lst) 0) #t))
((and (not(= count 0)) (= (length lst) 0) #f))
((equal? (first lst) "(") (counter (cdr lst) (+ count 1)))
((equal? (first lst) ")") (counter (cdr lst) (- count 1)))
(else (counter (cdr lst) count))
)
)
Your code has counter as the last condition, then it calls (cdr lst) and discards the value, and returns count.

Here is my version, tested in mit-scheme:
(define balanced
(lambda (input break ret)
(if (null? input)
(ret 'eos)
(if (char=? (car input) #\()
(balanced
(cdr input)
break
(lambda (rest)
(assert
(or (eq? rest 'eos)
(char=? #\) (car rest))))
(if (eq? rest 'eos)
(break)
(balanced (cdr rest) break ret))))
(if (char=? (car input) #\))
(ret input)
(balanced (cdr input) break ret))))))
Here is an unit test:
(define test
(lambda (input)
(display input)
(display " => ")
(balanced
(string->list input)
(lambda ()
(display "error"))
(lambda (rest)
(display (if (eq? rest 'eos) "OK" "error"))))
(newline)))
Input test:
(test "(")
(test ")")
(test "()")
(test "((")
(test "))")
(test ")(")
(test "(abc)")
(test "(a(b)c)")
(test "(")
(test ")")
(test "(a)b)")
(test "(a(b)")
(test "(a(b)c))(")
(test "(a(b)c)()")
% mit-scheme --silent < balanced.scm
( => error
) => error
() => OK
(( => error
)) => error
)( => error
(abc) => OK
(a(b)c) => OK
( => error
) => error
(a)b) => error
(a(b) => error
(a(b)c))( => error
(a(b)c)() => OK

Related

The object () is not applicable

I am writing a very simple program for Pascal's triangle in scheme (exercise from SICP). I wrote this code and its getting an error message The object () is not applicable.
(define (pascal-triangle n)
(define (get-value list position)
(define (get-sum-iter prevList counter)(
cond
((= counter (- position 1))
(+ (car prevList) (car (cdr prevList))))
(else (get-sum-iter (cdr prevList) (+ counter 1)))
))
(get-sum-iter list 0)
)
(define (create-list prevList size)
(define (create-list-iter currList counter)(
cond
((or (= counter (- size 1))
(= counter 0))
(create-list-iter (cons 1 currList) (- counter 1)))
((> counter 0)
create-list-iter
(cons (get-value prevList counter)
currList)
(- counter 1))
(else currList)
))
(create-list-iter () (- size 1))
)
(define (pascal-triangle-iter resultList counter)
(cond
((> counter n) resultList)
(else
(pascal-triangle-iter
(cons create-list
((cond
((null? resultList) resultList)
(else (car resultList)))
counter)
resultList)
(+ counter 1)))
)
)
(pascal-triangle-iter () 1)
)
In my function definition of pascal-triangle-iter I expect the first parameter to be a list of list. but when I'm calling it I am just passing an empty list and not list of list. My guess is that this is the cause of the error The object () is not applicable But when how do I initialize and empty list of list?
Thanks to everyone specially #barmar and #adabsurdum to helping me. The problem was the my parenthesis were off. The list construction was fine. The following code works fine for me (MIT Scheme on Mac OS)
; pascal triangle recursive
(define (pascal-triangle n)
(define (get-value list position)
(define (get-sum-iter prevList counter)(
cond
((= counter (- position 1)) (+ (car prevList) (car (cdr prevList))))
(else (get-sum-iter (cdr prevList) (+ counter 1)))
))
(get-sum-iter list 0)
)
(define (create-list prevList size)
(define (create-list-iter currList counter)(
cond
((or (= counter (- size 1)) (= counter 0)) (create-list-iter (cons 1 currList) (- counter 1)))
((> counter 0) (create-list-iter (cons (get-value prevList counter) currList) (- counter 1)))
(else currList)
))
(create-list-iter '() (- size 1))
)
(define (emptyOrFirst list)(
cond
((null? list) '())
(else (car list))
))
(define (pascal-triangle-iter resultList counter)
(cond
((> counter n) resultList)
(else (pascal-triangle-iter (cons (create-list (emptyOrFirst resultList) counter) resultList) (+ counter 1)))
)
)
(pascal-triangle-iter '() 1)
)

scheme - display won't print on screen in a recursive function

I have the function getBoundedVars which uses the function boundsInLambda. In the end of it all the box bBox should contain all bounded variables in the expression exp.
I'm trying to debug this function and in order to do so I want to print the parameters of boundsInLambda every time the function is being activated but for some reason the values won't show up on the screen.
If I put the display operation in getBoundedVars it will print it but those are just the values in the first iteration.
If I run the following :
(getBoundedVars (lambda-simple (x) (lambda-simple (y) (const x))) bx)
when bx is an empty box,
'1 will be printed but the print commands in boundsInLambda will not
here's the code:
(define getBoundedVars
(lambda (exp bBox)
(if (atom? exp)
0 ;; don't put in box
(if (lambda? (car exp))
(begin
(display 1)
(newline)
(let ((pBox (make-pBox exp))
(lBox (box '()))
(bodyExp (make-body exp))
)
(boundsInLambda bodyExp lBox pBox bBox)))
(begin
(getBoundedVars (car exp) bBox)
(getBoundedVars (cdr exp) bBox))))))
(define boundsInLambda
(lambda (bodyExp lastBox paramBox boundsBox)
(newline)
(display `(bodyExp: ,bodyExp))
(newline)
(display `(lastBox: ,lastBox))
(newline)
(display `(paramBox: ,paramBox))
(newline)
(display `(boundsBox: ,boundsBox))
(newline)
(if (and (not (null? bodyExp))
(list bodyExp)
(equal? (car bodyExp) 'seq)
)
(map boundsInLambda (cadr bodyExp))
(let* ( (lists* (filter (lambda (el) (and (not (null? el)) (list? el) (not (equal? (car el) 'const)))) bodyExp))
(lists (map (lambda (el) (if (equal? (car el) 'set) (cddr el) el)) lists*))
(bounds (filter (lambda (el) (and (member el (unbox lastBox)) (not (member el (unbox paramBox))))) bodyExp))
(listsLeft? (> (length lists) 0))
(anyBounds? (> (length bounds) 0))
)
(if anyBounds?
(begin
(set-box! boundsBox (append (unbox boundsBox) bounds))))
(if listsLeft?
(map
(lambda (lst)
(if (lambda? (car lst))
(let* ((newBodyExp (make-body lst))
(newParamBox (make-pBox exp))
(newLastBox (box (append (unbox lastBox) (unbox paramBox))))
)
(boundsInLambda newBodyExp newLastBox newParamBox boundsBox))
(boundsInLambda lst lastBox paramBox boundsBox)))
lists)
0))
)))
(define make-pBox
(lambda (lamExp)
(if (equal? (car lamExp) 'lambda-simple)
(box (cadr lamExp))
(if (equal? (car lamExp) 'lambda-opt)
(box (cadr lamExp))
(box '())))))
(define make-body
(lambda (lamExp)
(if (equal? (car lamExp) 'lambda-opt)
(cdddr lamExp)
(cddr lamExp))))
any help would be very much appreciated.

SCHEME Mutable Functions

I've been self-teaching myself Scheme R5RS for the past few months and have just started learning about mutable functions. I've did a couple of functions like this, but seem to find my mistake for this one.
(define (lst-functions)
(let ((lst '()))
(define (sum lst)
(cond ((null? lst) 0)
(else
(+ (car lst) (sum (cdr lst))))))
(define (length? lst)
(cond ((null? lst) 0)
(else
(+ 1 (length? (cdr lst))))))
(define (average)
(/ (sum lst) (length? lst)))
(define (insert x)
(set! lst (cons x lst)))
(lambda (function)
(cond ((eq? function 'sum) sum)
((eq? function 'length) length?)
((eq? function 'average) average)
((eq? function 'insert) insert)
(else
'undefined)))))
(define func (lst-functions))
((func 'insert) 2)
((func 'average))
You're not declaring the lst parameter in the procedures that use it, but you're passing it when invoking them. I marked the lines that were modified, try this:
(define (lst-functions)
(let ((lst '()))
(define (sum lst) ; modified
(cond ((null? lst) 0)
(else
(+ (car lst) (sum (cdr lst))))))
(define (length? lst) ; modified
(cond ((null? lst) 0)
(else
(+ 1 (length? (cdr lst))))))
(define (average)
(/ (sum lst) (length? lst)))
(define (insert x)
(set! lst (cons x lst)))
(lambda (function)
(cond ((eq? function 'sum) (lambda () (sum lst))) ; modified
((eq? function 'length) (lambda () (length? lst))) ; modified
((eq? function 'average) average)
((eq? function 'insert) insert)
(else
'undefined)))))
Now it works as expected:
(define func (lst-functions))
((func 'insert) 2)
((func 'average))
=> 2
((func 'sum))
=> 2
((func 'length))
=> 1
Some of your functions are recursive but defined without argument. Thus (sum (cdr lst)) shouldn't work since sum uses lst. You could do it by defining a helper:
(define (sum-rec lst)
(if (null? lst)
0
(+ (car lst) (sum-rec (cdr lst)))))
Or perhaps with an accumulator:
(define (sum-iter lst acc)
(if (null? lst)
acc
(sum-iter (cdr lst) (+ (car lst) acc)))
Your sum would of course use it passing the lst:
(define (sum)
(sum-iter lst 0))
Or you can just have the driver partial apply them like this:
(lambda (function)
(cond ((eq? function 'sum) (lambda () (sum-iter lst))
...))
A side note. length? is a strangely named function. A question mark in the end of a name is usually reserved for functions that return a true or a false value and this clearly returns a number.

Scheme function that returns a function

I need to write a scheme function that returns as a function which then takes another argument, eg a list and in turn return the desired result. In this example (c?r "arg") would return -- (car(cdr -- which then subsequently takes the list argument to return 2
> ((c?r "ar") '(1 2 3 4))
2
> ((c?r "ara") '((1 2) 3 4))
2
The problem I have is how can I return a function that accepts another arg in petite?
Here's how you might write such a function:
(define (c?r cmds)
(lambda (lst)
(let recur ((cmds (string->list cmds)))
(if (null? cmds)
lst
(case (car cmds)
((#\a) (car (recur (cdr cmds))))
((#\d) (cdr (recur (cdr cmds))))
(else (recur (cdr cmds))))))))
Note that I'm using d to signify cdr, not r (which makes no sense, to me). You can also write this more succinctly using string-fold-right (requires SRFI 13):
(define (c?r cmds)
(lambda (lst)
(string-fold-right (lambda (cmd x)
(case cmd
((#\a) (car x))
((#\d) (cdr x))
(else x)))
lst cmds)))
Just wanted to add my playing with this. Uses SRFI-1.
(import (rnrs)
(only (srfi :1) fold)) ;; require fold from SRFI-1
(define (c?r str)
(define ops (reverse (string->list str)))
(lambda (lst)
(fold (lambda (x acc)
((if (eq? x #\a) car cdr) ; choose car or cdr for application
acc))
lst
ops)))
Its very similar to Chris' version (more the previous fold-right) but I do the reverseso i can use fold in the returned procedure. I choose which of car or cdr to call by looking at the character.
EDIT
Here is an alternative version with much more preprocessing. It uses tail-ref and list-tail as shortcuts when there are runs of #\d's.
(define (c?r str)
(let loop ((druns 0) (ops (string->list str)) (funs '()))
(cond ((null? ops)
(let ((funs (reverse
(if (zero? druns)
funs
(cons (lambda (x)
(list-tail x druns))
funs)))))
(lambda (lst)
(fold (lambda (fun lst)
(fun lst))
lst
funs))))
((eq? (car ops) #\d) (loop (+ druns 1) (cdr ops) funs))
((= druns 0) (loop 0 (cdr ops) (cons car funs)))
(else (loop 0 (cdr ops) (cons (lambda (x)
(list-ref x druns))
funs))))))
This can be made even simpler in #!racket. we skip the reverse and just do (apply compose1 funs).
(define (c?r str)
(let loop ((druns 0) (ops (string->list str)) (funs '()))
(cond ((null? ops)
(let ((funs (if (zero? druns)
funs
(cons (lambda (x)
(list-tail x druns))
funs))))
(apply compose1 funs)))
((eq? (car ops) #\d) (loop (+ druns 1) (cdr ops) funs))
((= druns 0) (loop 0 (cdr ops) (cons car funs)))
(else (loop 0 (cdr ops) (cons (lambda (x)
(list-ref x druns))
funs))))))
Assuming a compose procedure:
(define (compose funs . args)
(if (null? funs)
(apply values args)
(compose (cdr funs) (apply (car funs) args))))
(compose (list cdr car) '(1 2 3 4))
=> 2
c?r can be defined in terms of compose like so:
(define (c?r funs)
(lambda (e)
(compose
(map
(lambda (f) (if (char=? f #\a) car cdr))
(reverse (string->list funs)))
e)))
then
((c?r "ar") '(1 2 3 4))
=> 2
((c?r "ara") '((1 2) 3 4))
=> 2

Add even items in list

I'd like to add the even items in a list and have the following algorithm I wrote to achieve the objective.
The error I am getting is:
+: expects type <number> as 2nd argument, given: #<void>; other arguments were: 4
The code:
(define (mylength alist cnt)
(if (null? alist)
0
(if (= (modulo cnt 2) 0)(+ (car alist) (mylength (cdr alist) (+ cnt 1)))))
(if (= (modulo cnt 2) 1)(mylength (cdr alist) (+ cnt 1))))
Could you please advise on the
i) error
ii) logic of the algorithm
Thanks!
First, indent your code properly:
(define (mylength alist cnt)
(if (null? alist) ;
0 ; this section is wasted because
(if (= (modulo cnt 2) 0) ; it's not the last expression
(+ (car alist) (mylength (cdr alist) (+ cnt 1))))) ;
(if (= (modulo cnt 2) 1) ; this if is the last expression, but
(mylength (cdr alist) (+ cnt 1)))) ; if it's false you get #<void>
You shouldn't have if expressions that don't have both the true and false branches. You have to remember that this isn't C, and anything that's not the last expression will be run and then thrown away.
Combine the last two if statements into one if statement:
(define (mylength alist cnt)
(if (null? alist)
0
(if (= (modulo cnt 2) 0)
(+ (car alist) (mylength (cdr alist) (+ cnt 1)))
(mylength (cdr alist) (+ cnt 1)))))
Edit: When I wrote "anything that's not the last expression will be run and then thrown away", I meant:
(begin
(+ 2 2)
(+ 4 1)
(+ 1 0)
(+ 1 1)) => 2
(let ((x 5))
(add1 x)
(+ x 2)
(* x 2)) => 10
((lambda ()
(if #t 3)
(if #f 0 4)
(if #t 2))) => 2
The other answer is completely right, but your interface is not very scheme-y. This is a more common form with tail recursion.
; Assumes given a list of numbers. Returns sum of even indices.
(define (mylength alist)
(let helper ((alist alist) (acc 0))
(cond
((null? alist) acc)
((null? (cdr alist)) (+ acc (car alist)))
(else (helper (cddr alist) (+ acc (car alist)))))))

Resources