Arithmetic expression parse - scheme

I want to parse an arithmetic expression into a binary tree represented as (list left right value). This is my code:
(define (parse exp)
(let loop ([e exp])
(cond
((and (list? e) (or (not (null? (car e))) (not (null? (caddr e)))))
(list (loop (car e)) (loop (caddr e)) (cadr e))))))
(parse '(1 + (2 * 3)))
The result is this and I don't know where from the void appears.
'(#<void> (#<void> #<void> *) +)

You're missing the base case of the recusion (here it's the else in cond form):
(define (parse exp)
(let loop ([e exp])
(cond
((and (list? e) (or (not (null? (car e))) (not (null? (caddr e)))))
(list (loop (car e)) (loop (caddr e)) (cadr e)))
(else e))))
Testing:
> (parse '(1 + (2 * 3)))
'(1 (2 3 *) +)
#<void> is the result of "falling through" the cond form (i.e. no condition matched, and there's no else):
> (void? (cond))
#t

Related

Removing all ()'s from a sublist in Racket

I need to have the following program interaction:
(clean'(1 (2 () (3 () 4))()()(()) 5)) → (1 (2 (3 4)) 5)
This is what I have so far
define (emptyClear theList)
(cond ((null? theList) '())
((null? (car theList)) (emptyClear (cdr theList)))
(else (cons (car theList) (emptyClear (cdr theList))))))
(define (clean tree)
(cond ((null? tree) '())
((not (list? (car tree))) (cons (car tree) (prune (cdr tree))))
(cons (emptyClear (car tree)) (prune (cdr tree)))))
But this gives me: -> (1 5) as the output.
How can I solve this issue?
From the example the task seems to be not simply to remove empty lists from a tree, but to continue to perform this operation until possible (since '(())) is not an empty list, but it is removed nevertheless).
Here is a possible solution, tested with DrRacket.
(define (my-empty? x)
(cond ((null? x) #t)
((list? x) (andmap my-empty? x))
(else #f)))
(define (clean x)
(cond ((null? x) '())
((not (list? x)) x)
((my-empty? (car x)) (clean (cdr x)))
(else (cons (clean (car x)) (clean (cdr x))))))
(clean '(1 (2 () (3 () 4))()()((())) 5)) ;=> '(1 (2 (3 4)) 5)

Removing extra parentheses in Scheme

Using a Scheme-like language, I am converting
(quote (lambda (a b) (* a b) (+ a b))))
to:
(quote (lambda (a) (lambda (b) (+ a b) (* a b))))
but with my current implementation I am getting an extra pair of parenthesis around the expressions (+ a b) and (* a b):
(lambda (a) (lambda (b) ((+ a b) (* a b))))
I have spent a lot of time trying to fix this problem, but can't figure it out. I feel like the fix should be trivial.
Here is my code currently:
(define (conv lyst)
(define (helper args)
(cond
((null? args) (append (cddr lyst) args))
(else (cons (car lyst)
(cons (list (car args))
(list (helper (cdr args))))))))
(cond
((eq? 1 (length (car (cdr lyst)))) lyst)
(else (helper (car (cdr lyst))))))
I think your implementation can be simplified. This should work:
(define (conv lyst)
(define (helper args)
(if (null? (cdr args))
(cons 'lambda
(append (list (list (car args)))
(cddr lyst)))
(list 'lambda
(list (car args))
(helper (cdr args)))))
(helper (cadr lyst)))
Or even simpler, using quasiquoting and splicing:
(define (conv lyst)
(define (helper args)
(if (null? (cdr args))
`(lambda (,(car args)) ,#(cddr lyst))
`(lambda (,(car args)) ,(helper (cdr args)))))
(helper (cadr lyst)))
Either way, it works as expected:
(conv '(lambda (a b) (* a b) (+ a b)))
=> '(lambda (a) (lambda (b) (* a b) (+ a b)))

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

scheme calculate root of binary tree

So I am trying to write a function that will calculate the root of a binary tree in scheme. The root is calculated by the following criteria: the value at the root is the maximum of the values at its two children, where each of those values is the minimum for its two children, etc. Alternating between maximizing the children and minimizing the children.
so (TREEMAX '((3 (2 5)) (7 (2 1))) would return 3, because 5 is the max of 2 and 5. 3 is the minimum of 3 and 5. 2 is the max of 2 and 1. 2 is the min of 7 and 2. And finally to get root 3 is the max of 3 and 2. The code I have so far is as follows:
(define TREEMAX
(lambda (a)
(cond ((list? (car a)) TREEMIN (car a))
((list? (cdr a)) TREEMIN (cdr a))
((> (car a) (cdr a)) (car a))
(#t (cdr b)))))
(define TREEMIN
(lambda (a)
(cond ((list? (car a)) TREEMAX (car a))
((list? (cdr a)) TREEMAX (cdr a))
((< (car a) (cdr a)) (car a))
(#t (cdr b)))))
But my code is not returning the right number. Where could I be going wrong?
If I understand your description correctly, this should do:
(define (root lst (res null) (maxmin #t))
(if (null? lst)
(apply (if maxmin max min) res)
(let ((c (car lst)))
(root (cdr lst)
(cons (if (list? c) (root c null (not maxmin)) c) res)
maxmin))))
then
> (root '((3 (2 5)) (7 (2 1))))
3
> (root '((3 (2 (1 5))) (7 ((2 7) 1))))
2
> (root '(1 2))
2
To see how it works, here's a version with a debugging printf:
(define (root lst (res null) (maxmin #t))
(if (null? lst)
(let* ((op (if maxmin max min)) (vl (apply op res)))
(printf "~a ~a = ~a\n" op res vl)
vl)
(let ((c (car lst)))
(root (cdr lst)
(cons (if (list? c) (root c null (not maxmin)) c) res)
maxmin))))
which outputs, for your example:
#<procedure:max> (5 2) = 5
#<procedure:min> (5 3) = 3
#<procedure:max> (1 2) = 2
#<procedure:min> (2 7) = 2
#<procedure:max> (2 3) = 3
When you apply the function car you use (car a) but when you apply the function TREEMAX you use TREEMAX (car a)?
The syntax of your code is wrong; you were unlucky that the errors are not flagged as syntax errors. Here is a fix:
(define TREEMAX
(lambda (a)
(cond ((list? (car a)) (TREEMIN (car a)))
((list? (cdr a)) (TREEMIN (cdr a)))
((> (car a) (cdr a)) (car a))
(else (cdr b))))
No idea if this solves your specific problem, but at least you'll be able to trust the computed value.

Trouble with simple calculator program in Scheme

I need to define a calculator for simple arithmetic expressions in Scheme. For example, when typing (calculator '( 1 + 2)), scheme interpreter will print 3. The calculator will accept expression of any length, and the expression associates to the right. Eg, in (calculator '(1 + 1 - 2 + 3 )) the expression is interpreted as (1 + (1 - (2 + 3))), hence the value is -3. I'm assuming the expression has + and - operators only and there are no brackets in the input. I wrote this program so far:
#lang lazy
(define (calculator exp)
(cond
((null? exp) 0)
(= (length (exp)) 1 exp)
(eq? '+ (cdr (cdr exp)) (+ (car exp) (calculator (cdr (cdr exp)))))
(else (eq? '- (cdr (cdr exp)) (- (car exp) (calculator (cdr (cdr exp)))))))
But when I try something like (calculator '(1 + 1 + 1)), I get this error:
#%module-begin: allowed only around a module body in: (#%module-begin (define
(calculator exp) (cond ((null? exp) 0) (= (length (exp)) 1 exp) (eq? (quote +)
(cdr (cdr exp)) (+ (car exp) (calculator (cdr (cdr exp))))) (else (eq? (quote -)
(cdr (cdr exp)) (- (car exp) (calculator (cdr (cdr exp)))))))) (calculator
(quote (1 + 1 + 1))))
I'm very new to Scheme so any help would be greatly appreciated
The syntax in your code isn't correct. As noted in the comment to your question, you've misplaced some parens. In Scheme you get a large benefit in 'tracking parens' by indenting consistently. Here is a version that gets you mostly there.
(define (calculator exp)
(cond ((null? exp) 0) ; zero terms
((null? (cdr exp)) (car exp)) ; one term only (assumed number)
(else ; assumed three or more terms
(let ((operand1 (car exp))
(operator (cadr exp))
(operands (cddr exp)))
((case operator ; convert operator, a symbol, to its function
((+) +)
((-) -))
operand1
(calculator operands)))))) ; calculate the rest
> (calculator '(1 + 2))
3
> (calculator '(1 - 2 + 3))
-4
In order to convert
1 - 2 + 3
to
(- 1 (+ 2 3))
you need to
cache value 1
apply - to the cached value 1 and the rest of the expression
cache value 2
apply + to the cached value 2 and the rest of the expression
cache value 3
return cached value 3 since your list is empty now
So your have 3 cases:
1) end of list => return cached value
otherwise toggle between
2) cache a value
3) apply the function to the cached value and the rest of the expression
Sample code:
(define (calculator exp)
(define funcs (hasheq '+ + '- -))
(let loop ((exp exp) (toggle #t) (val #f))
(if (empty? exp)
val ; 1) end of list => return cached value
(if toggle
(loop (cdr exp) #f (car exp)) ; 2) cache value
((hash-ref funcs (car exp)) val (loop (cdr exp) #t #f)))))) ; 3) apply the function to the cached value and the rest of the expression

Resources