blob: dca5e6eb386b1de08d3f9badef5833fcfbda2ff2 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
(defun read-map (filespec)
(with-open-file (stream filespec)
(let ((lines (loop for line = (read-line stream nil)
while line
collect (make-array
(length line)
:initial-contents (loop for c across line
collect (- (char-code c)
(char-code #\0)))))))
(make-array (list (length lines) (length (first lines))) :initial-contents lines))))
(defun min-node (q)
(let ((mk ())
(mv -1))
(maphash (lambda (k v) (when (or (= mv -1) (< v mv)) (setf mk k mv v))) q)
mk))
(defun best-path (map min-moves max-moves)
(let ((q (make-hash-table :test #'equalp))
(v (make-hash-table :test #'equalp))
(n (array-dimension map 0))
(m (array-dimension map 1)))
(labels ((is-final (node)
(multiple-value-bind (i j) (values-list node)
(and (= i (1- n)) (= j (1- m)))))
(is-possible (node)
(multiple-value-bind (i j c) (values-list node)
(and (>= i 0) (>= j 0) (< i n) (< j m) (<= c max-moves))))
(add-node (node val)
(unless (or (not (is-possible node)) (gethash node v))
(multiple-value-bind (oval found-p) (gethash node q)
(multiple-value-bind (i j) (values-list node)
(let ((val (+ val (aref map i j))))
(setf (gethash node q) (if found-p (min val oval) val))))))))
(setf (gethash '(0 1 1 #\R) q) (aref map 0 1))
(setf (gethash '(1 0 1 #\D) q) (aref map 1 0))
(loop for node = (min-node q)
while node
if (is-final node)
return (gethash node q)
do (multiple-value-bind (i j c d) (values-list node)
(let ((val (gethash node q)))
(remhash node q)
(setf (gethash node v) val)
(unless (or (equal d #\D) (and (not (equal d #\U)) (< c min-moves)))
(add-node (list (1- i) j (if (equal d #\U) (1+ c) 1) #\U) val))
(unless (or (equal d #\U) (and (not (equal d #\D)) (< c min-moves)))
(add-node (list (1+ i) j (if (equal d #\D) (1+ c) 1) #\D) val))
(unless (or (equal d #\R) (and (not (equal d #\L)) (< c min-moves)))
(add-node (list i (1- j) (if (equal d #\L) (1+ c) 1) #\L) val))
(unless (or (equal d #\L) (and (not (equal d #\R)) (< c min-moves)))
(add-node (list i (1+ j) (if (equal d #\R) (1+ c) 1) #\R) val))))))))
(defun solve1 (filespec)
(best-path (read-map filespec) 0 3))
(defun solve2 (filespec)
(best-path (read-map filespec) 4 10))
(print (solve1 "data/17/example.txt")) ;; 102
(print (solve1 "data/17/input.txt")) ;; 1039
(print (solve2 "data/17/example.txt")) ;; 102
(print (solve2 "data/17/input.txt")) ;; 1201
|