aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2022/03/solver.el
blob: 355ddf7c31c452b9cf38adce8f9ebb2d5103b00d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
;;; solver.el --- Day 03 -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2022 Óscar Nájera
;;
;; Author: Óscar Nájera <hi@oscarnajera.com>
;; Maintainer: Óscar Nájera <hi@oscarnajera.com>
;; Created: December 04, 2022
;; Modified: December 04, 2022
;;
;; This file is not part of GNU Emacs.
;;
;;; Commentary:
;;
;;  Day 03
;;
;;; Code:
(require 'subr-x)
(defsubst solver-recover-value (cross)
  (let ((result 0))
    (while (= 0 (logand cross 1))
      (setq cross (ash cross -1))
      (cl-incf result))
    result))

(ert-deftest test-recover ()
  (should (eq ?t (+ 64 (solver-recover-value (ash 1 (- ?t 64))))))
  (should (eq ?s (+ 64 (solver-recover-value (ash 1 (- ?s 64))))))
  (should (eq ?C (+ 64 (solver-recover-value (ash 1 (- ?C 64))))))) ;; small cap starts at a=97, but already took 64

(defsubst solver-to-priority (value)
  (if (< value 31) ;; It is a capital letter in range [1;26]
      (+ value 26)
    (- value 32)))

(defun solver-line-priority (str)
  (cl-assert (length> str 0))
  (let ((mid (/ (length str) 2))
        (left-pack 0) (right-pack 0))
    (cl-loop for l across (substring str 0 mid)
             for r across (substring str mid)
             do (progn
                  (setf left-pack (logior left-pack (ash 1 (- l 64)))) ;; ASCII letters start at 65=A
                  (setf right-pack  (logior right-pack(ash 1 (- r 64)))))
             for cross = (logand left-pack right-pack)
             when (< 0 cross)
             return (solver-to-priority (solver-recover-value cross)))))

(ert-deftest test-line-priority ()
  (should (= 16 (solver-line-priority  "vJrwpWtwJgWrhcsFMMfFFhFp")))
  (should (= 19 (solver-line-priority  "hMHLcmGLMLhHmsRMsSvsQSqrsrlJTTdV" )))
  (should (= 20 (solver-line-priority  "ttgJtRGJQctTZtZT"))))

(defsubst solver-badge (packs)
  (seq-reduce (lambda (acc item)
                (logior acc (ash 1 (- item 64))))
              packs 0))

(defun solver-badge-priority (group-packs)
  (thread-last  group-packs
                (split-string)
                (mapcar #'solver-badge)
                (apply #'logand)
                (solver-recover-value)
                (solver-to-priority)))

(defun solver (task lines)
  (with-temp-buffer
    (insert-file-contents "input")
    (goto-char (point-min))
    (cl-loop while (not (eobp))
             sum
             (funcall task
              (buffer-substring-no-properties (point)
                                              (line-end-position lines)))
             do (forward-line lines))))

(ert-deftest test-problems ()
  (should (= 8072 (solver #'solver-line-priority 1)))
  (should (= 2567 (solver #'solver-badge-priority 3))))