Category Archives: SICP

SICP – cap. 2 – painters – 63 – esercizi

Continuo da qui, copio qui.

Exercise 2.49: Use segments->painter to define the following primitive painters:

  • The painter that draws the outline of the designated frame.
  • The painter that draws an “X” by connecting opposite corners of the frame.
  • The painter that draws a diamond shape by connecting the midpoints of the sides of the frame.
  • The wave painter.

Sempre in stretto collegamento con i post precedenti.
Quando il gioco si fa duro mando il batlambda-segnale e Bill the Lizard arriva 😊

[W]e can use the PLT Scheme SICP Picture Language package to run the exercises. You can load the picture package by putting the following (require...) expression at the beginning of your Scheme Racket file.

(require (planet "sicp.ss" ("soegaard" "sicp.plt" 2 1)))

Since segments->painter takes a list of segments as its input parameter, each solution is just a matter of figuring out the coordinates of the endpoints of each required segment. Recall that the (0.0, 0.0) coordinate is the bottom left corner in the frame, not the top left corner as it is in many GUI environments. For each solution, we can define the list of segments first, then define a painter.

The painter that draws the outline of the designated frame.

Note that I used 0.99 instead of 1.0 for the edges of the frame. This is because the top and right edges won’t be displayed if you use 1.0.

The painter that draws an “X” by connecting opposite corners of the frame.

The painter that draws a diamond shape by connecting the midpoints of the sides

The wave painter in the last part of the exercise is the image shown in Figure 2.10 [qui] of the text. It consists of 17 separate segments.

Il codice è troppo lungo per visualizzarlo in DrRacket, è questo:

(define wave-segments
 (list
  (make-segment
   (make-vect 0.006 0.840)
   (make-vect 0.155 0.591))
  (make-segment
   (make-vect 0.006 0.635)
   (make-vect 0.155 0.392))
  (make-segment
   (make-vect 0.304 0.646)
   (make-vect 0.155 0.591))
  (make-segment
   (make-vect 0.298 0.591)
   (make-vect 0.155 0.392))
  (make-segment
   (make-vect 0.304 0.646)
   (make-vect 0.403 0.646))
  (make-segment
   (make-vect 0.298 0.591)
   (make-vect 0.354 0.492))
  (make-segment
   (make-vect 0.403 0.646)
   (make-vect 0.348 0.845))
  (make-segment
   (make-vect 0.354 0.492)
   (make-vect 0.249 0.000))
  (make-segment
   (make-vect 0.403 0.000)
   (make-vect 0.502 0.293))
  (make-segment
   (make-vect 0.502 0.293)
   (make-vect 0.602 0.000))
  (make-segment
   (make-vect 0.348 0.845)
   (make-vect 0.403 0.999))
  (make-segment
   (make-vect 0.602 0.999)
   (make-vect 0.652 0.845))
  (make-segment
   (make-vect 0.652 0.845)
   (make-vect 0.602 0.646))
  (make-segment
   (make-vect 0.602 0.646)
   (make-vect 0.751 0.646))
  (make-segment
   (make-vect 0.751 0.646)
   (make-vect 0.999 0.343))
  (make-segment
   (make-vect 0.751 0.000)
   (make-vect 0.597 0.442))
  (make-segment
   (make-vect 0.597 0.442)
   (make-vect 0.999 0.144))))

(define wave (segments->painter wave-segments))

Già si sa che Bill e DrRacket rockzs! 👽

sicp-ex presenta diverse soluzioni, il bello dei blog comunitari 😊
Bella la pagina di Drewiki 😊

:mrgreen:

SICP – cap. 2 – painters – 62 – esercizi

Continuo da qui, copio qui.

Exercise 2.48: A directed line segment in the plane can be represented as a pair of vectors—the vector running from the origin to the start-point of the segment, and the vector running from the origin to the end-point of the segment. Use your vector representation from Exercise 2.46 [qui] to define a representation for segments with a constructor make-segment and selectors start-segment and end-segment.

Mi sembrava troppo semplice ma (sbirciando Bill the Lizard) è davvero così 😁

(define (make-segment v1 v2)
   (cons v1 v2))

(define (start-segment segment)
   (car segment))

(define (end-segment segment)
   (cdr segment))

sicp-ex, precede la stessa soluzione con heh, 👽
Stessa soluzione per Drewiki.

:mrgreen:

SICP – cap. 2 – painters – 61

 

Continuo da qui, copio qui.

A painter is represented as a procedure that, given a frame as argument, draws a particular image shifted and scaled to fit the frame. That is to say, if p is a painter and f is a frame, then we produce p’s image in f by calling p with f as argument.

The details of how primitive painters are implemented depend on the particular characteristics of the graphics system and the type of image to be drawn. For instance, suppose we have a procedure draw-line that draws a line on the screen between two specified points. Then we can create painters for line drawings, such as the wave painter in Figure 2.10, from lists of line segments as follows ( Segments->painter uses the representation for line segments described in Exercise 2.48 below [prossimamente]. It also uses the for-each procedure described in Exercise 2.23 [qui].):

(define (segments->painter segment-list)
  (lambda (frame)
    (for-each
     (lambda (segment)
       (draw-line
        ((frame-coord-map frame) 
         (start-segment segment))
        ((frame-coord-map frame) 
         (end-segment segment))))
     segment-list)))

Figure 2.10: Images produced by the wave painter, with respect to four different frames. The frames, shown with dotted lines, are not part of the images.

The segments are given using coordinates with respect to the unit square. For each segment in the list, the painter transforms the segment endpoints with the frame coordinate map and draws a line between the transformed points.

Representing painters as procedures erects a powerful abstraction barrier in the picture language. We can create and intermix all sorts of primitive painters, based on a variety of graphics capabilities. The details of their implementation do not matter. Any procedure can serve as a painter, provided that it takes a frame as argument and draws something scaled to fit the frame.

:mrgreen:

SICP – cap. 2 – frames – 60 – esercizi

Continuo da qui, copio qui.

Exercise 2.47: Here are two possible constructors for frames:

(define (make-frame origin edge1 edge2)
  (list origin edge1 edge2))

(define (make-frame origin edge1 edge2)
  (cons origin (cons edge1 edge2)))

For each constructor supply the appropriate selectors to produce an implementation for frames.

Uhmmm… mi sa che cito Bill the Lizard.

Like any selector implementation, the task here is simply to extract each piece from the assembled object. We’ll follow the naming convention from the previous exercise and call our selectors origin-frame, edge1-frame, and edge2-frame. Let’s start with the version that uses list.

; 2.47a
(define (make-frame origin edge1 edge2)
   (list origin edge1 edge2))

(define (origin-frame frame)
   (car frame))

(define (edge1-frame frame)
   (car (cdr frame)))

(define (edge2-frame frame)
   (car (cdr (cdr frame))))

Queste procedure le ho raccoltre nel file 2-47a.rkt.
Mi serve poi il codice definito nel post precedente, vect.rkt.

The selectors simply use the right combinations of car and cdr to extract the appropriate elements from the list. We can test it with some of the same values used in the previous exercise, but we’ll need to add an origin vector.

Because the internal representation of a frame is different in the second implementation of make-frame, one of the selectors will have to change for the second part of the exercise. The original origin-frame and edge1-frame implementations will still work, but the edge2-frame procedure causes an error if you try to use it.

; 2.47b
(define (make-frame origin edge1 edge2)
   (cons origin (cons edge1 edge2)))

(define (edge2-frame frame)
   (cdr (cdr frame)))

Codice raccolto nel file 2-47b.rkt.

Run exactly the same test from above to verify that you get the same results (except for the internal structure of the frame in the second step).

Soluzione molto simile per sicp-ex, senza spiegazione.
Simile, e commentata, la soluzione di Drewiki.

:mrgreen:

SICP – cap. 2 – frames – 59 – esercizi

Continuo da qui, copio qui.

Exercise 2.46: A two-dimensional vector v running from the origin to a point can be represented as a pair consisting of an x-coordinate and a y-coordinate. Implement a data abstraction for vectors by giving a constructor make-vect and corresponding selectors xcor-vect and ycor-vect. In terms of your selectors and constructor, implement procedures add-vect, sub-vect, and scale-vect that perform the operations vector addition, vector subtraction, and multiplying a vector by a scalar:

Cose già viste, basta usare cons, car e cdr:

(define (make-vect x y)
  (cons x y))
  
(define (xcor-vect v)
  (car v))
  
(define (ycor-vect v)
  (cdr v))

E quindi somma, sottrazione e ingrandimento:

(define (add-vect u v)
  (make-vect
    (+ (xcor-vect u) (xcor-vect v))
    (+ (ycor-vect u) (ycor-vect v))))

(define (sub-vect u v)
  (make-vect
    (- (xcor-vect u) (xcor-vect v))
    (- (ycor-vect u) (ycor-vect v))))

(define (scale-vect s v)
  (make-vect
    (* s (xcor-vect v))
    (* s (ycor-vect v))))

Raccolgo tutto nel file vect.rkt

Elementare vero? Vedo i soliti nerds: Bill the Lizard, sicp-ex che implementa condizioni di test e Drewiki.

:mrgreen:

SICP – cap. 2 – frames – 58

Continuo da qui, copio qui.

Frames
Before we can show how to implement painters and their means of combination, we must first consider frames. A frame can be described by three vectors—an origin vector and two edge vectors. The origin vector specifies the offset of the frame’s origin from some absolute origin in the plane, and the edge vectors specify the offsets of the frame’s corners from its origin. If the edges are perpendicular, the frame will be rectangular. Otherwise the frame will be a more general parallelogram.

Figure 2.15 shows a frame and its associated vectors. In accordance with data abstraction, we need not be specific yet about how frames are represented, other than to say that there is a constructor make-frame, which takes three vectors and produces a frame, and three corresponding selectors origin-frame, edge1-frame, and edge2-frame (see Exercise 2.47 [prossimamente]).

Figure 2.15: A frame is described by three vectors — an origin and two edges.

We will use coordinates in the unit square (0 ≤ x , y ≤ 1) to specify images. With each frame, we associate a frame coordinate map, which will be used to shift and scale images to fit the frame. The map transforms the unit square into the frame by mapping the vector v = (x , y) to the vector sum

For example, (0, 0) is mapped to the origin of the frame, (1, 1) to the vertex diagonally opposite the origin, and (0.5, 0.5) to the center of the frame. We can create a frame’s coordinate map with the following procedure [Note 1]:

(define (frame-coord-map frame)
  (lambda (v)
    (add-vect
     (origin-frame frame)
     (add-vect 
      (scale-vect (xcor-vect v)
                  (edge1-frame frame))
      (scale-vect (ycor-vect v)
                  (edge2-frame frame))))))

Observe that applying frame-coord-map to a frame returns a procedure that, given a vector, returns a vector. If the argument vector is in the unit square, the result vector will be in the frame. For example,

((frame-coord-map a-frame) (make-vect 0 0))

returns the same vector as

(origin-frame a-frame)


Note 1: frame-coord-map uses the vector operations described in Exercise 2.46 below [prossimamente], which we assume have been implemented using some representation for vectors. Because of data abstraction, it doesn’t matter what this vector representation is, so long as the vector operations behave correctly.

:mrgreen:

SICP – cap. 2 – operazioni di ordine superiore – 57 – esercizi

Continuo da qui, copio qui.

Exercise 2.45: right-split and up-split can be expressed as instances of a general splitting operation. Define a procedure split with the property that evaluating

(define right-split (split beside below))
(define up-split (split below beside))

produces procedures right-split and up-split with the same behaviors as the ones already defined.

Sempre da vedere in stretta connessione con i posts precedenti. E come per quelli seguo Bill the Lizard 👽

We already noted the similarity between the two procedures right-split and up-split when we solved exercise 2.44 above [qui]. The only real difference between them is in which direction they split the painter first. Given the amount of duplication between the two, we can use either one of these procedures as a template for split.

(define (split dir1 dir2)
   (lambda (painter n)
     (if (= n 0)
         painter
         (let ((smaller ((split dir1 dir2) painter (- n 1))))
           (dir1 painter (dir2 smaller smaller))))))

The biggest change is that split uses a lambda to return the procedure that it creates. Once you’re done substituting the new definitions for right-split and up-split, you can run the square-limit procedure again to verify that the output hasn’t changed.

Molto più sintetico il post di sicp-ex. Meglio la soluzione di Drewiki 😁

:mrgreen:

SICP – cap. 2 – operazioni di ordine superiore – 56

Continuo da qui, copio qui.

In addition to abstracting patterns of combining painters, we can work at a higher level, abstracting patterns of combining painter operations. That is, we can view the painter operations as elements to manipulate and can write means of combination for these elements—procedures that take painter operations as arguments and create new painter operations.

For example, flipped-pairs and square-limit each arrange four copies of a painter’s image in a square pattern; they differ only in how they orient the copies. One way to abstract this pattern of painter combination is with the following procedure, which takes four one-argument painter operations and produces a painter operation that transforms a given painter with those four operations and arranges the results in a square. tl, tr, bl, and br are the transformations to apply to the top left copy, the top right copy, the bottom left copy, and the bottom right copy, respectively.

(define (square-of-four tl tr bl br)
  (lambda (painter)
    (let ((top (beside (tl painter) 
                       (tr painter)))
          (bottom (beside (bl painter) 
                          (br painter))))
      (below bottom top))))

Then flipped-pairs can be defined in terms of square-of-four as follows [vedi nota 1]:

(define (flipped-pairs painter)
  (let ((combine4 
         (square-of-four identity 
                         flip-vert
                         identity 
                         flip-vert)))
    (combine4 painter)))

and square-limit can be expressed as [vedi nota 2]

(define (square-limit painter n)
  (let ((combine4 
         (square-of-four flip-horiz 
                         identity
                         rotate180 
                         flip-vert)))
    (combine4 (corner-split painter n))))

Note:
1. Equivalently, we could write

(define flipped-pairs
  (square-of-four 
   identity flip-vert identity flip-vert))

2. rotate180 rotates a painter by 180 degrees (see Exercise 2.50 [prossimamente]). Instead of rotate180 we could say (compose flip-vert flip-horiz), using the compose procedure from Exercise 1.42 [qui].

:mrgreen:

SICP – cap. 2 – Sequenze come interfacce convenzionali – 55 – esercizi

Continuo da qui, copio qui.

Exercise 2.44: Define the procedure up-split used by corner-split. It is similar to right-split, except that it switches the roles of below and beside.

Da vedersi in stretto collegamento con lo spiegone del post precedente 😊
Bill the Lizard 🚀 al solito spiega bene, lo seguo 😊 Inoltre, contrariamente alla mia predilizione per il (vecchio) terminale, per via della grafica uso Dr.Racket, quando ci vuole ci vuole 😉

I’m going to be using the PLT Scheme SICP Picture Language package to run the examples and exercises. You can load the picture package by putting the following (require...) expression at the beginning of your Scheme file.

The painter primitive in the PLT package behaves slightly differently than the one presented in the text, in that it doesn’t display itself. To display a painter you must call the paint procedure, which takes a painter as its argument.

The einstein [... is] built in to the PLT Scheme Picture Language package. The package also includes procedures for flipping, rotating and combining painter values, similar to those discussed in the lecture.

Now that we can work with painters, we can start to combine them in ways that form patterns. For example, the text shows us how we can combine an image beside a flipped representation of itself, then draw the resulting painter below itself.

We can also define recursive operations, like right-split, which makes painters split and branch towards the right as many times as we specify.

E a questo punto si arriva all’esercizio

Once we have both right-split and up-split defined, we can create balanced patterns by branching in both directions.

By combining four copies of the corner-split pattern, we can create the square-limit pattern from the Escher drawing that we saw in the lecture.

Secondo me Bill non solo rockz ma è anche oltre 👽

La soluzione di sicp-ex è molto simile a quella di Bill; come pure Drewiki.

:mrgreen:

SICP – cap. 2 – Sequenze come interfacce convenzionali – 54

Continuo da qui, copio qui.

Esempio: un linguaggio di immagini
This section presents a simple language for drawing pictures that illustrates the power of data abstraction and closure, and also exploits higher-order procedures in an essential way. The language is designed to make it easy to experiment with patterns such as the ones in Figure 2.9, which are composed of repeated elements that are shifted and scaled.

Figure 2.9: Designs generated with the picture language.

 

In this language, the data objects being combined are represented as procedures rather than as list structure. Just as cons, which satisfies the closure property, allowed us to easily build arbitrarily complicated list structure, the operations in this language, which also satisfy the closure property, allow us to easily build arbitrarily complicated patterns.

Il linguaggio di immagini
When we began our study of programming [qui], we emphasized the importance of describing a language by focusing on the language’s primitives, its means of combination, and its means of abstraction. We’ll follow that framework here.

Part of the elegance of this picture language is that there is only one kind of element, called a painter. A painter draws an image that is shifted and scaled to fit within a designated parallelogram-shaped frame. For example, there’s a primitive painter we’ll call wave that makes a crude line drawing, as shown in Figure 2.10.

Figure 2.10: Images produced by the wave painter, with respect to four different frames. The frames, shown with dotted lines, are not part of the images.

The actual shape of the drawing depends on the frame—all four images in figure 2.10 are produced by the same wave painter, but with respect to four different frames. Painters can be more elaborate than this: The primitive painter called rogers paints a picture of MIT’s founder, William Barton Rogers, as shown in Figure 2.11.

Figure 2.11: Images of William Barton Rogers, founder and first president of MIT, painted with respect to the same four frames as in Figure 2.10 (original image from Wikimedia Commons).

The four images in figure 2.11 are drawn with respect to the same four frames as the wave images in figure 2.10.

To combine images, we use various operations that construct new painters from given painters. For example, the beside operation takes two painters and produces a new, compound painter that draws the first painter’s image in the left half of the frame and the second painter’s image in the right half of the frame. Similarly, below takes two painters and produces a compound painter that draws the first painter’s image below the second painter’s image. Some operations transform a single painter to produce a new painter. For example, flip-vert takes a painter and produces a painter that draws its image upside-down, and flip-horiz produces a painter that draws the original painter’s image left-to-right reversed.

Figure 2.12 shows the drawing of a painter called wave4 that is built up in two stages starting from wave:

(define wave2 (beside wave (flip-vert wave)))
(define wave4 (below wave2 wave2))

Figure 2.12: Creating a complex figure, starting from the wave painter of Figure 2.10.

In building up a complex image in this manner we are exploiting the fact that painters are closed under the language’s means of combination. The beside or below of two painters is itself a painter; therefore, we can use it as an element in making more complex painters. As with building up list structure using cons, the closure of our data under the means of combination is crucial to the ability to create complex structures while using only a few operations.

Once we can combine painters, we would like to be able to abstract typical patterns of combining painters. We will implement the painter operations as Scheme procedures. This means that we don’t need a special abstraction mechanism in the picture language: Since the means of combination are ordinary Scheme procedures, we automatically have the capability to do anything with painter operations that we can do with procedures. For example, we can abstract the pattern in wave4 as

(define (flipped-pairs painter)
  (let ((painter2 
         (beside painter 
                 (flip-vert painter))))
    (below painter2 painter2)))

and define wave4 as an instance of this pattern:

(define wave4 (flipped-pairs wave))

We can also define recursive operations. Here’s one that makes painters split and branch towards the right as shown in Figure 2.13 and Figure 2.14:

(define (corner-split painter n)
  (if (= n 0)
      painter
      (let ((up (up-split painter (- n 1)))
            (right (right-split painter 
                                (- n 1))))
        (let ((top-left (beside up up))
              (bottom-right (below right 
                                   right))
              (corner (corner-split painter 
                                    (- n 1))))
          (beside (below painter top-left)
                  (below bottom-right 
                         corner))))))

Figure 2.13: Recursive plans for right-split and corner-split.

Figure 2.14: The recursive operations right-split and corner-split applied to the painters wave and rogers. Combining four corner-split figures produces symmetric square-limit designs as shown in Figure 2.9.

By placing four copies of a corner-split appropriately, we obtain a pattern called square-limit, whose application to wave and rogers is shown in Figure 2.9:

(define (square-limit painter n)
  (let ((quarter (corner-split painter n)))
    (let ((half (beside (flip-horiz quarter) 
                        quarter)))
      (below (flip-vert half) half))))

Panico? 😯 Kwasy 😯

:mrgreen: