How to do the reverse of format? - scheme

the format can turn any type into a string, e.g
(define lam-form (list `lambda (list `x ) (list `when (list `> `x 0) (list `* 100 `x ))))
(format "~s" lam-form)
result will be: "(lambda (x) (when (> x 0) (* 100 x)))"
Then my question is: how to do the reverse? meaning, turn "(lambda (x) (when (> x 0) (* 100 x)))" back to '(lambda (x) (when (> x 0) (* 100 x)))

Use read.
Welcome to Racket v5.1.3.1.
-> (read (open-input-string "(lambda (x) (when (> x 0) (* 100 x)))"))
'(lambda (x) (when (> x 0) (* 100 x)))

If you're referring only to the use of the "~s" formatting directive, then "read" is the right choice. See the docs for racket's "printf", then click through on the definition of "write" for more information.
If, on the other hand, you want to reverse any use of format, then there may be no unique answer; e.g., undoing (format "~a~a" "abc" "def") is not possible (in the sense that there are multiple possible calls that produce abcdef ).

Related

Racket: Trying to subtract numbers, getting list

I'm currently learning Racket/Scheme for a course (I'm not sure what's the difference, actually, and I'm not sure if the course covered that). I'm trying a basic example, implementing the Newton method to find a square root of a number; however, I ran into a problem with finding the distance between two numbers.
It seems that for whatever reason, when I'm trying to apply the subtraction operator between two numbers, it returns a list instead.
#lang racket
(define distance
(lambda (x y) (
(print (real? x))
(print (real? y))
(abs (- x y))
)
)
)
(define abs
(lambda x (
(print (list? x))
(if (< x 0) (- x) x)
)
)
)
(distance 2 5)
As you can see, I've added printing of the types of variables to make sure the problem is what I think it is, and the output of all those prints is #t. So:
In calling distance, x and y are both real.
In calling abs, x is a list.
So, the conclusion is that (- x y) returns a list, but why?
I double-checked with the documentation and it seems I'm using the subtraction operator correctly; I've typed (- 2 5) and then (real? (- 2 5)) into the same REPL I'm using to debug my program (Dr. Racket, to be specific), and I'm getting the expected results (-3 and #t, respectively).
Is there any wizard here that can tell me what kind of sorcery is this?
Thanks in advance!
How about this...
(define distance
(lambda (x y)
(print (real? x))
(print (real? y))
(abs (- x y))))
(define abs
(lambda (x) ;; instead of (lambda x ...), we are using (lambda (x) ...) form which is more strict in binding with formals
(print (list? x))
(if (< x 0) (- x) x)))
Read further about various lambda forms and their binding with formals.

Scheme program to get average not recognizing last number

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.

Convert lists into functions

I have a little noob question. I have to do a homework on genetic programming in scheme and the first step is to finish some given functions.
I got to a point where i have to execute a randomly generated function with all the possible parameters in a range (using map). The "function" is list like '(* (+ 1 x) (- x (* 2 3))).
How can i execute it with a given parameter? (for example x = 2). By the way, the generated function has a maximum of 1 parameter (it's x or none).
Thanks!
Here's my solution:
(define (execute expr)
(lambda (x)
(let recur ((expr expr))
(case expr
((x) x)
((+) +)
((-) -)
((*) *)
((/) /)
(else
(if (list? expr)
(apply (recur (car expr)) (map recur (cdr expr)))
expr))))))
Example usage:
> (define foo (execute '(* (+ 1 x) (- x (* 2 3)))))
> (foo 42)
=> 1548

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

Distributive Law Simplification

I'm trying to write a procedure that makes use of the distributive property of an algebraic expression to simplify it:
(dist '(+ x y (exp x) (* x 5) y (* y 6)))
=> (+ (* x (+ 1 5))
(* y (+ 1 1 6))
(exp x))
(dist '(+ (* x y) x y))
=> (+ (* x (+ y 1))
y)
; or
=> (+ (* y (+ x 1))
x)
As the second example shows, there can be more than one possible outcome, I don't need to enumerate them all, just a valid one. I'm wondering if someone could provide me with at least a qualitative description of how they would start attacking this problem? Thanks :)
Oleg Kiselyov's pmatch macro makes distributing a factor across terms pretty easy:
(define dist
(λ (expr)
(pmatch expr
[(* ,factor (+ . ,addends))
`(+ ,#(map (λ (addend)
(list factor addend))
addends))]
[else
expr])))
(dist '(* 5 (+ x y))) => (+ (5 x) (5 y))
The main trick is to match a pattern and extract elements from the expression from the corresponding slots in the pattern. This requires a cond and let with tricky expressions to cdr to the right place in the list and car out the right element. pmatch writes that cond and let for you.
Factoring out common terms is harder because you have to look at all the subexpressions to find the common factors and then pull them out:
(define factor-out-common-factors
(λ (expr)
(pmatch expr
[(+ . ,terms) (guard (for-all (λ (t) (eq? '* (car t)))
terms))
(let ([commons (common-factors terms)])
`(* ,#commons (+ ,#(remove-all commons (map cdr terms)))))]
[else
expr])))
(define common-factors
(λ (exprs)
(let ([exprs (map cdr exprs)]) ; remove * at start of each expr
(fold-right (λ (factor acc)
(if (for-all (λ (e) (member factor e))
exprs)
(cons factor acc)
acc))
'()
(uniq (apply append exprs))))))
(define uniq
(λ (ls)
(fold-right (λ (x acc)
(if (member x acc)
acc
(cons x acc)))
'()
ls)))
(factor-out-common-factors '(+ (* 2 x) (* 2 y)))
=> (* 2 (+ (x) (y)))
The output could be cleaned up some more, this doesn't cover factoring out a 1, and remove-all is missing, but I'll leave all that to you.
A very general approach:
(dist expr var-list)
=> expr factored using terms in var-list
dist would have to know about "distributable" functions like +,-,*,/,etc and how each of them behave. If, say, it only knew about the first four, then :
(dist expr var-list
(if (empty? var-list) expr
(let* ([new-expr (factor expr (first var-list))])
(return "(* var " (dist new-expr (rest var-list)))))
That "return "(* var " " is not correct syntax, but you probably already knew that. I'm not a racket or lisp expert by any means, but basically this comes down to string processing? In any case, factor needs to be fleshed out so that it removes a single var from * functions and all of the var from + functions (replacing them with 1). It also needs to be smart enough to only do it when there are at least two replacements (otherwise we haven't actually done anything).

Resources