I'm creating a tail recursive function that evaluates a polynomial by passing a list of coefficients and an x value.
example: evaluate x^3 + 2x^2 + 5, so the user would pass the list '(5 0 2 1) and an x like 1 in a functional call (poly '(5 0 2 1) 1).
I can't figure out why i'm getting the following error:
if: bad syntax in: (if (null? (cdr lst)) (+ total (car lst))
eval-poly-tail-helper ((cdr lst) x (+ (* (expt x n) (car lst)) total)
(+ 1 n)))
(define (poly lst x)
(poly-assistant lst x 0 0))
(define (poly-assistant lst x total n)
(if (null? (cdr lst))
(+ total (car lst))
poly-assistant((cdr lst) x (+ (* (expt x n) (car lst)) total) (+ 1 n))))
You need a left paren before poly-assistant in the last line.
In Scheme, function applications start with a left paren. And if takes 2 or 3 operands.
Use a better editor (e.g. emacs) able to match parenthesis.
The two left parenthesis before cdr looks suspicious. You might need only one.
Learn to use your Scheme debugger, or at least add debugging prints.
I am attempting to accept a list, have it count the positive, negative, and zeros, and return a new list.
The only thing I notice as I'm debugging is that the list is iterating through, but it is not utilizing any of the conditionals. So its successfully recursively calling itself, and then it just errors once its empty.
(define (mydisplay value)
(display value)
(newline)
#t
)
(define neg 0)
(define z 0)
(define pos 0)
(define (posneg lst)
(cond
((NULL? lst))
(NEGATIVE? (car lst) (+ 1 neg))
(ZERO? (car (lst)) (+ 1 z))
(else (+ 1 pos))
)
(posneg (cdr lst))
)
(mydisplay (posneg '(1 2 3 4 2 0 -2 3 23 -3)))
(mydisplay (posneg '(-1 2 -3 4 2 0 -2 3 -23 -3 0 0)))
(mydisplay (posneg '()))
OK, my favorite technique to apply here is wishful thinking as I learned it from Gerald Jay Sussman and Hal Abelson in the Structure and Interpretation of Computer Programs (SICP) course. Particularly, video lecture 2B. Compound Data will be of interest to you.
Let's start by just pretending (wishing) with have this data container available to us that holds 3 values: one for positives, one for negatives, and one for zeros. We'll call it pnz.
The way to create one of these is simple
; construct a pnz that has 1 positive, 4 negatives, and 2 zeros
(define x (make-pnz 1 4 2))
To select the positives value
(positives x) ;=> 1
To select a negatives value
(negatives x) ;=> 4
To select the zeros value
(zeros x) ;=> 2
Forget for a moment that these procedures don't exist (yet). Instead, just wish that they did and begin writing the procedure to solve your problem.
We'll start with some pseudocode
; pseudocode
define count-pnz xs
if xs is null? return (make-pnz p n z)
if (car xs) is positive, update the positive count by one
if (car xs) is negative, update the negative count by one
if (car xs) is zero, update the zero count by one
return count-pnz (cdr xs)
OK, that's pretty straight forward actually. Well, with one little gotcha. Notice I'm saying "update the count by one"? Well we need somewhere to store that count as the procedure is iterating. Let's make a slight adjustment to the pseudocode, this time including a pnz parameter to keep track of our current count
; pseudocode v2
define count-pnz xs pnz=(0 0 0)
if xs is null? return (make-pnz p n z)
if (car xs) is positive, nextpnz = (make-pnz p+1 n z)
if (car xs) is negative, nextpnz = (make-pnz p n+1 z)
if (car xs) is zero, nextpnz = (make-pnz p n z+1)
return count-pnz (cdr xs) nextpnz
Now this procedure makes sense to me. In the simplest case where xs is an empty list, it will simply return a pnz of (0 0 0). If xs has any number of values, it will iterate through the list, one-by-one, and increment the corresponding value in the pnz container.
Translating this into scheme is a breeze
; wishful thinking
; we will define make-pnz, positives, negatives, and zeros later
(define (count-pnz xs (pnz (make-pnz 0 0 0)))
(let [(p (positives pnz))
(n (negatives pnz))
(z (zeros pnz))]
(cond [(null? xs) pnz]
[(> (car xs) 0) (count-pnz (cdr xs) (make-pnz (+ 1 p) n z))]
[(< (car xs) 0) (count-pnz (cdr xs) (make-pnz p (+ 1 n) z))]
[(= (car xs) 0) (count-pnz (cdr xs) (make-pnz p n (+ 1 z)))])))
You'll notice I used a let here to make it easier to reference the individual p, n, z values of the current iteration. That way, when we detect a positive, negative, or zero, we can easily increment the appropriate value by simply doing (+ 1 p), (+ 1 n), or (+ 1 z) accordingly. Values that are not meant to be incremented can simply be passed on untouched.
We're getting extremely close. Our procedure make logical sense but we need to define make-pnz, positives, negatives, and zeros before it can work. By the way, this methodology of defining data objects by creating constructors and selectors to isolate use from representation is called data abstraction. You'll learn more about that in the video I linked, if you're interested.
So here's the contract that we need to fulfill
; PNZ CONTRACT
; pnz *must* behave like this
(positives (make-pnz p n z)) ⇒ p
(negatives (make-pnz p n z)) ⇒ n
(zeros (make-pnz p n z)) ⇒ z
Let's implement it !
; constructor
(define (make-pnz p n z)
(list p n z))
; positives selector
(define (positives pnz)
(car pnz))
; negatives selector
(define (negatives pnz)
(cadr pnz))
; zeros selector
(define (zeros pnz)
(caddr pnz))
Pff, well that was easy as can be ! Using a list, car, cadr, and caddr made our job simple and it's easy to understand how pnz behaves.
Without further ado, let's see this thing in action now
(define answer (count-pnz '(-1 2 -3 4 2 0 -2 3 -23 -3 0 0)))
(positives answer) ; => 4
(negatives answer) ; => 5
(zeros answer) ; => 3
And there you have it. Wishful thinking and a dash of data abstraction to the rescue.
Data abstraction is a very powerful concept. You might be thinking, "Why didn't we just use list in the count-pnz procedure instead of all of this constructor/selector ceremony?" The answer may not be readily apparent, but it is a bit too much for me to get into with this post. Instead, I sincerely do hope you check out the learning resources I linked as I'm certain they will be of great benefit to you.
#DavinTryon says "#naomik's answer could be defined in something other than a list (even just functions)."
Yep, that's totally true. Let's see make-pnz, positives, negatives, and zero implemented in a different way. Remember, the contract still has to be fulfilled in order for this implementation to be considered valid.
; constructor
(define (make-pnz p n z)
(λ (f) (f p n z)))
; selectors
(define (positives pnz)
(pnz (λ (p n z) p)))
(define (negatives pnz)
(pnz (λ (p n z) n)))
(define (zeros pnz)
(pnz (λ (p n z) z)))
Pretty cool. This demonstrates the beauty of data abstraction. We were able to completely re-implement make-pnz, positives, negatives, and zeros in a different way, but because we still fulfilled the original contract, our count-pnz function does not need to change at all.
First, let me say that #naomik's answer is awesome. This is the way to deconstruct the problem and build it up step by step.
When I first read the question, what I ended up thinking was:
How can I reduce a list of integers to the defined list '(p n z)?
So reduce means perhaps using foldl or foldr.
Here is example with foldr (returning a list in the format '(p n z)):
(define (count-pnz xs)
(foldr (lambda (next prev)
(cond ((= next 0) (list (car prev) (cadr prev) (+ 1 (caddr prev))))
((< next 0) (list (car prev) (+ 1 (cadr prev)) (caddr prev)))
(else (list (+ 1 (car prev)) (cadr prev) (caddr prev)))))
'(0 0 0) xs))
The body of the solution is the lambda we are using to reduce. Essentially, this just adds 1 to the p, n or z position of the list (using car, cadr and caddr respectively).
*note, this solution is not optimized.
A better way to keep values while computing are by making a helper that has the data you want to keep as arguments. Updating the value is the same as recursing by providing a new value:
(define (pos-neg-zero lst)
(define (helper pos neg zero lst)
(cond ((null? lst) (pnz pos neg zero)) ; the result
((positive? (car lst)) (helper (+ 1 pos) neg zero (cdr lst)))
((negative? (car lst)) (helper pos (+ neg 1) zero (cdr lst)))
(else (helper pos neg (+ zero 1) (cdr lst)))))
(helper 0 0 0 lst))
I like #naomik's abstraction but unboxing/boxing for each iteration within the helper is perhaps overkill. Though having a contract is nice and both Racket and R6RS supports making your own types:
;; scheme version (r6rs)
(define-record-type (pnz-type pnz pnz?)
(fields
(immutable p pnz-p)
(immutable n pnz-n)
(immutable z pnz-z)))
;; racket
(struct pnz (p n z) #:transparent)
An alternative would be it returned the values as separate results with values or it could take a continuation:
(define (pos-neg-zero lst . lcont)
(define cont (if (null? lcont) values (car lcont)))
(define (helper pos neg zero lst)
(cond ((null? lst) (cont pos neg zero)) ; the result
((positive? (car lst)) (helper (+ 1 pos) neg zero (cdr lst)))
((negative? (car lst)) (helper pos (+ neg 1) zero (cdr lst)))
(else (helper pos neg (+ zero 1) (cdr lst)))))
(helper 0 0 0 lst))
(pos-neg-zero '(1 -3 0)) ; returns 1, 1, and 1
(pos-neg-zero '(1 -3 0) pnz) ; returns result as an object
(pos-neg-zero '(1 -3 0) list) ; returns result as a list
(pos-neg-zero '(1 -3 0) (lambda (p n z) (+ p n z))) ; does something with the results
#!racket has optional arguments so the prototype could be just without having to have the first expression to check if there was passed an extra argument or not:
(define (pos-neg-zero lst (cont values))
...)
So far I have assumed that the last two should be:
(define or-gate
(lambda (a b)
(if (= a 1)
1
(if (= b 1)
1
0))))
(define xor-gate
(lambda (a b)
(if (= a b)
0
1)))
...but the AND one is puzzling. How can I implement it?
It's simple if we remember that = can accept more than two parameters:
(define and-gate
(lambda (a b)
(if (= a b 1)
1
0)))
In words: the and logical connector is true if and only if both of its arguments are true, for all other arguments it's false.
What is the truth table for and? Actually if you have a truth table for any of and or or or xor then the algorithm is identical.
Let's make a function that accepts a truth table and returns a function that computes the gate logic
(define (gate-logic-for-truth-table table)
(lambda (a b)
(vector-ref (vector-ref table b) a)))
Now, with the truth table for and we produce the and-gate function:
(define and-gate (gate-logic-for-truth-table
'#(#(0 0)
#(0 1))))
And a mini-test:
> (and-gate 0 0)
0
> (and-gate 0 1)
0
> (and-gate 1 0)
0
> (and-gate 1 1)
1
Assuming that the parameters are either 1 or 0:
For or, you don't need to look at b if a is 1 - the result is 1. Otherwise the result is b.
For and, you don't need to look at b if a is 0 - the result is 0. Otherwise the result is b.
If you want to make it as similar to or-gate as possible, you can replace the 1s with 0s in the outer conditional:
(define and-gate
(lambda (a b)
(if (= a 0)
0
(if (= b 1)
1
0))))
or, if you want to stick to comparisons with 1, you can rearrange the branches:
(define and-gate
(lambda (a b)
(if (= a 1)
(if (= b 1)
1
0)
0)))
It's possible to shorten the code:
(define and-gate
(lambda (a b)
(if (= a 1)
b
0)))
and
(define or-gate
(lambda (a b)
(if (= a 1)
1
b)))
but whether this is more readable is pretty individual.
If we're going to work with gates, we probably ought to start by defining a method for constructing them. I mean we are going to have to construct three gates.
#lang racket
;; Gate Constructor
(define (make-gate predicate)
(lambda (A B)
(predicate A B)))
Then we can define the gates at a high level using wishful thinking:
(define and-gate
(make-gate and-predicate))
(define or-gate
(make-gate or-predicate))
(define xor-gate
(make-gate xor-predicate))
Then we can arbitrarily define the internal gate logic however we fancy:
(define (and-predicate A B)
(let ([a (if A 1 0)]
[b (if B 1 0)])
(= 2 (+ a b))))
(define (or-predicate A B)
(let ([a (if A 1 0)]
[b (if B 1 0)])
(< 0 (+ a b))))
(define (xor-predicate A B)
(let ([a (if A 1 0)]
[b (if B 1 0)])
(= 1 (+ a b))))
Then we do the real work of testing...ok, maybe we actually should have started by writing the tests.
(module+ test
(require rackunit
rackunit/text-ui)
(define (make-test-harness test-function)
(define (test-harness ins outs)
(if (or (null? ins)
(null? outs))
'test-complete
(begin
(test-function (first ins)
(first outs))
(test-harness (rest ins)
(rest outs)))))
test-harness))
(define gate-inputs
'((#f #f)
(#t #f)
(#f #t)
(#t #t)))
(define and-truth-table
'(#f #f #f #t))
(define or-truth-table
'(#f #t #t #t))
(define xor-truth-table
'(#f #t #t #f))
(define (make-gate-test gate name)
(lambda (input correct)
(define A (first input))
(define B (second input))
(test-equal? name
(gate A B)
correct)))
(define and-gate-test
(make-gate-test and-gate "AND Gate Test"))
(define or-gate-test
(make-gate-test or-gate "OR Gate Test"))
(define xor-gate-test
(make-gate-test xor-gate "XOR Gate Test"))
(define (and-tests)
(define tests
(make-test-harness and-gate-test))
(tests gate-inputs and-truth-table))
(define (or-tests)
(define tests
(make-test-harness or-gate-test))
(tests gate-inputs or-truth-table))
(define (xor-tests)
(define tests
(make-test-harness xor-gate-test))
(tests gate-inputs xor-truth-table))
(define-test-suite
all-gate-tests
(and-tests)
(or-tests)
(xor-tests))
(run-tests all-gate-tests))
Run the Tests
racket#29761897.rkt> ,enter "/home/ben/StackOverflow/29761897.rkt"
12 success(es) 0 failure(s) 0 error(s) 12 test(s) run
0
Since all the tests pass, we can now turn in our homework [as always subject to academic policy].
Notes
Using truth values #f and #t provides cleaner hooks into Racket's testing tools. It also allows writing predicates directly rather than serializing and deserializing 1 and 0.
Here is a simple definition where the truth table is clear:
(define (and-gate a b)
(cond
[(and (= a 0) (= b 0)) 0]
[(and (= a 0) (= b 1)) 0]
[(and (= a 1) (= b 0)) 0]
[(and (= a 1) (= b 1)) 1]))
If we note that only one clause has 1 as a result and all others give 0,
we can write:
(define (and-gate a b)
(cond
[(and (= a 1) (= b 1)) 1]
[else 0]))
I'm not sure how to do this and couldn't find an example of it anywhere. How do I find the position of a value in a list. For example I have a (define findValue x lst) which accepts a value and list and from that list I want type in (findValue 3 '(1 2 0 8 5 6)) and it should return 0 since the value in position 3 is 0. From my understanding and how it usually is position 3 would be 8 and not 0 in arrays at least. How does it work in here and how do I approach this problem?
Thanks!
Try:
(define (at n xs)
(cond ((null? xs) xs)
((= n 1) (car xs))
(else (at (- n 1) (cdr xs)))))
Use it as follows:
(at 3 '(1 2 0 8 5 6)) => 0
For zero-based indexing change the (= n 1) check on the 3rd line to (= n 0).
Edit: So you want to partially apply the at function? All you need is curry and flip. They are defined as follows:
(define (curry func . args)
(lambda x (apply func (append args x))))
(define (flip func)
(lambda (a b) (func b a)))
Using curry and flip you can now partially apply at as follows:
(define position (curry (flip at) '(1 2 0 8 5 6)))
You can now use position as follows:
(position 3) => 0
(position 4) => 8
Hope that helped.
Usually indexes are counted starting from 0, and your understanding is correct. But if you're required to implement a findValue procedure that starts counting indexes from 1, it's not that hard to write the procedure:
(define (findValue idx lst)
(cond ((or (null? lst) (negative? idx)) #f)
((= idx 1) (car lst))
(else (findValue (sub1 idx) (cdr lst)))))
Explanation:
If the list received as parameter is empty or the index becomes negative, we treat that as a special case and return #f to indicate that the value was not found
If the index is 1 then we're right where we wanted, so it's time to return the current element
Otherwise advance the recursion: subtract one from the index and advance one position over the list
It works as expected:
(findValue 3 '(1 2 0 8 5 6))
=> 0
(findValue -1 '(1 2 0 8 5 6))
=> #f
(findValue 7 '(1 2 0 8 5 6))
=> #f
I am trying to write a function which takes a list (x) and a number (y) and deletes every occurance of that number in the list. Ex. (deepdeleting '(0 0 1 2 0 3 0) 0) ===> '(1 2 3)
Here's what I have so far:
(define (deepdeleting x y)
(if (pair? x)
(if (eqv? (car x) y)
(begin
(set! x (cdr x))
(deepdeleting x y)
)
(deepdeleting (cdr x) y) ; else
)
x ; else
)
)
The code works, but my problem is I want it to modify the original list, not just return a new list. Right now this is what happens:
> (define list '(0 0 1 2 0 3 0))
> (deepdeleting list 0)
(1 2 3)
> list
(0 0 1 2 0 3 0) ; <<< I want this to be (1 2 3)
This seems strange to me since both the set-car! and set-cdr! functions seem to change the input list, whereas set! does not...
Any insight would be much appreciated!
When you use set! you are redefining the innermost binding:
(define test 10)
(set! test 11) ; changes global test to 11
(define (change-test value)
(set! test value))
(change-test 12) ; changes global test to 12
(define (change-test! value new-value)
(display value)
(set! value new-value) ; changes the local binding value
(display value))
(change-test! test 13) ; changes nothing outside of change-test, prints 12 then 13
Variable bindings are totally different than list structure mutation. Here a binding is used to point to a pair that is altered:
(define lst '(1 2 3))
(define lst2 (cdr lst)) ; lst2 shares structure with lst
(set-cdr! lst2 '(8 7 6 5))
lst2 ; ==> (2 8 7 6 5)
lst ; ==> (1 2 8 7 6 5) the original binding share structure thus is changed too
(set-cdr! lst lst) ; makes a circular never ending list (1 1 1 1 ...)
(eq? lst (cdr lst)) ;==> #t
(set-car! lst 2) ; changes lst to be never ending list (2 2 2 2 ...)
So you can mutate pairs with set-cdr! and set-car! and a binding to the original list will point to the first pair. Thus you need the result to start with the same pair as the first. With that you can make your mutating procedure this way:
#!r6rs
(import (rnrs) (rnrs mutable-pairs))
(define (remove! lst e)
(if (pair? lst)
(let loop ((prev lst)(cur (cdr lst)))
(if (pair? cur)
(if (eqv? (car cur) e)
(begin
(set-cdr! prev (cdr cur))
(loop prev (cdr cur)))
(loop cur (cdr cur)))
(if (eqv? (car lst) e)
(if (pair? (cdr lst))
(begin
(set-car! lst (cadr lst))
(set-cdr! lst (cddr lst)))
(error 'first-pair-error "Not possible to remove the first pair"))
#f)))
#f))
(define test '(0 0 1 2 0 3 0))
(define test2 (cdr test))
test2 ;==> (0 1 2 0 3 0)
(remove! test 0)
test ; ==> (1 2 3)
test2 ; ==> (0 1 2 0 3 0)
(remove! '(0) 0)
; ==> first-pair-error: Not possible to remove the first pair
(remove! '(1 2 3) 2) ; this works too but you have no way of checking
While lst is bound to the list during removal and the same list has one element less there was not binding to it outside of the remove! procedure so the result is forever lost.
EDIT
For R5RS remove the first two lines and add error:
;; won't halt the program but displays the error message
(define (error sym str)
(display str)
(newline))