Scheme program to get average not recognizing last number - scheme

I've created this super simple program to take a list from the console and return the average. For whatever reason I always get an error message saying the last number of the list is not a number. Here's my code:
(define getline (lambda ()
(read-line (current-input-port))
)
)
(define getlist (lambda ()
(let ((input (getline)))
(if (not (equal? input "end"))
(cons input (getlist))
' ()
)
)
)
)
(define x (getlist))
(define (sum x)
(if (null? x)
0
(+ (car x) (sum (cdr x)))))
(define (average x)
(/ (sum x) (length x)))
(display (average x) (current-output-port))

You don't mention what scheme implementation you're using, but read-line functions usually return a string. You have to convert those strings to numbers first to be able to add them:
(define x (map string->number (getlist)))
or else
(define (sum x)
(if (null? x)
0
(+ (string->number (car x)) (sum (cdr x)))))
or something else along those lines.

Related

scheme, sicp, solution 3.19, procedure with infinite loop works in case it is provided as argument

could someone help me with clarification to one of the possible solution to exercise 3.19. the procedure mystery is infinite loop in case list cycle is given as argument. nevertheless when we use procedure eq? to check if list contains the cycle, it works and provides true value.
(define (last-pair x)
(if (null? (cdr x))
x
(last-pair (cdr x))
)
)
(define (make-cycle x)
(set-cdr! (last-pair x) x)
)
(define (mystery x)
(define (loop x y)
(if (null? x)
y
(let ((temp (cdr x)))
(set-cdr! x y)
(loop temp x)
)
)
)
(loop x '())
)
(define t (list 1 2 3))
(define w (make-cycle t))
(eq? (mystery t) t)
it looks like magic. I would appreciate for any help.
mystery reverses an array "in-place" by repeatedly snipping off the cdr of each entry and replacing that with the cdr of the previous x.
If this list has no loop, then it will end up reversed by the time you get back to the original '(). If there is a loop, you'll have the original array's pointer.
This is definitely a tricky to understand issue. If you make a box-and-pointer diagram it will definitely help and you'll only need to draw 3 diagrams.
Automatically Generating Diagrams of Lists
In the process of doing SICP myself, I found myself wanting a way to visualize list mutation (and to skip the numerous "draw a list diagram of..." exercises). I wrote a small function for doing so and I thought you might find it helpful if I shared it.
These diagrams are an example of this function being run on x each time loop (within the mystery function) is ran.
The following code is what I used for generating these diagrams. I wrote this code as a Scheme novice, but it's very simple to use: the function (list->graphviz) accepts a parameter lst which is the list you'd like a diagram of, as well as an optional argument graph-name which gives the graph a special name.
(define* (list->graphviz lst #:optional graph-name)
"""Convert a list into a set of Graphviz instructions
`lst' is the list you'd like a diagram of
`graph-name` is an optional parameter indicating the name you'd like to give the graph."""
(define number 0)
(define result "")
(define ordinals '())
(define (result-append! str)
(set! result (string-append result str)))
(define* (nodename n #:optional cell)
(format #f "cons~a~a" n (if cell (string-append ":" cell) "")))
(define* (build-connector from to #:optional from-cell)
(format #f "\t~a -> ~a;~%" (nodename from from-cell) (nodename to)))
(define (build-shape elt)
(define (build-label cell)
(cond ((null? cell) "/");; "∅") ; null character
((pair? cell) "*");; "•") ; bullet dot character
(else (format #f "~a" cell))))
(set! number (+ number 1))
(format #f "\t~a [shape=record,label=\"<car> ~a | <cdr> ~a\"];~%"
(nodename number)
(build-label (car elt))
(build-label (cdr elt))))
(define* (search xs #:optional from-id from-cell)
(let ((existing (assq xs ordinals)))
(cond
;; if we're not dealing with a pair, don't bother making a shape
((not (pair? xs)) (result-append! "\tnothing [shape=polygon, label=\"not a pair\"]\n"))
((pair? existing)
(result-append! (build-connector from-id (cdr existing) from-cell)))
(else
(begin
(result-append! (build-shape xs))
(set! ordinals (assq-set! ordinals xs number))
(let ((parent-id number))
;; make a X->Y connector
(if (number? from-id)
(result-append! (build-connector from-id parent-id from-cell)))
;; recurse
(if (pair? (car xs)) (search (car xs) parent-id "car"))
(if (pair? (cdr xs)) (search (cdr xs) parent-id "cdr"))))))))
(search lst)
(string-append "digraph " graph-name " {\n" result "}\n"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;; Here is where `mystery' begins ;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define t '(1 2 3))
(set-cdr! (cddr t) t)
(define (mystery x)
(define (loop x y graph-num)
(display (list->graphviz x (format #f "graph~a" graph-num)))
(if (null? x)
y
(let ((temp (cdr x)))
(set-cdr! x y)
(loop temp x (+ 1 graph-num)))))
(loop x '() 0))
(mystery t)
The code above code generates Graphviz graph description statements, which must then be processed by dot (Graphviz) to be rendered to a graphical format.
For example, you can run the code above and pipe it into dot:
$ scheme generate_box_ptr.scm | dot -o ptrs.ps -Tps
This command generates a postscript file which has the advantage of separating each list into it's own page if you've run list->graphviz more than once. dot can also output PNGs, PDFs and many other file formats as the manpage describes.

Outputting a sorted list of pairs in scheme recursively (issue with base case)

I want to sort and print out a list somewhat like this:
Apple : 1
Banana : 2
...etc (each pair is on a new line, but stackoverflow shows it like this)
I find that I can get it mostly done, but I get an error that it expects a pair, while it is given an empty list. I understand that the error is because I reached the end of my list, and that I need a base case here, but I'm not sure what is required. If I check to see if the list is null, and then return the list as my base case, it doesn't output anything.
Getting the following error:
car: contract violation expected: pair? given: ()
Thanks for checking out my problem.
(define lst '( ("Apple" 1) ("Orange" 4) ("Pear"3) ("Banana" 2)) )
(define name (lambda (m)
(car m)
))
(define priority (lambda (m)
(car (cdr m))
))
(define sortList
(lambda (lst)
(sort lst
(lambda (x y)
(<(priority x)(priority y))
)
)
)
)
(define printItem (lambda (m)
(display (name m))
(display " : ")
(display (priority m))
(display "\n")
)
)
(define printQueue
(lambda (lst)
(printItem (car(sortList lst)))
(printQueue (cdr (sortList lst)))
)
)
(printQueue lst)
You must ensure that the list is not empty for the procedure to work, that's the base case. Also avoid sorting the list twice at every iteration! try this:
(define printQueue
(lambda (lst)
(unless (null? lst)
(printItem (car lst))
(printQueue (cdr lst)))))
(printQueue (sortList lst))
By the way, it'd be more idiomatic to use a for-each in this case:
(define (printQueue lst)
(for-each printItem lst))

How to do square in RACKET

Here is my code:
(define (squares 1st)
(let loop([1st 1st] [acc 0])
(if (null? 1st)
acc
(loop (rest 1st) (* (first 1st) (first 1st) acc)))))
My test is:
(test (sum-squares '(1 2 3)) => 14 )
and it's failed.
The function input is a list of number [1 2 3] for example, and I need to square each number and sum them all together, output - number.
The test will return #t, if the correct answer was typed in.
This is rather similar to your previous question, but with a twist: here we add, instead of multiplying. And each element gets squared before adding it:
(define (sum-squares lst)
(if (empty? lst)
0
(+ (* (first lst) (first lst))
(sum-squares (rest lst)))))
As before, the procedure can also be written using tail recursion:
(define (sum-squares lst)
(let loop ([lst lst] [acc 0])
(if (empty? lst)
acc
(loop (rest lst) (+ (* (first lst) (first lst)) acc)))))
You must realize that both solutions share the same structure, what changes is:
We use + to combine the answers, instead of *
We square the current element (first lst) before adding it
The base case for adding a list is 0 (it was 1 for multiplication)
As a final comment, in a real application you shouldn't use explicit recursion, instead we would use higher-order procedures for composing our solution:
(define (square x)
(* x x))
(define (sum-squares lst)
(apply + (map square lst)))
Or even shorter, as a one-liner (but it's useful to have a square procedure around, so I prefer the previous solution):
(define (sum-squares lst)
(apply + (map (lambda (x) (* x x)) lst)))
Of course, any of the above solutions works as expected:
(sum-squares '())
=> 0
(sum-squares '(1 2 3))
=> 14
A more functional way would be to combine simple functions (sum and square) with high-order functions (map):
(define (square x) (* x x))
(define (sum lst) (foldl + 0 lst))
(define (sum-squares lst)
(sum (map square lst)))
I like Benesh's answer, just modifying it slightly so you don't have to traverse the list twice. (One fold vs a map and fold)
(define (square x) (* x x))
(define (square-y-and-addto-x x y) (+ x (square y)))
(define (sum-squares lst) (foldl square-y-and-addto-x 0 lst))
Or you can just define map-reduce
(define (map-reduce map-f reduce-f nil-value lst)
(if (null? lst)
nil-value
(map-reduce map-f reduce-f (reduce-f nil-value (map-f (car lst))))))
(define (sum-squares lst) (map-reduce square + 0 lst))
racket#> (define (f xs) (foldl (lambda (x b) (+ (* x x) b)) 0 xs))
racket#> (f '(1 2 3))
14
Without the use of loops or lamdas, cond can be used to solve this problem as follows ( printf is added just to make my exercises distinct. This is an exercise from SICP : exercise 1.3):
;; Takes three numbers and returns the sum of squares of two larger number
;; a,b,c -> int
;; returns -> int
(define (sum_sqr_two_large a b c)
(cond
((and (< a b) (< a c)) (sum-of-squares b c))
((and (< b c) (< b a)) (sum-of-squares a c))
((and (< c a) (< c b)) (sum-of-squares a b))
)
)
;; Sum of squares of numbers given
;; a,b -> int
;; returns -> int
(define (sum-of-squares a b)
(printf "ex. 1.3: ~a \n" (+ (square a)(square b)))
)
;; square of any integer
;; a -> int
;; returns -> int
(define (square a)
(* a a)
)
;; Sample invocation
(sum_sqr_two_large 1 2 6)

How to return the parameter value in Racket?

I have to create a Racket scheme that would return the reverse of a list. I cannot use the built in reverse method or anything like it.
So far I have done everything to reverse, but the problem is that my method is not returning the value, it is keeping it instead.
This is what I have done:
#lang racket
(define (rev x)
(define n '())
(define i (- (length x) 1))
(let loop ()
(when (> i -1)
(set! n (append n (list (list-ref x i))))
(set! i (sub1 i))
(loop)))
(set! x n)
"in method display"
(displayln x))
"display"
(define letters'("a" "b" "c"))
(rev letters)
"in main program display"
(displayln letters)
when I print inside the method, I get (c b a) but when I print from the main program I get (a b c) which means that my method is not returning the value. What should I do?
this method is returning void, how can I make it return a value?
The very last expression evaluated in a procedure is what gets "returned" so in rev it's (displayln x) and it returns a void. If you changed the last element to be n like this:
(define (rev x)
(define n '())
(define i (- (length x) 1))
(let loop ()
(when (> i -1)
(set! n (append n (list (list-ref x i))))
(set! i (sub1 i))
(loop)))
(set! x n)
"in method display"
(displayln x)
n) ; evaluates n last!
It would return the result as well. This code is very imperative for Scheme. Without changing how you solved this you could move n and i to the named let:
(define (rev x)
(let loop ((n '())
(i (- (length x) 1)))
(if (> i -1) ; if i is positive
(loop (append n (list (list-ref x i))) ; then call loop with new n and
(sub1 i)) ; new i
n))) ; else return n
A more idiomatic solution would be to cons the elements from the start to end into an accumulator. The first element will automatically become the last:
(define (rev lst)
(let loop ((lst lst) ; we start with the whole list
(acc '())) ; out initial acc is the empty list
(if (<??> lst) ; if lst is empty
<??> ; then return accumulator
(loop (<??> lst) ; else we recurse with the cdr of the list
(cons <??> acc))))) ; while adding the car to the beginning of acc

How do I use a pair to find which of two functions will evaluate the largest value? Scheme

Basically there is a pair made up of two functions and the code has to take the pair input x to find the highest evaluation for x and print that evaluation.
I receive the error:
car: contract violation expected: pair? given: 4
define (max x)
(lambda (x) ;I wanted lambda to be the highest suitable function
(if (> (car x) (cdr x))
(car x)
(cdr x))))
(define one-function (lambda (x) (+ x 1)))
(define second-function (lambda (x) (+ (* 2 x) 1))) ;my two functions
((max (cons one-function second-function)) 4)
And where are the functions being called? And you have two parameters called x, they must have different names. Try this:
(define (max f) ; you must use a different parameter name
(lambda (x)
(if (> ((car f) x) ((cdr f) x)) ; actually call the functions
((car f) x)
((cdr f) x))))
Now it'll work as expected:
((max (cons one-function second-function)) 4)
=> 9

Resources