-
-
Save vanadium23/281186ff57e17980604fc1012bab4b1c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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