---
# System prepended metadata

title: Lista 4
tags: [mp, ' WCh']

---

---
tags: mp, WCh
---

# Lista 4

## Ćwiczenie 1

```racket=
; Wybrana reprezentacja:
; Lista par współrzędnych (col row).
; N.p. odpowiedź dla (queens 4):
; '(((4 . 3) (3 . 1) (2 . 4) (1 . 2)) ((4 . 2) (3 . 4) (2 . 1) (1 . 3)))
(define (empty-board)
'())

```

adjoin-position

```racket=
(define (adjoin-position row col rest)
(cons (cons col row) rest))
```

safe?

```racket=
(define (safe? k positions)
    (define this (car (filter (lambda (x) (= (car x) k)) positions)))
    (= 0 (length (filter
        (lambda (other) ; czy other konfliktuje z this?
            (and
                (not (equal? this other)) ; jeśli this = other, nie ma konfliktu
                (or
                    (= (cdr this) (cdr other)) ; ten sam wiersz
                    ; (= (car this) (car other)) ; ta sama kolumna
                    (= (abs (- (cdr this) (cdr other)))
                        (abs (- (car this) (car other)))) ; ta sama przekątna
                )
            )
        )
        positions
    )))
)
```

queens

```racket=
#lang racket
(define (concatMap x y) (append-map x y))
(define (from-to x y)
    (if (= x y)
        (list y)
        (cons x (from-to (+ x 1) y))
))

(define (queens board-size)
  ;; Return the representation of a board with 0 queens inserted
  (define (empty-board)
    null)
  ;; Return the representation of a board with a new queen at
  ;; (row , col) added to the partial representation `rest '
  (define (adjoin-position row col rest)
    (cons (cons col row) rest))
  ;; Return true if the queen in k-th column does not attack any of
  ;; the others
  (define (safe? k positions)
        (define this (car (filter (lambda (x) (= (car x) k)) positions)))
        (= 0 (length (filter
            (lambda (other) ; czy other konfliktuje z this?
                (and
                    (not (equal? this other)) ; jeśli this = other, nie ma konfliktu
                    (or
                        (= (cdr this) (cdr other)) ; ten sam wiersz
                        ; (= (car this) (car other)) ; ta sama kolumna
                        (= (abs (- (cdr this) (cdr other)))
                            (abs (- (car this) (car other)))) ; ta sama przekątna
                    )
                )
            )
            positions
        ))))
  ;; Return a list of all possible solutions for k first columns
  (define (queen-cols k)
    (if (= k 0)
        (list (empty-board))
        (filter
         (lambda (positions) (safe? k positions))
         (concatMap
          (lambda (rest-of-queens)
            (map (lambda (new-row)
                   (adjoin-position new-row k rest-of-queens))
                 (from-to 1 board-size)))
          (queen-cols (- k 1))))))
  (queen-cols board-size))
  ```


## Ćwiczenie 2
```racket=
(append-map
  (lambda (rest-of-queens)
   (map (lambda (new-row)
         (adjoin-position new-row k rest-of-queens))
        (from-to 1 board-size)))
  (queen-cols (- k 1))))))
```
vs
```racket
(append-map
 (lambda (new-row)
  (map (lambda (rest-of-queens)
         (adjoin-position new-row k rest-of-queens))
       (queen-cols (- k 1))))
(from-to 1 board-size)))))
```

Różnica między tymi dwoma podejściami jest taka, że w pierwszym, w każdym wywołaniu rekurencyjnym queen-cols jest wywołane tylko raz (jako drugi argument append-map), ale w drugim (intuicyjnie) queen-cols jest wywoływane w każdym “obrocie” append-map, co znacznie obniża wydajność, bo dla każdego nowego wiersza są ponawiane te same obliczenia.

Można to naprawić korzystając np. z let i zapisując wartośc (queen-cols (- k 1)) przed wywołaniem append-map.

## Ćwiczenie 3


```racket=
(define (leaf) 'leaf)
(define (leaf? t) (eq? t 'leaf))
(define (node value left-subtree right-subtree)
    (list 'node value left-subtree right-subtree))
(define (left-subtree t)
  (caddr t))
(define (right-subtree t)
  (cadddr t))
(define (label t)
  (car t))
(define (value t)
  (cadr t))

(define (btree? t)
  (or (eq? t 'leaf)
      (and (list? t)
           (= 4 (length t))
           (eq? (label t) 'node)
           (btree? (left-subtree t))
           (btree? (right-subtree t)))))

(define (mirror t)
    (if (leaf? t) (leaf)
        (node (value t) (mirror (right-subtree t)) (mirror (left-subtree t)))
    ))
    
(require rackunit)
(check-equal? (mirror '(node a (node b (node c leaf leaf) leaf) (node d leaf leaf)))
    '(node a (node d leaf leaf) (node b leaf (node c leaf leaf))))
```

## Ćwiczenie 4


Jedynym miejscem w wersji iteracyjnej, w którym alokujemy pamięć jest cons w linii 10. Tymczasem w wersji rekurencyjnej procedura append kopiuje elementy, więc (flatten (left-subtree t)) jest nieużytkiem.

```racket=

(define (flatten-rec t)
    (if (leaf? t) null
        (append (flatten-rec (left-subtree t)) (list (value t)) (flatten-rec (right-subtree t)))
    ))

(define (flatten t)
    (define (iter acc t)
        (if (leaf? t) acc
            (iter
                (cons
                    (value t)
                    (iter acc (right-subtree t)))
                (left-subtree t))
        )
    )
    (iter null t)
)

(check-equal? (flatten '(node a (node b (node c leaf leaf) leaf) (node d leaf leaf)))
    '(c b a d))
```

## Ćwiczenie 5
```racket=
(define (insert l x)
    (if (null? l)
        (list x)
        (if (> x (car l))
            (cons (car l) (insert (cdr l) x))
            (cons x l)
        )
    )
)

; (1 2 1 5 2 7 2) ()
; (2 1 5 2 7 2) (1)
; (1 5 2 7 2) (1 2)
; (5 2 7 2) (1 1 2)
; (2 7 2) (1 1 2 5)
(define (insertion-sort l)
    (define (sort l acc)
      (if (null? l)
        acc
        (sort (cdr l) (insert acc (car l)))))
    (sort l '()))

(define (random-list k)
  (if (= k 0)
      null
      (cons (random 10000) (random-list (- k 1))))) 

(insertion-sort (random-list 100))


(take (insertion-sort (random-list 10000)) 100)
```
```racket=

(define (insert x t)
  (cond
    [(leaf? t)        (node x (leaf) (leaf))]
    [(= (value t) x)  t]
    [(> (value t) x)  (node (value t)
                                (insert x (left-subtree t))
                                (right-subtree t))]
    [(< (value t) x)  (node (value t)
                                (left-subtree t)
                                (insert x (right-subtree t)))]))

(define (tree-sort l)
    (define (from-list acc xs)
        (if (null? xs)
            acc
            (from-list (insert (car xs) acc)
                       (cdr xs))))
    (flatten (from-list (leaf) l))
)
```

## Ćwiczenie 6

    Szukamy elementu do usunięcia.
    Usuwamy najmniejszy element z jego prawego poddrzewa (R->L->L->…->L).
    Ten najmniejszy element wstawiamy w miejsce elementu do usunięcia.
    
```racket=
(define (delete elt t)
    (define (find-smallest t)
        (if (leaf? (left-subtree t))
            (value t)
            (find-smallest (left-subtree t))))
    (cond
        [(leaf? t) (leaf)]
        [(= (value t) elt)
            (if (leaf? (right-subtree t))
                (left-subtree t)
                (let [(smallest (find-smallest (right-subtree t)))]
                    (node
                        smallest
                        (left-subtree t)
                        (delete smallest (right-subtree t))
                    )))]
        [(> (value t) elt) (node (value t)
            (delete elt (left-subtree t))
            (right-subtree t))]
        [(< (value t) elt) (node (value t)
            (left-subtree t)
            (delete elt (right-subtree t)))]
    )
)
```