Substring: Starting index out of range with big-bang - racket

"Pictured Programs" http://www.facom.ufu.br/~marcelo/PF/pictures_racket.pdf is the book I'm working out of and Ch.10. I'm trying to use what has been introduced in the book in a linear fashion. The program is suppose to cut the first character off of the string when a mouse moves or clicks which it does, but I can't find a way to stop it from throwing the out of range error.
I've tried several different approaches and spent hours on it unfortunately. This must be done without conditionals, loops, built-in functions not mentioned yet, & etc...
Any tips would be appreciated.
Here is the actual Exercise questions.
(require picturing-programs)
(define (add-str s)
(string-append s "b"))
(define (a-with-b s)
(text s 18 "green"))
(define (chop-first-on-mouse s mouse-x mouse-y me)
(substring s 1 (string-length s)))
(define (string-world s)
(big-bang s
(check-with string?)
(on-tick add-str 1/2)
(on-draw a-with-b 200 200)
(on-mouse chop-first-on-mouse)))
(string-world "a")

So in order to improve the program, there was one piece of code added to the function definition (chop-first-on-mouse ...), which was the built-in function (min). This was the only change that was needed to obtain the desired results.
This appears to give the desired output because the newly defined/refined call to "chop-first-on-mouse" now only deletes one char at a time and also does not throw an error(always stays within range of substring parameters).
While before the original call to "chop-first-on-mouse" would go out of range and it would also delete chars too quickly to analy 's/z' e.
(require picturing-programs)
(define (add-str s)
(string-append s "b"))
(define (a-with-b s)
(text s 18 "green"))
# Only change to program is the built-in function (min) in the substring call below
(define (chop-first-on-mouse s mouse-x mouse-y me)
(substring s (min 1 (string-length s))))
(define (string-world s)
(big-bang s
(check-with string?)
(on-tick add-str 1/2)
(on-draw a-with-b 200 200)
(on-mouse chop-first-on-mouse)))
(string-world "a" )

Related

Displaying x & y coordinate with mouse handler

"Pictured Programs" http://www.facom.ufu.br/~marcelo/PF/pictures_racket.pdf Ch.10 (final exercise 10.2.6) is the book I'm working out of.
I'm trying to use what has been introduced in the book in a linear fashion. The exercise wants an animation that displays the x & y coordinates on the window.
This must be done without conditionals, loops, built-in functions not mentioned, & etc...
I'm having trouble writing the mouse-handler handling the x-mouse & y-mouse in the same expression.
I can't think of a way to track them both (ie... I need a space between the two coordinates in the same mh without throwing an error.
(define (number->image s)
(text (string-append "(" (number->string s)")" "("(number->string s) ")" ) 18 "blue"))
(define (show-coord s)
(number->image s)))
(define (mh s mouse-x mouse-y me)
(string->number (string-append
(number->string mouse-x)
(number->string mouse-y))))
(define (string-world s)
(big-bang s
(check-with number?)
(on-draw show-coord 200 200)
(on-mouse mh)))
(string-world 0)
Instead of returning a number from the mouse handler, how about returning a list of coordinates? Then the list of coordinates can be converted to an appropriate string representation before calling text.
Since the world state is now a list instead of a number, the check-with predicate will need to be changed:
#lang racket
(require picturing-programs)
(define (coord->image s)
(text (string-append "("
(number->string (first s))
" "
(number->string (second s))
")")
18 "blue"))
(define (show-coord s)
(coord->image s))
(define (mh s mouse-x mouse-y me)
(list mouse-x mouse-y))
(define (string-world s)
(big-bang s
(check-with list?)
(on-draw show-coord 200 200)
(on-mouse mh)))
(string-world '(0 0))
Update
OP says that lists have not been introduced in the book yet. OK. We need some way to return the information that we want to display. Let's just return a string! Don't forget that the check-with predicate and the initial world state must match our new approach:
#lang racket
(require picturing-programs)
(define (coord->image s)
(text s 18 "blue"))
(define (show-coord s)
(coord->image s))
(define (mh s mouse-x mouse-y me)
(string-append "("
(number->string mouse-x)
" "
(number->string mouse-y)
")"))
(define (string-world s)
(big-bang s
(check-with string?)
(on-draw show-coord 200 200)
(on-mouse mh)))
(string-world "")

Racket: Why wont this compile?

I'm attempting to program a simple function that adds integers to a list descending from a range of "high" and "low", incremented by "step"
For example,
if the input is (3 12 3), the expected output is '(12 9 6 3)
Below is the following code:
(define (downSeries step high low [(define ret '())])
(if (< high low)
ret
(cons ret (- high step))
(downSeries (step (- high step) low))))
I'm pretty new to racket, but I'm really not sure why this isn't compiling. Any tips? Thank you.
Since only racket is tagged and no special languages are describes it is expeted the first line in the definition window is #lang racket. Answer will be different for student languages.
1 The last argument is nested in two parentheses and is illegal syntax. Default arguments only have one set:
(define (test mandatory (optional '()))
(list mandatory optional))
(test 1) ; ==> (1 ())
(test 1 2) ; ==> (1 2)
2 You have 4 operands in your if form. It takes maximum 3!
(if prediate-expression
then-expression
else-expression)
Looking at the code you should have the cons expression in the position of ret argument. Having it before the recursion makes it dead code. ret will always be (). Eg this loks similar to a typical fold implementation:
(define (fold-1 combine init lst)
(if (null? lst)
init ; fully grown init returned
(fold-1 combine
(combine (car lst) init) ; init grows
(cdr lst))))

racket - define-struct and abstract list function

I am trying to create a function games-won that consumes a list of Games, results, and a string, name, and produces the number of games in results that name won.
For example:
(define-struct game (winner loser high low))
(check-expect (games-won (list (make-game "Lori" "Troy" 52 34)
(make-game "Mary" "Lori" 30 20)) "Lori") 1)
Below is what I have so far:
(define (won? game name)
(equal? (game-winner game) name))
(define (wonlst results)
(filter won? results))
(define (lst-length lst)
(cond
[(empty? lst) 0]
[(cons? lst) (+ 1 (length (rest lst)))]))
(define (games-won results)
(cond
[(cons? (wonlst results)) (lst-length (wonlst results))]
[else 0]))
Can anyone help correct the errors in my code and maybe tell me how to use local and put the functions all together?
Here are the fixes:
As the test suggests, games-won should accept two arguments: a results list and a name. So we add a parameter - name - to games-won.
You don't need a custom lst-length function, you can just use length. Also, games-won doesn't need to worry about returning 0 in the else case. The base case is taken care of by the list-abstractions.
Note that won? takes in two inputs, but the predicate function in a filter only accepts one input. So we remove name from won?. Once we put won? in a local, it can just use name from the surrounding function's context.
We put a local in games-won and put the two helpers - won? and won-lst - in the local.
You should use string=? instead of equal?for since we know that name and winner field of game is always a String.
(define-struct game (winner loser high low))
; games-won : [List-of Game] String -> Number
(define (games-won results name)
(local (; won? : Game -> Boolean
(define (won? game)
(string=? (game-winner game) name))
; wonlst : [List-of Game] -> [List-of Game]
(define (wonlst results)
(filter won? results)))
(length (wonlst results))))
(define my-games1 (list (make-game "Lori" "Troy" 52 34)
(make-game "Mary" "Lori" 30 20)))
(check-expect (games-won my-games1 "Lori") 1)
We can just put everything in one function along with a lambda like the following:
(define (games-won results name)
(length (filter (λ (game) (string=? (game-winner game) name)) results)))
How to use local
A local expression has the following shape:
(local [definition ...] body-expression)
Within the square brackets, you can put as many definitions (i.e. defines, define-structs) as you want, and in the body of the local — body-expression — you can put any expression that may or may not use the definitions within the square brackets. The definitions are only available in the body.
From HtDP, here's how we compute with locals:
We rename the locally defined constants and functions to use names that aren’t used elsewhere in the program.
We lift the definitions in the local expression to the top level and evaluate the body of the local expression next.

Procedure works as intended but error message still shows up

I've been attempting to learn programming with the book "Structures and Interpretation of Computer Programs. To do the exercises I've been using DrRacket (I couldn't find a scheme interpreter for Windows 7, and DrRacket seems pretty good), and haven't had any problems so far. But while doing exercise 1.22 I've ran into an issue. I've wrote a procedure that gives a given number (n) of prime numbers larger than a:
(define (search-for-primes a n)
(define (sfp-iter a n counter)
(cond ((and (prime? a) (= counter n))
((newline) (display "end")))
((prime? a)
((newline)
(display a)
(sfp-iter (+ a 1) n (+ counter 1))))
(else (sfp-iter (+ a 1) n counter))))
(sfp-iter a n 0))
The procedure works as intended, displaying all that it should, but after displaying end it shows the following error message:
application: not a procedure;
expected a procedure that can be applied to arguments
given: #
arguments...:
#
And highlights the following line of code:
((newline) (display "end"))
What is the problem?
(I apologize for any mistakes in spelling and so, English isn't my native language, I also apologize for any error in formatting or tagging, I'm new here)
You have a couple of parenthesis problems, this fixes it:
(define (search-for-primes a n)
(define (sfp-iter a n counter)
(cond ((and (prime? a) (= counter n))
(newline) (display "end"))
((prime? a)
(newline)
(display a)
(sfp-iter (+ a 1) n (+ counter 1)))
(else (sfp-iter (+ a 1) n counter))))
(sfp-iter a n 0))
In the first and second conditions of the cond, you were incorrectly surrounding the code with (). That's unnecessary, in a cond clause all the expressions that come after the condition are implicitly surrounded by a (begin ...) form, so there's no need to group them together.

LISP functions that perform both symbolic and numeric operations on expressions using +, -, *, and /

I'm currently working on a LISP exercise for a small project and need severe help. This may be more or less of a beginner's question but I'm absolutely lost on writing a certain function that takes in two unevaluated functions and spits out the result dependent on if the variables were given an assignment or not.
An example would be
(setq p1 '(+ x (* x (- y (/ z 2)))))
Where
(evalexp p1 '( (x 2) (z 8) ))
returns (+ 2 (* 2 (- y 4)))
My goal is to write the evalexp function but I can't even think of where to start.
So far I have
(defun evalexp (e b) )
.. not very much. If anyone could please help or lead me in a good direction I'd be more than appreciative.
Here's a full solution. It's pretty straightforward, so I'll leave out a full explanation. Ask me in the comments if there's anything you can't figure out yourself.
(Using eval to do the actual evaluation might not be what you want in your exercise/project. Look up "meta-circular interpreter" for another way.)
(defun apply-env (exp env)
(reduce (lambda (exp bdg) (subst (cadr bdg) (car bdg) exp))
env :initial-value exp))
(defun try-eval (exp)
(if (atom exp)
exp
(let ((exp (mapcar #'try-eval exp)))
(if (every #'numberp (cdr exp))
(eval exp)
exp))))
(defun evalexp (exp env)
(try-eval (apply-env exp env)))
Here's a hint, this is how you might do it (in pseudocode):
function replace(vars, list):
for each element of list:
if it's an atom:
if there's an association in vars:
replace atom with value in vars
else:
leave atom alone
else:
recursively apply replace to the sublist
There will certainly be some details to work out as you convert this to Lisp code.