---
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)))]
)
)
```