Skip to content

Instantly share code, notes, and snippets.

@vanadium23
Created December 4, 2024 08:27
Show Gist options
  • Save vanadium23/281186ff57e17980604fc1012bab4b1c to your computer and use it in GitHub Desktop.
Save vanadium23/281186ff57e17980604fc1012bab4b1c to your computer and use it in GitHub Desktop.
(ns advent-of-code.day04
(:require [clojure.string :as str]
[clojure.java.io :as io]))
(defn read-input [file]
(str/trim (slurp file)))
(defn to-lines
"Turn a blob or block into a seq of lines"
[input]
(str/split-lines input))
(defn parse-line
"Parse a line into a seq of strings"
[line]
(vec (str/split line #"")))
(def xmas (vec (str/split "XMAS" #"")))
(defn valid-pos?
[grid x y visited xmas_index]
(and (>= x 0) (< x (count grid))
(>= y 0) (< y (count (grid 0)))
(not (visited [x y]))
(= (get-in grid [x y]) (get xmas xmas_index))))
(defn dfs-grid-xmas
([grid start-x start-y direction]
(dfs-grid-xmas grid start-x start-y direction 0 [] #{} #{}))
([grid x y direction xmas_index path visited paths]
(cond
(= xmas_index (count xmas)) (if (empty? path) paths (conj paths path))
(or (> xmas_index (count xmas))
(not (valid-pos? grid x y visited xmas_index)))
paths
:else
(let [new-path (conj path [x y])
new-visited (conj visited [x y])]
(reduce
(fn [unique-paths [dx dy]]
(dfs-grid-xmas grid (+ x dx) (+ y dy) [dx dy] (inc xmas_index) new-path new-visited unique-paths))
paths
[direction])))))
(def directions [[-1 0] [1 0] [0 -1] [0 1] [1 1] [1 -1] [-1 1] [-1 -1]])
(defn count-xmas [grid x y]
(if (not (= (get-in grid [x y]) "X"))
0
(count (filter not-empty (map #(dfs-grid-xmas grid x y %) directions)))))
(defn generate-coords
"Generates all coordinates for a grid with given rows and cols."
[rows cols]
(for [x (range rows) y (range cols)]
[x y]))
(defn part1 [input]
(let [grid (vec (map parse-line (to-lines input)))
height (count grid)
width (count (first grid))]
(reduce + (map #(count-xmas grid (first %) (second %)) (generate-coords height width)))))
(defn count-x-mas [grid x y]
(if (not (= (get-in grid [x y]) "A"))
0
(if (or
(and (= (get-in grid [(dec x) (dec y)]) "M") (= (get-in grid [(dec x) (inc y)]) "M") (= (get-in grid [(inc x) (inc y)]) "S") (= (get-in grid [(inc x) (dec y)]) "S"))
(and (= (get-in grid [(dec x) (dec y)]) "S") (= (get-in grid [(dec x) (inc y)]) "M") (= (get-in grid [(inc x) (inc y)]) "M") (= (get-in grid [(inc x) (dec y)]) "S"))
(and (= (get-in grid [(dec x) (dec y)]) "S") (= (get-in grid [(dec x) (inc y)]) "S") (= (get-in grid [(inc x) (inc y)]) "M") (= (get-in grid [(inc x) (dec y)]) "M"))
(and (= (get-in grid [(dec x) (dec y)]) "M") (= (get-in grid [(dec x) (inc y)]) "S") (= (get-in grid [(inc x) (inc y)]) "S") (= (get-in grid [(inc x) (dec y)]) "M"))
)
1
0
)))
(defn part2 [input] (let [grid (vec (map parse-line (to-lines input)))
height (count grid)
width (count (first grid))] (reduce + (map #(count-x-mas grid (first %) (second %)) (generate-coords height width)))))
(def answer1example (part1 (read-input "04-example.txt")))
(assert (= answer1example 18) answer1example)
(def answer1 (part1 (read-input "04.txt")))
(assert (= answer1 2562) answer1)
(def answer2example (part2 (read-input "04-example.txt")))
(assert (= answer2example 9) answer2example)
(def answer2 (part2 (read-input "04.txt")))
(assert (= answer2 0) answer2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment