aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Marín Noguera <juan@mnpi.eu>2024-12-03 19:53:12 +0100
committerJuan Marín Noguera <juan@mnpi.eu>2024-12-03 19:53:42 +0100
commit1f393d95c1c8f6793826f05660f575fee2ebe987 (patch)
tree390bc29df28013da0628181b7f64d68ad4c1c91e
parent07691021e215b598d986a1709b3b6a6e0a1a031d (diff)
Started switch to Guile Scheme
I want to learn it more than I want to learn Lua right now. And I won't have time for both once the problems are more difficult.
-rw-r--r--03.lua65
-rw-r--r--day03.scm43
-rw-r--r--main.scm32
3 files changed, 140 insertions, 0 deletions
diff --git a/03.lua b/03.lua
new file mode 100644
index 0000000..0677236
--- /dev/null
+++ b/03.lua
@@ -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)