Compare commits
5 Commits
3df3a70754
...
98336be2d7
| Author | SHA1 | Date | |
|---|---|---|---|
| 98336be2d7 | |||
| a22420b554 | |||
| d35640dc63 | |||
| f0d18d31ce | |||
| a1266ca648 |
@@ -1,39 +1,6 @@
|
|||||||
(import (srfi :43)) ; vector extensions
|
(import (srfi :43)) ; vector extensions
|
||||||
(load "../common.scm")
|
(load "../common.scm")
|
||||||
|
|
||||||
; constructor of heightmap object
|
|
||||||
; from a vector of vector of altitudes
|
|
||||||
(define (make-heightmap data)
|
|
||||||
(list
|
|
||||||
(vector-length (vector-ref data 0)) ; width
|
|
||||||
(vector-length data) ; height
|
|
||||||
data))
|
|
||||||
|
|
||||||
; heightmap object getters
|
|
||||||
(define (heightmap-width heightmap) (car heightmap))
|
|
||||||
(define (heightmap-height heightmap) (cadr heightmap))
|
|
||||||
(define (heightmap-data heightmap) (caddr heightmap))
|
|
||||||
(define (sample-heightmap heightmap x y)
|
|
||||||
(if (or (< x 0)
|
|
||||||
(< y 0)
|
|
||||||
(>= x (heightmap-width heightmap))
|
|
||||||
(>= y (heightmap-height heightmap)))
|
|
||||||
9
|
|
||||||
(vector-ref (vector-ref (heightmap-data heightmap) y) x)))
|
|
||||||
|
|
||||||
; parse altitude data from file and return an heightmap object
|
|
||||||
(define (load-heightmap file)
|
|
||||||
(let y-loop [(heightmap '())]
|
|
||||||
(let x-loop [(line '())]
|
|
||||||
(let [(c (get-char file))]
|
|
||||||
(cond
|
|
||||||
[(eof-object? c)
|
|
||||||
(make-heightmap (reverse-list->vector heightmap))]
|
|
||||||
[(char-whitespace? c)
|
|
||||||
(y-loop (cons (reverse-list->vector line) heightmap))]
|
|
||||||
[(char-numeric? c)
|
|
||||||
(x-loop (cons (char->number c) line))])))))
|
|
||||||
|
|
||||||
; constructor of low point objects
|
; constructor of low point objects
|
||||||
; from their position and altitude
|
; from their position and altitude
|
||||||
(define (make-low-point x y altitude)
|
(define (make-low-point x y altitude)
|
||||||
@@ -50,17 +17,17 @@
|
|||||||
(lambda (y line)
|
(lambda (y line)
|
||||||
(vector-for-each
|
(vector-for-each
|
||||||
(lambda (x altitude)
|
(lambda (x altitude)
|
||||||
(let [(left (sample-heightmap heightmap (- x 1) y))
|
(let [(left (matrix-get heightmap (- x 1) y 9))
|
||||||
(right (sample-heightmap heightmap (+ x 1) y))
|
(right (matrix-get heightmap (+ x 1) y 9))
|
||||||
(up (sample-heightmap heightmap x (- y 1)))
|
(up (matrix-get heightmap x (- y 1) 9))
|
||||||
(down (sample-heightmap heightmap x (+ y 1)))]
|
(down (matrix-get heightmap x (+ y 1) 9))]
|
||||||
(when (and (< altitude left)
|
(when (and (< altitude left)
|
||||||
(< altitude right)
|
(< altitude right)
|
||||||
(< altitude up)
|
(< altitude up)
|
||||||
(< altitude down))
|
(< altitude down))
|
||||||
(set! low-points (cons (make-low-point x y altitude) low-points)))))
|
(set! low-points (cons (make-low-point x y altitude) low-points)))))
|
||||||
line))
|
line))
|
||||||
(heightmap-data heightmap))
|
(matrix-data heightmap))
|
||||||
low-points))
|
low-points))
|
||||||
|
|
||||||
; compute risk level from low point list
|
; compute risk level from low point list
|
||||||
@@ -70,8 +37,8 @@
|
|||||||
; starting with from a given low-point
|
; starting with from a given low-point
|
||||||
; call closure with and all points of the corresponding basin
|
; call closure with and all points of the corresponding basin
|
||||||
(define (visit-basin heightmap low-point closure)
|
(define (visit-basin heightmap low-point closure)
|
||||||
(let* [(width (heightmap-width heightmap))
|
(let* [(width (matrix-width heightmap))
|
||||||
(height (heightmap-height heightmap))
|
(height (matrix-height heightmap))
|
||||||
(width-1 (- width 1))
|
(width-1 (- width 1))
|
||||||
(height-1 (- height 1))
|
(height-1 (- height 1))
|
||||||
(visited (make-vector (* width height) 0))]
|
(visited (make-vector (* width height) 0))]
|
||||||
@@ -82,7 +49,7 @@
|
|||||||
(let [(ofs (offset x y))]
|
(let [(ofs (offset x y))]
|
||||||
(when (= (vector-ref visited ofs) 0)
|
(when (= (vector-ref visited ofs) 0)
|
||||||
(vector-set! visited ofs 1)
|
(vector-set! visited ofs 1)
|
||||||
(when (< (sample-heightmap heightmap x y) 9)
|
(when (< (matrix-get heightmap x y 9) 9)
|
||||||
(closure x y)
|
(closure x y)
|
||||||
(when (> x 0) (flood-fill (- x 1) y))
|
(when (> x 0) (flood-fill (- x 1) y))
|
||||||
(when (< x width-1) (flood-fill (+ x 1) y))
|
(when (< x width-1) (flood-fill (+ x 1) y))
|
||||||
@@ -118,12 +85,12 @@
|
|||||||
(lambda (file)
|
(lambda (file)
|
||||||
; write header to file: "P3" followed by width, height and max value of channel
|
; write header to file: "P3" followed by width, height and max value of channel
|
||||||
(fprintf file "P3~%~a ~a~%255~%"
|
(fprintf file "P3~%~a ~a~%255~%"
|
||||||
(heightmap-width heightmap)
|
(matrix-width heightmap)
|
||||||
(heightmap-height heightmap))
|
(matrix-height heightmap))
|
||||||
|
|
||||||
(let* [(width (heightmap-width heightmap))
|
(let* [(width (matrix-width heightmap))
|
||||||
(width*3 (* width 3))
|
(width*3 (* width 3))
|
||||||
(height (heightmap-height heightmap))
|
(height (matrix-height heightmap))
|
||||||
(data (make-vector (* width*3 width)))]
|
(data (make-vector (* width*3 width)))]
|
||||||
|
|
||||||
; from (x,y) returns of offset of pixel's red channel in data vector
|
; from (x,y) returns of offset of pixel's red channel in data vector
|
||||||
@@ -136,7 +103,7 @@
|
|||||||
(let y-loop [(y 0)]
|
(let y-loop [(y 0)]
|
||||||
(let x-loop [(x 0)]
|
(let x-loop [(x 0)]
|
||||||
(let [(ofs (offset x y))
|
(let [(ofs (offset x y))
|
||||||
(gray-level (* (sample-heightmap heightmap x y) 20))]
|
(gray-level (* (matrix-get heightmap x y 9) 20))]
|
||||||
; red channel
|
; red channel
|
||||||
(vector-set! data ofs gray-level)
|
(vector-set! data ofs gray-level)
|
||||||
; green channel
|
; green channel
|
||||||
@@ -173,7 +140,7 @@
|
|||||||
(call-with-input-file
|
(call-with-input-file
|
||||||
"input"
|
"input"
|
||||||
(lambda (file)
|
(lambda (file)
|
||||||
(let* [(heightmap (load-heightmap file))
|
(let* [(heightmap (load-matrix file))
|
||||||
(low-points (find-low-points heightmap))]
|
(low-points (find-low-points heightmap))]
|
||||||
(printf "part 1:~% Risk level: ~a~%"
|
(printf "part 1:~% Risk level: ~a~%"
|
||||||
(risk-level low-points))
|
(risk-level low-points))
|
||||||
|
|||||||
72
11-dumbo-octopus/code.scm
Normal file
72
11-dumbo-octopus/code.scm
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
(load "../common.scm")
|
||||||
|
|
||||||
|
(define-record-type vec2i (fields x y))
|
||||||
|
|
||||||
|
; flash given octopus
|
||||||
|
; ie. increase energy of neighbor ones
|
||||||
|
; returns list of octopuses that now need to flash too
|
||||||
|
(define (flash! matrix x y)
|
||||||
|
(let [(extra '())]
|
||||||
|
(let y-loop [(yy (- y 1))]
|
||||||
|
(let x-loop [(xx (- x 1))]
|
||||||
|
(when (not (and (= xx x) (= yy y)))
|
||||||
|
(when (< (matrix-get matrix xx yy 0) 10)
|
||||||
|
(when (= (matrix-inc! matrix xx yy) 10)
|
||||||
|
(set! extra (cons (make-vec2i xx yy) extra)))))
|
||||||
|
(when (< xx (+ x 1))
|
||||||
|
(x-loop (+ xx 1))))
|
||||||
|
(when (< yy (+ y 1))
|
||||||
|
(y-loop (+ yy 1))))
|
||||||
|
extra))
|
||||||
|
|
||||||
|
(define (step! matrix)
|
||||||
|
(let [(flashes '())]
|
||||||
|
; increase energy of all octopuses
|
||||||
|
(visit-matrix!
|
||||||
|
matrix
|
||||||
|
(lambda (x y energy)
|
||||||
|
(when (= energy 9)
|
||||||
|
(set! flashes (cons (make-vec2i x y) flashes)))
|
||||||
|
(+ 1 energy)))
|
||||||
|
; recursively flash octopuses
|
||||||
|
(let loop [(flash flashes)]
|
||||||
|
(when (not (null? flash))
|
||||||
|
(loop (append (cdr flash)
|
||||||
|
(flash! matrix (vec2i-x (car flash))
|
||||||
|
(vec2i-y (car flash)))))))
|
||||||
|
; drain all octopuses that flashed
|
||||||
|
(visit-matrix!
|
||||||
|
matrix
|
||||||
|
(lambda (x y energy)
|
||||||
|
(if (< energy 10) energy 0)))
|
||||||
|
; count octopuses that flashed
|
||||||
|
(vector-fold
|
||||||
|
(lambda (y sum line)
|
||||||
|
(+ sum
|
||||||
|
(vector-fold
|
||||||
|
(lambda (x sum value)
|
||||||
|
(if (= value 0) (+ sum 1) sum))
|
||||||
|
0 line)))
|
||||||
|
0 (matrix-data matrix))))
|
||||||
|
|
||||||
|
(call-with-input-file
|
||||||
|
"input"
|
||||||
|
(lambda (file)
|
||||||
|
(let [(matrix (load-matrix file))
|
||||||
|
(flash-count 0)]
|
||||||
|
(let loop [(i 0)]
|
||||||
|
(set! flash-count (+ flash-count
|
||||||
|
(step! matrix)))
|
||||||
|
(when (< i 99)
|
||||||
|
(loop (+ i 1))))
|
||||||
|
(printf "part 1:~% ~a flashes after a hundred steps.~%"
|
||||||
|
flash-count)
|
||||||
|
(let loop [(i 100)]
|
||||||
|
(if (= (matrix-sum matrix) 0)
|
||||||
|
(printf "part 2:~% Octopuses synchronized at step ~a.~%" i)
|
||||||
|
(begin
|
||||||
|
(step! matrix)
|
||||||
|
(loop (+ i 1))))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
10
11-dumbo-octopus/input
Normal file
10
11-dumbo-octopus/input
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
1326253315
|
||||||
|
3427728113
|
||||||
|
5751612542
|
||||||
|
6543868322
|
||||||
|
4422526221
|
||||||
|
2234325647
|
||||||
|
1773174887
|
||||||
|
7281321674
|
||||||
|
6562513118
|
||||||
|
4824541522
|
||||||
85
common.scm
85
common.scm
@@ -1,3 +1,5 @@
|
|||||||
|
(import (srfi :43)) ; vector extensions
|
||||||
|
|
||||||
; returns a list of numbers parsed from the first line of the file,
|
; returns a list of numbers parsed from the first line of the file,
|
||||||
; separated by commas
|
; separated by commas
|
||||||
(define (read-comma-separated-numbers file)
|
(define (read-comma-separated-numbers file)
|
||||||
@@ -12,3 +14,86 @@
|
|||||||
(define (char->number c)
|
(define (char->number c)
|
||||||
(- (char->integer c) 48)) ; 48 is ASCII's number zero
|
(- (char->integer c) 48)) ; 48 is ASCII's number zero
|
||||||
|
|
||||||
|
(define-record-type matrix (fields width height data))
|
||||||
|
|
||||||
|
; builds a matrix record from the given 2D vector
|
||||||
|
; vectors inside data vector are expected to all be the same length
|
||||||
|
(define (matrix-from-data data)
|
||||||
|
(make-matrix
|
||||||
|
(vector-length (vector-ref data 0))
|
||||||
|
(vector-length data)
|
||||||
|
data))
|
||||||
|
|
||||||
|
; returns value at x,y coordinates in matrix
|
||||||
|
; if coordinate is out of bounds, returns default
|
||||||
|
(define (matrix-get matrix x y default)
|
||||||
|
(if (or (< x 0)
|
||||||
|
(< y 0)
|
||||||
|
(>= x (matrix-width matrix))
|
||||||
|
(>= y (matrix-height matrix)))
|
||||||
|
default
|
||||||
|
(vector-ref (vector-ref (matrix-data matrix) y) x)))
|
||||||
|
|
||||||
|
; set value at x,y in matrix with given one
|
||||||
|
; if coordinate is out of bounds, nothing happens
|
||||||
|
(define (matrix-set! matrix x y value)
|
||||||
|
(when (and (>= x 0)
|
||||||
|
(>= y 0)
|
||||||
|
(< x (matrix-width matrix))
|
||||||
|
(< y (matrix-height matrix)))
|
||||||
|
(vector-set! (vector-ref (matrix-data matrix) y) x value)))
|
||||||
|
|
||||||
|
; print matrix line by line to console
|
||||||
|
; each line will be displayed as a scheme-vector
|
||||||
|
(define (matrix-print matrix)
|
||||||
|
(let y-loop [(y 0)]
|
||||||
|
(printf "~a~%" (vector-ref (matrix-data matrix) y))
|
||||||
|
(when (< y (- (matrix-height matrix) 1))
|
||||||
|
(y-loop (+ y 1)))))
|
||||||
|
|
||||||
|
; parse 0-9 numerical data from file and return a matrix
|
||||||
|
(define (load-matrix file)
|
||||||
|
(let y-loop [(heightmap '())]
|
||||||
|
(let x-loop [(line '())]
|
||||||
|
(let [(c (get-char file))]
|
||||||
|
(cond
|
||||||
|
[(eof-object? c)
|
||||||
|
(matrix-from-data (reverse-list->vector heightmap))]
|
||||||
|
[(char-whitespace? c)
|
||||||
|
(y-loop (cons (reverse-list->vector line) heightmap))]
|
||||||
|
[(char-numeric? c)
|
||||||
|
(x-loop (cons (char->number c) line))])))))
|
||||||
|
|
||||||
|
; matrix visitor
|
||||||
|
; calls function with all coordinates of matrix and value at corresponding point
|
||||||
|
; value returned by function is set at the visiting coordinate
|
||||||
|
(define (visit-matrix! matrix function)
|
||||||
|
(let [(data (matrix-data matrix))
|
||||||
|
(width-1 (- (matrix-width matrix) 1))
|
||||||
|
(height-1 (- (matrix-height matrix) 1))]
|
||||||
|
(let y-loop [(y 0)]
|
||||||
|
(let x-loop [(x 0)]
|
||||||
|
(let [(value (vector-ref (vector-ref data y) x))]
|
||||||
|
(vector-set! (vector-ref data y) x
|
||||||
|
(function x y value))
|
||||||
|
(when (< x width-1)
|
||||||
|
(x-loop (+ x 1)))))
|
||||||
|
(when (< y height-1)
|
||||||
|
(y-loop (+ y 1))))))
|
||||||
|
|
||||||
|
; increase by 1 value at x,y in given matrix
|
||||||
|
; return that value too
|
||||||
|
(define (matrix-inc! matrix x y)
|
||||||
|
(let [(v (+ 1 (matrix-get matrix x y 0)))]
|
||||||
|
(matrix-set! matrix x y v)
|
||||||
|
v))
|
||||||
|
|
||||||
|
; sum all values of matrix
|
||||||
|
(define (matrix-sum matrix)
|
||||||
|
(vector-fold
|
||||||
|
(lambda (y sum line)
|
||||||
|
(+ sum
|
||||||
|
(vector-fold
|
||||||
|
(lambda (x sum value) (+ sum value))
|
||||||
|
0 line)))
|
||||||
|
0 (matrix-data matrix)))
|
||||||
|
|||||||
Reference in New Issue
Block a user