diff options
| -rw-r--r-- | 04.lua | 78 | ||||
| -rw-r--r-- | day04.scm | 63 | ||||
| -rwxr-xr-x[-rw-r--r--] | main.scm | 5 |
3 files changed, 145 insertions, 1 deletions
@@ -0,0 +1,78 @@ +local input = {} + +for line in io.lines() do + local row = {} + for i = 1,#line do + -- X,M,A,S --> 1,2,3,4 + row[i] = string.find('XMAS', string.sub(line, i, i)) or 0 + end + table.insert(input, row) +end + +function compute_bounds (dx, size) + return math.max(0, -3*dx)+1, math.min(size, size-3*dx) +end + +function input:_has_xmas (i, j, di, dj) + for x = 0,3 do + if self[i+x*di][j+x*dj] ~= x+1 then + return false + end + end + return true +end + +function input:part1 () + local m = #self + local n = 0 + if m ~= 0 then n = #self[1] end + local sum = 0 + + for di = -1,1 do + local istart, iend = compute_bounds(di, m) + for dj = -1,1 do + if di ~= 0 or dj ~= 0 then + local jstart, jend = compute_bounds(dj, n) + for i = istart,iend do + for j = jstart,jend do + if self:_has_xmas(i, j, di, dj) then + sum = sum + 1 + end + end + end + end + end + end + print(sum) +end + +function input:_has_x_mas (i, j) + if self[i][j] ~= 3 then return false end + local nm = 0 + for ci = i-1,i+1,2 do + for cj = j-1,j+1,2 do + if self[ci][cj] == 2 then + nm = nm + 1 + if nm > 2 then return false end + elseif self[ci][cj] ~= 4 then + return false + end + end + end + return nm == 2 and self[i-1][j-1] ~= self[i+1][j+1] +end + +function input:part2 () + local m = #self + local n = 0 + if m ~= 0 then n = #self[1] end + local sum = 0 + for i = 2,m-1 do + for j = 2,n-1 do + if self:_has_x_mas(i, j) then sum = sum + 1 end + end + end + print(sum) +end + +return input diff --git a/day04.scm b/day04.scm new file mode 100644 index 0000000..a65a300 --- /dev/null +++ b/day04.scm @@ -0,0 +1,63 @@ +(define-module (day04) + #:use-module (ice-9 rdelim) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-41)) + +(define* (read-input #:optional (port (current-input-port))) + (define (read-lines acc) + (define line (read-line port)) + (if (and (not (eof-object? line)) (> (string-length line) 0)) + (read-lines (cons line acc)) + acc)) + (define strings (reverse! (read-lines '()))) + (define string->char-codes (compose (cut map char->integer <>) string->list)) + (list->typed-array 'u8 2 (map string->char-codes strings))) + +(define xmas (map char->integer (string->list "XMAS"))) + +(define (start-word? arr i j di dj) + (let loop ((i i) (j j) (lst xmas)) + (or (null-list? lst) + (and (= (array-ref arr i j) (first lst)) + (loop (+ i di) (+ j dj) (cdr lst)))))) + +(define (count-xmas arr) + (define-values (m n) (apply values (array-dimensions arr))) + (define (compute-range dx size) + (stream-range (if (< dx 0) (* -3 dx) 0) + (if (> dx 0) (- size (* 3 dx)) size))) + (define (count-dir di dj) + (define (count-row i) + (stream-length (stream-filter (cut start-word? arr i <> di dj) + (compute-range dj n)))) + (stream-fold + 0 (stream-map count-row (compute-range di m)))) + (stream-fold + 0 + (stream-map (cut apply count-dir <>) + (list->stream '((-1 -1) (-1 0) (-1 1) (0 -1) (0 1) + (1 -1) (1 0) (1 1)))))) + +(define (is-x-mas? arr i j) + (and (= (array-ref arr i j) (char->integer #\A)) + (let loop ((nm 0) (di '(1 1 -1 -1)) (dj '(1 -1 1 -1))) + (if (null-list? di) + (= nm 2) + (let ((cur (array-ref arr (+ i (car di)) (+ j (car dj))))) + (cond ((= cur (char->integer #\M)) + (and (< nm 2) (loop (+ nm 1) (cdr di) (cdr dj)))) + ((= cur (char->integer #\S)) + (loop nm (cdr di) (cdr dj))) + (else #f))))) + (not (= (array-ref arr (- i 1) (- j 1)) + (array-ref arr (+ i 1) (+ j 1)))))) + +(define (count-x-mas arr) + (define-values (m n) (apply values (array-dimensions arr))) + (define (count-row i) + (stream-length (stream-filter (cut is-x-mas? arr i <>) + (stream-range 1 (- n 1))))) + (stream-fold + 0 (stream-map count-row (stream-range 1 (- m 1))))) + +(define part1 (compose count-xmas read-input)) + +(define part2 (compose count-x-mas read-input)) @@ -1,9 +1,12 @@ +#!/usr/bin/env guile +!# + (use-modules (ice-9 format) (ice-9 regex)) (define args (program-arguments)) (unless (<= 2 (length args) 3) - (error (format #f "Syntax: ~a <DAY><a|b> [INFILE]\n")) + (error (format #f "Syntax: ~a <DAY><a|b> [INFILE]\n" (car args))) (exit 1)) (define mtch (string-match "^([0-9]+)(a|b)$" (list-ref args 1))) |
