diff options
| -rw-r--r-- | 03.lua | 65 | ||||
| -rw-r--r-- | day03.scm | 43 | ||||
| -rw-r--r-- | main.scm | 32 |
3 files changed, 140 insertions, 0 deletions
@@ -0,0 +1,65 @@ +local function parse_instruction (x, y, dont) + if dont then return 'dont' + elseif x then return {'mul', tonumber(x), tonumber(y)} + else return 'do' + end +end + +local function input () + local line = '' + local start, next_mul, next_do = 1, 0, 0 + return function () + while true do + if next_mul and next_mul < start then + next_mul = string.find(line, 'mul', start) + end + if next_do and next_do < start then + next_do = string.find(line, 'do', start) + end + if next_mul and (not next_do or next_mul < next_do) then + start = next_mul + 1 + local x, y = string.match(line, '^mul%((%d+),(%d+)%)', next_mul) + if x then return 'mul', tonumber(x), tonumber(y) end + elseif next_do and (not next_mul or next_do < next_mul) then + start = next_do + 1 + if string.match(line, '^do%(%)', next_do) then + return 'do' + elseif string.match(line, "^don't%(%)", next_do) then + return 'dont' + end + elseif not next_mul and not next_do then + line = io.read '*l' + if not line then return end + start, next_mul, next_do = 1, 0, 0 + end + end + end +end + +local funcs = {reader = input()} + +function funcs:part1 () + local sum = 0 + for op, arg1, arg2 in self.reader do + if op == 'mul' then sum = sum + arg1 * arg2 end + end + print(sum) +end + +function funcs:part2() + local sum = 0 + local enabled = true + for op, arg1, arg2 in self.reader do + print(op, arg1, arg2) + if op == 'do' then + enabled = true + elseif op == 'dont' then + enabled = false + elseif op == 'mul' then + if enabled then sum = sum + arg1 * arg2 end + end + end + print(sum) +end + +return funcs diff --git a/day03.scm b/day03.scm new file mode 100644 index 0000000..983d8b5 --- /dev/null +++ b/day03.scm @@ -0,0 +1,43 @@ +(define-module (day03) + #:use-module (srfi srfi-41) + #:use-module (ice-9 match) + #:use-module (ice-9 rdelim) + #:use-module (ice-9 regex) + #:export (part1 part2)) + +(define mul-regexp (make-regexp "mul\\(([0-9]+),([0-9]+)\\)|do\\(\\)|(don't\\(\\))")) + +(define (parse-instruction match) + (cond ((match:start match 3) 'dont) + ((match:start match 1) (list 'mul + (string->number (match:substring match 1)) + (string->number (match:substring match 2)))) + (else 'do))) + +(define* (input-instructions #:optional (port (current-input-port))) + (stream-let loop ((line (read-line port)) (start 0)) + (if (eof-object? line) + stream-null + (let ((mch (regexp-exec mul-regexp line start))) + (if mch + (stream-cons (parse-instruction mch) + (loop line (match:end mch))) + (loop (read-line port) 0)))))) + +(define (mul-op? x) + (and (pair? x) (eq? 'mul (car x)))) + +(define* (part1 #:optional (port (current-input-port))) + (stream-fold + 0 + (stream-map (lambda (op) (apply * (cdr op))) + (stream-filter mul-op? (input-instructions port))))) + +(define* (part2 #:optional (port (current-input-port))) + (let ((sum 0) (on? #t)) + (stream-for-each + (match-lambda + ('do (set! on? #t)) + ('dont (set! on? #f)) + (('mul x y) (when on? (set! sum (+ sum (* x y)))))) + (input-instructions port)) + sum)) diff --git a/main.scm b/main.scm new file mode 100644 index 0000000..bcbadda --- /dev/null +++ b/main.scm @@ -0,0 +1,32 @@ +(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")) + (exit 1)) + +(define mtch (string-match "^([0-9]+)(a|b)$" (list-ref args 1))) + +(unless mtch + (error (format #f "Expected day and part (like \"03a\" or \"02b\"), got: ~a" + (list-ref args 1)))) + +(define day (format #f "~2,'0d" (string->number (match:substring mtch 1)))) +(define part (if (string= (match:substring mtch 2) "a") 'part1 'part2)) + +(set! %load-path (cons "." %load-path)) + +(define day-module + (resolve-module (list (string->symbol (string-append "day" day))))) +(define func (module-ref day-module part)) + +(define input-file + (cond ((= (length args) 2) (string-append day ".in")) + ((string= (list-ref args 2) "-") #f) + (else (list-ref args 2)))) + +(display (if input-file + (call-with-input-file input-file func) + (func (current-input-port)))) +(newline) |
