129 lines
3.8 KiB
Scheme
129 lines
3.8 KiB
Scheme
(import (srfi :43)) ; vector extensions
|
|
|
|
; get list of lines from a file
|
|
(define (get-lines file)
|
|
(let loop [(lines '())]
|
|
(if (eof-object? (peek-char file))
|
|
lines
|
|
(loop (cons (get-line file) lines)))))
|
|
|
|
; reads a numnber from input
|
|
; also consumes the next non-number character in the file!
|
|
(define (get-number file)
|
|
(let [(sign 1)]
|
|
(let loop [(index 0) (n 0)]
|
|
(let [(c (get-char file))]
|
|
(cond
|
|
[(char-numeric? c)
|
|
(loop (+ index 1) (+ (char->number c) (* n 10)))]
|
|
[(and (char=? c #\-)
|
|
(= index 0))
|
|
(set! sign -1)
|
|
(loop 1 n)]
|
|
[else (* sign n)])))))
|
|
|
|
; returns a list of numbers parsed from the first line of the file,
|
|
; separated by commas
|
|
(define (read-comma-separated-numbers file)
|
|
(let loop [(draws '()) (n 0)]
|
|
(let [(c (get-char file))]
|
|
(cond
|
|
[(char=? c #\,) (loop (cons n draws) 0)]
|
|
[(char-whitespace? c) (reverse (cons n draws))]
|
|
[else (loop draws (+ (* n 10) (char->number c)))]))))
|
|
|
|
; returns numbers 0 to 9 from ascii character
|
|
(define (char->number c)
|
|
(- (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 a matrix object of given dimensions full of zeroes
|
|
(define (filled-matrix width height filler)
|
|
(matrix-from-data
|
|
(do [(i 0 (+ i 1))
|
|
(v '() (cons (make-vector width filler) v))]
|
|
((>= i height) (list->vector v)) '())))
|
|
|
|
; 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 (update-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)))
|