Make a function that makes line segment coordinates centered at point (x y) with slope m - scheme

I have a plotting library I'm building source, and want to plot slope lines. I have a function (draw-seg-list device color lst) with the lst arg being a list containing lists with the start and stop cords of a line (x0 y0 x1 y1). I want to make a function (make-slope-seg x y m) that then returns the point list for a line segment centered at (x, y) with slope m.
Example: (make-slope-seg 0 0 0) -> (-.05 0 .05 0) and (make-slope-seg .1 .1 1) -> (.05 .05 .15 .15)
The non-working function I have is:
(define (make-slope-cords x y m)
(list (- x .05)
(* y m -1)
(+ x .05)
(* y m)))
Which returns the incorrect lines. If I use :
;makes graphics window
(define window (make-graphics-device 'win32))
;plots blue line for function y = x^2 with black axis
(make-plot window 'simple-plot (list "white" "black" "blue" (list (range -1 1 .01) square)))
;makes list of lists containing the slope and x y cords that the slope lines
;are supposed to be centered at
(define cords (map (lambda (s x y)
(list s x y))
(map (lambda (x) (* 2 x)) (range -1 1 .1))
(range -1 1 .1)
(map square (range -1 1 .1))))
;plots the line segments generated by mapping make-slope-cords to the coordinate list
(draw-seg-list window "red"
(map (lambda (lst)
(make-slope-cords (car lst) (cadr lst) (caddr lst)))
cords))
It outputs the following:
But I want it to output red lines of width .1 (1 square on the grid in the image) with slope being the slope of the blue line(lambda (x) (square x)) at each point spaced by .1 along the x axis.
NOTE: assume that draw-seg-list works. I just need assistance in making the function make-slope-cords produce a the correct list of cordinates

Well experimenting around I was able to determine the answer.
(define (make-sloped-seg x y m)
(define b (- y (* m x)))
(list (- x .03)
(+ (* m (- x .03)) b)
(+ x .03)
(+ (* m (+ x .03)) b)))
It determines the y-intercept (b) at the beginning of the calculation, and then generates the points using the correct intercept
example:
;makes graphics window
(define window (make-graphics-device 'win32))
;plots blue line for function y = x^2 with black axis
(make-plot window 'simple-plot (list "white" "black" "blue" (list (range -1 1 .01) square)))
;makes list of lists containing the slope and x y cords that the slope lines
;are supposed to be centered at
(define cords (map (lambda (s x y)
(list s x y))
(map (lambda (x) (* 2 x)) (range -1 1 .1))
(range -1 1 .1)
(map square (range -1 1 .1))))
;plots the line segments generated by mapping make-slope-cords to the coordinate list
(draw-seg-list window "red"
(map (lambda (lst)
(make-slope-cords (car lst) (cadr lst) (caddr lst)))
cords))
outputs the following:

Related

output of map function?

Hi I am trying to understand the output of the following code
(define p (lambda (x) (lambda (y) (x (x y)))))
(define q (lambda (x) (* x x)))
when I use
(map (p q) (list 1 2 3))
the result is
(1 16 81)
shouldn't the answer be
(1 4 9) ?
You're mapping (p q) over the list, so start with figuring out what that is.
Using the subsitution method, you get
(p q)
==> ((lambda (x) (lambda (y) (x (x y)))) q)
==> (lambda (y) (q (q y)))
==> (lambda (y) (q ((lambda (x) (* x x)) y)))
==> (lambda (y) (q (* y y)))
==> (lambda (y) ((lambda (x) (* x x)) (* y y)))
==> (lambda (y) (* (* y y) (* y y)))
so (p q) is a function that takes a number and squares its square.
Two functions are provided:
(define p (lambda (x) (lambda (y) (x (x y)))))
(define q (lambda (x) (* x x)))
q is a function which takes a number and squares it.
p is a function which takes a function x, and returns another function where x is applied twice to y. Please note that in p, that x is in the function location of the forms, and has been highlighted in the listing to show this.
The use of x in both expressions is unfortunately confusing. You can replace any variable in a lambda expression with any other variable, for example function - this is called alpha-conversion - https://en.wikipedia.org/wiki/Lambda_calculus - and you can change the name of any named function to something more sensible. So, I've renamed q to square, the squaring function, and I've renamed p to do-twice.
(define do-twice (lambda (function) (lambda (y) (function (function y)))))
(define square (lambda (x) (* x x)))
It then becomes obvious what is happening when you evaluate do-twice square.
Francis King's answer is very clear,
this is just an extended footnote inspired by it.
Replacing identifiers with mnemonic ones (rewriting q as square) can make it easier to understand code [1]
Procedures as [first-class] values in Scheme [2] are often introduced with examples using lambda:
> (define twelve 12)
> (define square (lambda (x) (* x x)))
> (square twelve)
144
>
just as the characters 12 in the code above are the representation of a Number,
the characters (lambda (x) (* x x)) are the representation of a Procedure:
(number? 12) => #t, (procedure? (lambda (x) (* x x))) => #t
Two further code rewritings may be helpful:
using the "short-form" define for procedures, and annotating the definition
with a type signature (argument and result types):
> (define (square x) (* x x)) ;; Number -> Number
> (square 3)
9
> (define (do-twice f x) ;; (X -> X) X -> X
(f (f x)))
> (do-twice square 3)
81
> (map (lambda (x) (do-twice square x))
'(1 2 3))
(1 16 81)
>
Note that this do-twice does not yet correspond to the p of the question: making
this do-twice the first argument of map would require:
(map do-twice (make-list 3 square) '(1 2 3))
Mapping one list needs a function of one argument, so something has to produce the do-twice of
(define (do-twice x) (f (f x))) as its value:
> (define (do-twice-with f) ;; (X -> X) -> (X -> X)
(define (do-twice x) ;; X -> X
(f (f x)))
do-twice)
> ((do-twice-with square) 3)
81
> (map (do-twice-with square)
'(1 2 3))
(1 16 81)
>
So do-twice-with is the function p in the question.
do-twice-with requires a function argument (X -> X), but X can be any type, so:
> (define (repeat s) ;; String -> String
(string-append s " " s))
> ((do-twice-with repeat) "buffalo")
"buffalo buffalo buffalo buffalo"
and do-twice-with itself has type (X' -> X') (with X' standing for (X -> X)), so can be
applied to itself:
> (((do-twice-with do-twice-with) square) 3)
43046721
> (((do-twice-with do-twice-with) repeat) "buffalo") [3]
"buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo"
((((do-twice-with do-twice-with) do-twice-with) square) 3) is left as an
exercise for the reader...
[1] "Naming is perhaps the most powerful abstracting notion we have" [Guy L Steele]
[2] https://walker.cs.grinnell.edu/courses/151.sp04/readings/procedures-as-values.xhtml
[3] https://en.wikipedia.org/wiki/Buffalo_buffalo_Buffalo_buffalo_buffalo_buffalo_Buffalo_buffalo

.Dynamically changing the clock tick rate in big-bang

The on-tick clause includes an option to change the clock tick rate. I have included my code to dynamically change the value depending on the world state value. The code is not working and I can't understand why. Another issue - how are world programs debugged? The "step" option doesn't work.
; physical constants
(define HEIGHT 300)
(define WIDTH 100)
(define YDELTA 3)
; graphical constants
(define BACKG (empty-scene WIDTH HEIGHT))
(define ROCKET (rectangle 5 30 "solid" "red"))
(define ROCKET-CENTER (/ (image-height ROCKET) 2))
(define ROCKET-XPOS 10)
; LRCD -> LRCD
(define (main1 s)
(big-bang s
[to-draw show]
[on-key launch]
[on-tick fly (clock-rate s)]))
; LRCD -> Image
; renders the state as a resting or flying rocket
(define (show x)
(cond
[(string? x) (rocket-ht HEIGHT)]
[(<= -3 x -1)
(place-image (text (number->string x) 20 "red")
ROCKET-XPOS (* 3/4 WIDTH)
(rocket-ht HEIGHT))]
[(>= x 0)
(rocket-ht x)]))
; LRCD -> image
; positions the rocket at correct height
(define (rocket-ht ht)
(place-image ROCKET ROCKET-XPOS (- ht ROCKET-CENTER) BACKG))
; LRCD KeyEvent -> LRCD
; starts the count-down when space bar is pressed,
; if the rocket is still resting
(define (launch x ke)
(cond
[(string? x) (if (string=? ke " ") -3 x)]
[else x]))
; LRCD -> LRCD
; raises the rocket by YDELTA,
; if it is moving already
(define (fly x)
(cond
[(string? x) x]
[(<= -3 x -1) (if (= x -1) HEIGHT (add1 x))]
[else (- x YDELTA)]))
(define (clock-rate s)
(cond
[(number? s) (if (< s 0) 1 1/28)]
[else 1/28]))

Reaching a specific item in define-struct

I'm really stuck about somethings and I will try to tell my questions correctly, I hope you can understand. It can be a little bit long so firstly thank you to spends your time to read this.
I'm trying to create a game whose name is "Same" in Racket 5.0.2 version.
Here is explanation of the game: http://download.racket-lang.org/docs/5.0.2/html/games/same.html?q=games
I created a table with disks and draw it:
a: width
b: height
r: radius
(define (color x) ///for random colors
(cond [(< (random x) 100) 'blue]
[(< (random x) 200) 'purple]
[(< (random x) 300) 'yellow]
[(< (random x) 400) 'red]
[else 'green]))
(define-struct top (coord color))
(define (row x y)
(if (> x (- a r)) empty
(cons (make-top (make-posn x y)(color 500)) (row (+ x (* 2 r)) y))))
(define (draw-row L)
(if (empty? L) #f
(and
(draw-solid-disk (top-coord (first L)) r (top-color (first L)))
(draw-row (rest L)))))
(define (board x y)
(if (> y (- b r)) empty
(cons (row x y) (board x (+ y (* 2 r))))))
(for-each draw-row (board 20 20))
So I've 200 disks with random colors...(There are 20 disks in every row)
Here my biggest problems are:
1) To delete the disk, player will input particular line and column. Will I have conditions for every choices?
if line=1 and column=1, delete this disk and its same colored adjacent disks
if line=5 and column=7, delete that disk and its same colored adjacent disks
I hope you have some easier, alternative ways because it looks extremely challenging.
2) How can I compare disk's colors in many lists? It's hard to tell my problem but I'll try.
(define table (board 20 20))
(define row1 (list-ref table 0))
(list-ref row1 0)
It will return:
(make-top (make-posn 20 20) 'yellow)
How can I reach 'yellow in here? And if I reach, how can I compare it with other colors?
Any idea would be great! I've been thinking about these questions for 2 days and still I couldn't do anything.
I shouldn't use mutable structures
Structs come with built in accessors:
> (define my-top (make-top (make-posn 20 20) 'yellow))
> (top-color my-top)
'yellow
> (top-coord my-top)
(make-posn 20 20)
> (top? my-top)
true

Drawing table/board in Racket

I'm trying to create a game whose name is "Same" in Racket 5.0.2 version.
Here is explanation of the game:
http://download.racket-lang.org/docs/5.0.2/html/games/same.html?q=games
I created a row and draw it:
a: width
b: height
r: radius
(define (color x) ///for random colors
(cond [(< (random x) 100) 'blue]
[(< (random x) 200) 'purple]
[(< (random x) 300) 'yellow]
[(< (random x) 400) 'red]
[else 'green]))
(define-struct top (coord color))
(define (row x y)
(if (> x (- a r)) empty
(cons (make-top (make-posn x y)(color 500)) (row (+ x (* 2 r)) y))))
(define (draw-row L)
(if (empty? L) #f
(and
(draw-solid-disk (top-coord (first L)) r (top-color (first L)))
(draw-row (rest L)))))
So I've got a top row included 20 disks with random colors. But I need 200 disks in 20 rows and 10 columns. So I created a board like this:
(define (board x y)
(if (> y (- b r)) empty
(cons (row x y) (board x (+ y (* 2 r))))))
But I couldn't draw it. I tried to create a function as "draw-row" but I got error.
So my question is: How can I draw this board?
You can draw a row, and a board is just a list of rows, so I would expect
(define (draw-board b)
(for-each draw-row b))
to Just Work.
Based on your comment, an example I would expect to work:
(draw-board (board 10 10))
and it does for me, at least.

Why can't I make two make function calls in function body?

So I'm going through the first chapter of How To Design Programs 2nd Edition. I believe I made pretty good progress. But there's a "suggestion" to add another graphic to the grid. Every time I try I get an error. At this point, I'm stuck. Below is the code and the error.
Note: the ROCKET image is in the Chapter 1. I just copy and pasted it into the IDE.
Note: The "suggestion" is: How would change the program so that the rocket lands on a flat rock bed that is 10 pixels higher than the bottom of the scene? Don’t forget to change the scenery, too.
HTDP Chapter 1
Here's code that works.
(define BOARDWIDTH 200)
(define BOARDHEIGHT 200)
(define STARTPOSITION 50)
(define BOARDBKGR "blue")
(define GAMEBOARD (empty-scene BOARDWIDTH BOARDHEIGHT BOARDBKGR))
(define ROCKET .)
(define UFO (overlay (circle 10 "solid" "red")
(rectangle 40 4 "solid" "green")))
(define FLATBED (rectangle 60 10 "outline" "black"))
(define (SPACESHIP option)
(cond
[(= option 1) ROCKET]
[(= option 2) UFO]))
(define SHOWNSHIP (SPACESHIP 1))
(define V 20) ;Velocity
(define A 1) ;Acceleration
(define (distance t) ;t = Time
(- (* V t) (* 1/2 A (sqr t))))
(define SPACESHIP-BOTTOM (- BOARDHEIGHT (/ (image-height SHOWNSHIP) 2)))
(define (render-shownship x y)
(place-image SHOWNSHIP x y GAMEBOARD))
(define (create-rocket-scene.v7 t)
(cond
[(<= (distance t) SPACESHIP-BOTTOM)
(render-shownship STARTPOSITION (distance t))]
[(> (distance t) SPACESHIP-BOTTOM)
(render-shownship STARTPOSITION SPACESHIP-BOTTOM)]))
Here's the code that doesn't work:
(define BOARDWIDTH 200)
(define BOARDHEIGHT 200)
(define STARTPOSITION 50)
(define BOARDBKGR "blue")
(define GAMEBOARD (empty-scene BOARDWIDTH BOARDHEIGHT BOARDBKGR))
(define ROCKET .)
(define UFO (overlay (circle 10 "solid" "red")
(rectangle 40 4 "solid" "green")))
(define FLATBED (rectangle 60 10 "outline" "black"))
(define (SPACESHIP option)
(cond
[(= option 1) ROCKET]
[(= option 2) UFO]))
(define SHOWNSHIP (SPACESHIP 1))
(define V 20) ;Velocity
(define A 1) ;Acceleration
(define (distance t) ;t = Time
(- (* V t) (* 1/2 A (sqr t))))
(define SPACESHIP-BOTTOM (- BOARDHEIGHT (/ (image-height SHOWNSHIP) 2)))
(define (render-shownship x y)
(place-image SHOWNSHIP x y GAMEBOARD)
(place-image FLATBED STARTPOSITION 195 GAMEBOARD)) ;offender
(define (create-rocket-scene.v7 t)
(cond
[(<= (distance t) SPACESHIP-BOTTOM)
(render-shownship STARTPOSITION (distance t))]
[(> (distance t) SPACESHIP-BOTTOM)
(render-shownship STARTPOSITION SPACESHIP-BOTTOM)]))
And the error I get is:
define: expected only one expression for the function body, but found
1 extra part
place-image always takes 4 arguments - the image to be placed, x and y coordinates, and the scene (background) on which to place the image. The problem in your code is that the expression (place-image FLATBED STARTPOSITION 195) is providing only 3 inputs to place-image.
So, back up a little and consider: what does the first expression produce? (place-image SHOWNSHIP x y GAMEBOARD) produces a game board scene with a ship on it, correct? Now on top of that scene you further want to place the FLATBED. So instead of sequencing the place-image function calls, instead consider composing them - i.e. what do you think the missing piece is in (place-image FLATBED STARTPOSITION 195 ____)? upon what scene do you want to place the FLATBED? (Hint: we just answered that above). What expression produces that scene? (hint: you already have that expression).
If you understand the idea, you see that to place multiple images on a scene, you compose or nest the function calls (instead of sequencing them as you are attempting):
(place-image img1 x1 y1 (place-image img2 x2 y2 ...))

Resources