2009년 04월 13일
SICP 연습문제 2.42인 8-queen을 풀었다(스포일러 주의!!!).
이 한문제 푼다고 4시간 정도 걸린 것 같다. -_-;
문제에 있는 코드를 보면 n X n 체스보드 판에 n개의 퀸을 배치하는 순열을 생성하고 그걸 safe?라는 술어(predicate) 함수로 필터링하는 식으로 되어있다.
퀸을 보드의 세로줄에 놓는 모든 경우를 생성하는 순열은 금방 만들었고 safe?를 판단하는 함수도 쉽게 만들었다. 그런데 이 두개를 합치려니까 결과가 안나왔다. 알고보니 depth를 착각했던 게 원인이었다.
거두절미하고 코드는 다음과 같다. 혹시나 답을 보기 원치 않은 분을 위해서 여백을 넣었다.
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op initial (cdr sequence)))))
(define (enumerate-interval start end)
(if (> start end)
null
(cons start (enumerate-interval (+ start 1) end))))
(define (flatmap proc seq)
(accumulate append null (map proc seq)))
; answer
(define empty-board
null)
(define (adjoin-position new-row k rest-of-queens)
(accumulate cons rest-of-queens (list (list new-row k))))
(define (safe? k positions)
(define (invalid? pos1 pos2)
(or (equal? (car pos1) (car pos2))
(equal? (cadr pos1) (cadr pos2))
(equal? (abs (- (car pos1) (car pos2)))
(abs (- (cadr pos1) (cadr pos2))))))
(define a (car positions))
(define b (cdr positions))
(null? (filter
(lambda (x) (invalid? a x))
b)))
; problem
(define (queens board-size)
(define (queen-cols k)
(define safe (lambda (positions) (safe? k positions)))
(if (= k 0)
(list empty-board)
(filter
safe
(flatmap
(lambda (rest-of-queens)
(map (lambda (new-row)
(adjoin-position new-row k rest-of-queens))
(enumerate-interval 1 board-size)))
(queen-cols (- k 1))))))
(queen-cols board-size))
;test-case
(equal? (list (list 3 2) (list 2 7) (list 1 3))
(adjoin-position 3 2 (list (list 2 7) (list 1 3))))
(equal? (list (list (list 1 1)))
(queens 1))
(equal? null
(queens 2))
(equal? null
(queens 3))
(define queens-4
(list (list (list 3 4) (list 1 3) (list 4 2) (list 2 1)) (list (list 2 4) (list 4 3) (list 1 2) (list 3 1))))
(equal? queens-4
(queens 4))
문제에 있는 코드를 보면 n X n 체스보드 판에 n개의 퀸을 배치하는 순열을 생성하고 그걸 safe?라는 술어(predicate) 함수로 필터링하는 식으로 되어있다.
퀸을 보드의 세로줄에 놓는 모든 경우를 생성하는 순열은 금방 만들었고 safe?를 판단하는 함수도 쉽게 만들었다. 그런데 이 두개를 합치려니까 결과가 안나왔다. 알고보니 depth를 착각했던 게 원인이었다.
거두절미하고 코드는 다음과 같다. 혹시나 답을 보기 원치 않은 분을 위해서 여백을 넣었다.
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op initial (cdr sequence)))))
(define (enumerate-interval start end)
(if (> start end)
null
(cons start (enumerate-interval (+ start 1) end))))
(define (flatmap proc seq)
(accumulate append null (map proc seq)))
; answer
(define empty-board
null)
(define (adjoin-position new-row k rest-of-queens)
(accumulate cons rest-of-queens (list (list new-row k))))
(define (safe? k positions)
(define (invalid? pos1 pos2)
(or (equal? (car pos1) (car pos2))
(equal? (cadr pos1) (cadr pos2))
(equal? (abs (- (car pos1) (car pos2)))
(abs (- (cadr pos1) (cadr pos2))))))
(define a (car positions))
(define b (cdr positions))
(null? (filter
(lambda (x) (invalid? a x))
b)))
; problem
(define (queens board-size)
(define (queen-cols k)
(define safe (lambda (positions) (safe? k positions)))
(if (= k 0)
(list empty-board)
(filter
safe
(flatmap
(lambda (rest-of-queens)
(map (lambda (new-row)
(adjoin-position new-row k rest-of-queens))
(enumerate-interval 1 board-size)))
(queen-cols (- k 1))))))
(queen-cols board-size))
;test-case
(equal? (list (list 3 2) (list 2 7) (list 1 3))
(adjoin-position 3 2 (list (list 2 7) (list 1 3))))
(equal? (list (list (list 1 1)))
(queens 1))
(equal? null
(queens 2))
(equal? null
(queens 3))
(define queens-4
(list (list (list 3 4) (list 1 3) (list 4 2) (list 2 1)) (list (list 2 4) (list 4 3) (list 1 2) (list 3 1))))
(equal? queens-4
(queens 4))
# by | 2009/04/13 18:28 | SICP 스터디 | 트랙백 | 덧글(0)



