-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathp81.scm
75 lines (65 loc) · 2.51 KB
/
p81.scm
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
64
65
66
67
68
69
70
71
72
73
74
; Project Euler problem 81 using Pre-Scheme (Scheme-to-C compiler from Scheme 48)
; There must be some better way to get a hold of the "unit" (void?) type
(define nil (let ((x 0)) (set! x 0)))
; Note: Need to supply a default, in case of I/O error
(define-syntax with-open-file
(syntax-rules ()
((with-open-file (file filename default) body ...)
(receive (file status) (open-input-file filename)
; Oddly, (enum errors no-errors) doesn't work (NO_ERRORS isn't defined in prescheme.h!)
(if (eq? status 0)
(let ((result (begin body ...)))
(close-input-port file)
result)
default)))))
(define-syntax for-range
(syntax-rules ()
((for-range (index initial limit) body ...)
(let ((l limit))
(do ((index initial (+ index 1))) ((>= index l))
body ...)))))
(define (skip-char file)
(read-char file)
nil) ; Annoying that a value is required here...
(define (read-integer-unsafe file)
(receive (int eof? status) (read-integer file)
int))
(define matrix-size 80)
(define (matrix-index i j) (+ (* matrix-size i) j))
(define (matrix-set matrix i j value) (vector-set! matrix (matrix-index i j) value))
(define (matrix-get matrix i j) (vector-ref matrix (matrix-index i j)))
(define (min a b) (if (< a b) a b))
(define (matrix-parse filename)
(letrec
((matrix-parse-recursive
(lambda (file matrix index limit)
(if (< index limit)
(begin
(if (> index 0) (skip-char file))
(vector-set! matrix index (read-integer-unsafe file))
(matrix-parse-recursive file matrix (+ index 1) limit))
matrix))))
(let* ((size (* matrix-size matrix-size))
(matrix (make-vector size 0)))
(with-open-file (file filename matrix)
(matrix-parse-recursive file matrix 0 size)))))
; Walk left-to-right, top-to-bottom, filling in best of up/left path
(define (matrix-solve matrix)
(for-range (i 0 matrix-size)
(for-range (j 0 matrix-size)
(if (or (> i 0) (> j 0))
(let ((up (if (> i 0) (matrix-get matrix (- i 1) j) 1000000000))
(left (if (> j 0) (matrix-get matrix i (- j 1)) 1000000000)))
(matrix-set matrix i j (+ (matrix-get matrix i j) (min up left)))))))
(let ((last (- matrix-size 1)))
(matrix-get matrix last last)))
; Entry point
(define (main argc argv)
(if (= argc 2)
(let* ((out (current-output-port))
(matrix (matrix-parse (vector-ref argv 1)))
(solution (matrix-solve matrix)))
(write-integer solution out)
(newline out)
0)
-1))