78 lines
2.8 KiB
Scheme
78 lines
2.8 KiB
Scheme
(load "../common.scm")
|
|
|
|
; returns a vector of the same length of input string
|
|
; where all values are 0 except for when the corresponding
|
|
; entry in the string is '#' which will have a 1 instead.
|
|
(define (string->bin-vector str)
|
|
(vector-unfold
|
|
(lambda (i)
|
|
(if (char=? (string-ref str i) #\#) 1 0))
|
|
(string-length str)))
|
|
|
|
; returns a binary matrix loaded from the file
|
|
; all the lines are expected to be the same lengths
|
|
(define (file->matrix file)
|
|
(let loop [(data '())]
|
|
(if (eof-object? (peek-char file))
|
|
(matrix-from-data (reverse-list->vector data))
|
|
(loop (cons (string->bin-vector (get-line file)) data)))))
|
|
|
|
; palette enhancing algorihtm:
|
|
; for each pixel in input image
|
|
; gather all pixels around it to form a 3x3 matrix
|
|
; turn that matrix into a binary number, row by row
|
|
; look up new pixel value in input palette
|
|
(define (enhance image palette steps)
|
|
(let* [(new-width (+ (matrix-width image) 4))
|
|
(new-height (+ (matrix-height image) 4))
|
|
(new-image (filled-matrix new-width new-height 0))
|
|
(top-left (matrix-get image 0 0 0))
|
|
; if palette 0 is 1, outside becomes all 1 each odd iteration
|
|
(outside (if (= (vector-ref palette 0) 1) (mod steps 2) 0))]
|
|
(update-matrix!
|
|
new-image
|
|
(lambda (x y v)
|
|
(vector-ref palette (+ (* (matrix-get image (- x 3) (- y 3) outside) 256)
|
|
(* (matrix-get image (- x 2) (- y 3) outside) 128)
|
|
(* (matrix-get image (- x 1) (- y 3) outside) 64)
|
|
(* (matrix-get image (- x 3) (- y 2) outside) 32)
|
|
(* (matrix-get image (- x 2) (- y 2) outside) 16)
|
|
(* (matrix-get image (- x 1) (- y 2) outside) 8)
|
|
(* (matrix-get image (- x 3) (- y 1) outside) 4)
|
|
(* (matrix-get image (- x 2) (- y 1) outside) 2)
|
|
(* (matrix-get image (- x 1) (- y 1) outside) 1)))))
|
|
(if (<= steps 1)
|
|
new-image
|
|
(enhance new-image palette (- steps 1)))))
|
|
|
|
; for debugging purposes
|
|
; output a PGM 1bpp image file from a given binary matrix
|
|
(define (matrix->image-file matrix filename)
|
|
(when (file-exists? filename)
|
|
(delete-file filename))
|
|
(call-with-output-file
|
|
filename
|
|
(lambda (file)
|
|
(fprintf file "P1~%~a ~a~%" (matrix-width matrix) (matrix-height matrix))
|
|
(vector-for-each
|
|
(lambda (y line)
|
|
(vector-for-each
|
|
(lambda (x pixel) (fprintf file "~a " (- 1 pixel))) line)
|
|
(fprintf file "~%"))
|
|
(matrix-data matrix)))))
|
|
|
|
(call-with-input-file
|
|
"input"
|
|
(lambda (file)
|
|
(let* [(enhancer (string->bin-vector (get-line file)))
|
|
(image (begin
|
|
(get-line file) ; skip empty line
|
|
(file->matrix file)))]
|
|
(let [(enhanced-2 (enhance image enhancer 2))]
|
|
(printf "part 1:~% Lit pixels after enhancing twice: ~a~%"
|
|
(matrix-sum enhanced-2))
|
|
(let [(enhanced-50 (enhance enhanced-2 enhancer 48))]
|
|
(printf "part 2:~% Lit pixels after enhancing fifty times: ~a~%"
|
|
(matrix-sum enhanced-50)))))))
|
|
|