summaryrefslogtreecommitdiff
path: root/aoc_2022
diff options
context:
space:
mode:
authorElizabeth Hunt <elizabeth.hunt@simponic.xyz>2023-11-30 22:46:45 -0700
committerElizabeth Hunt <elizabeth.hunt@simponic.xyz>2023-11-30 22:46:45 -0700
commit3d57434c04a669610d5f15bd2a7713e6928cdef7 (patch)
treea0f1f04a335bbc808369d6492f4fee2ff06a0bdb /aoc_2022
parent59966ade163a39fc03f07a9d905e0bd87a98d60c (diff)
downloadaoc-3d57434c04a669610d5f15bd2a7713e6928cdef7.tar.gz
aoc-3d57434c04a669610d5f15bd2a7713e6928cdef7.zip
add aoc2023
Diffstat (limited to 'aoc_2022')
-rw-r--r--aoc_2022/README.md32
-rw-r--r--aoc_2022/day-00/.gitkeep0
-rwxr-xr-xaoc_2022/day-00/sol.sh40
-rw-r--r--aoc_2022/day-01/.gitkeep0
-rw-r--r--aoc_2022/day-01/sol.c74
-rw-r--r--aoc_2022/day-02/.gitkeep0
-rw-r--r--aoc_2022/day-02/sol.clj34
-rw-r--r--aoc_2022/day-03/.gitkeep0
-rw-r--r--aoc_2022/day-03/sol.lisp33
-rw-r--r--aoc_2022/day-04/.gitkeep0
-rwxr-xr-xaoc_2022/day-04/a.outbin0 -> 92448 bytes
-rw-r--r--aoc_2022/day-04/sol.cpp103
-rw-r--r--aoc_2022/day-05/.gitkeep0
-rw-r--r--aoc_2022/day-05/sol.exs28
-rw-r--r--aoc_2022/day-06/.gitkeep0
-rw-r--r--aoc_2022/day-06/package.json3
-rw-r--r--aoc_2022/day-06/sol.js115
-rw-r--r--aoc_2022/day-07/.gitkeep0
-rw-r--r--aoc_2022/day-07/sol.hs114
-rw-r--r--aoc_2022/day-08/.gitkeep0
-rw-r--r--aoc_2022/day-09/.gitkeep0
-rw-r--r--aoc_2022/day-10/.gitkeep0
-rw-r--r--aoc_2022/day-11/.gitkeep0
-rw-r--r--aoc_2022/day-11/sol.py67
-rw-r--r--aoc_2022/day-12/.gitignore3
-rw-r--r--aoc_2022/day-12/.gitkeep0
-rw-r--r--aoc_2022/day-12/package-lock.json46
-rw-r--r--aoc_2022/day-12/package.json9
-rw-r--r--aoc_2022/day-12/sol.ts59
-rw-r--r--aoc_2022/day-12/tsconfig.json103
-rw-r--r--aoc_2022/day-13/.gitkeep0
-rw-r--r--aoc_2022/day-13/sol.java147
-rw-r--r--aoc_2022/day-14/.gitkeep0
-rw-r--r--aoc_2022/day-15/.gitkeep0
-rw-r--r--aoc_2022/day-16/.gitkeep0
-rw-r--r--aoc_2022/day-17/.gitkeep0
-rw-r--r--aoc_2022/day-18/.gitkeep0
-rw-r--r--aoc_2022/day-19/.gitkeep0
-rw-r--r--aoc_2022/day-20/.gitkeep0
-rw-r--r--aoc_2022/day-21/.gitkeep0
-rw-r--r--aoc_2022/day-22/.gitkeep0
-rw-r--r--aoc_2022/day-23/.gitkeep0
-rw-r--r--aoc_2022/day-24/.gitkeep0
43 files changed, 1010 insertions, 0 deletions
diff --git a/aoc_2022/README.md b/aoc_2022/README.md
new file mode 100644
index 0000000..5ce862f
--- /dev/null
+++ b/aoc_2022/README.md
@@ -0,0 +1,32 @@
+# AOC 2022
+
+## Goal Languages
+
+- [x] BASH
+ - [Day 0](./day-00)
+- [x] C
+ - [Day 1](./day-01)
+- [x] Clojure
+ - [Day 2](./day-02)
+- [x] Common LISP
+ - [Day 3](./day-03)
+- [x] C++
+ - [Day 4](./day-04)
+- [] Dart
+- [x] Elixir
+ - [Day 5](./day-05)
+- [] Emacs Lisp
+- [x] Haskell
+ - [Day 7](./day-07)
+- [x] Java
+ - [Day 13](./day-13)
+- [x] JavaScript
+ - [Day 6](./day-06)
+- [] Kotlin
+- [] PHP
+- [x] Python
+ - [Day 11](./day-11)
+- [] Ruby
+- [x] TypeScript
+ - [Day 12](./day-12)
+
diff --git a/aoc_2022/day-00/.gitkeep b/aoc_2022/day-00/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-00/.gitkeep
diff --git a/aoc_2022/day-00/sol.sh b/aoc_2022/day-00/sol.sh
new file mode 100755
index 0000000..441efb2
--- /dev/null
+++ b/aoc_2022/day-00/sol.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# USAGE: ./sol.sh (n: top elves)
+
+NUM_ELVES=${1:-3}
+
+declare -a ELVES=()
+for (( i = 0; i<$NUM_ELVES; i++))
+do
+ ELVES+=(0)
+done
+
+
+add_to_elves () {
+ local max=$1
+ for (( i = 0; i<${NUM_ELVES}; i++));
+ do
+ local tmp="${ELVES[$i]}";
+ if [[ $max -ge $tmp ]];
+ then
+ ELVES[$i]=$max
+ max=$tmp
+ fi
+ done
+}
+
+CURRENT_ELF=0
+while read -r line
+do
+ if [[ -z "$line" ]];
+ then
+ add_to_elves $CURRENT_ELF
+ CURRENT_ELF=0
+ else
+ CURRENT_ELF=$((CURRENT_ELF+line))
+ fi
+done < input
+
+echo "MAX ELF = ${ELVES[0]}"
+echo "sum(TOP $NUM_ELVES ELVES) = $(printf "%s\n" $(echo "${ELVES[*]}") | paste -sd+ - | bc)"
diff --git a/aoc_2022/day-01/.gitkeep b/aoc_2022/day-01/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-01/.gitkeep
diff --git a/aoc_2022/day-01/sol.c b/aoc_2022/day-01/sol.c
new file mode 100644
index 0000000..612692a
--- /dev/null
+++ b/aoc_2022/day-01/sol.c
@@ -0,0 +1,74 @@
+#include <stdio.h>
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+/*
+ USAGE: ./sol <inputfile>
+*/
+
+int get_my_score(char elf, char me)
+{
+ int elf_choice = (int)(elf - 'A') + 1;
+ int my_choice = (int)(me - 'X') + 1;
+ int i_won = 0;
+ if (elf_choice == my_choice)
+ return my_choice + 3;
+
+ switch (elf_choice + my_choice)
+ {
+ case 3:
+ i_won = (elf_choice == 1);
+ break;
+ case 4:
+ i_won = (elf_choice == 3);
+ break;
+ case 5:
+ i_won = (elf_choice == 2);
+ break;
+ }
+
+ return my_choice + i_won * 6;
+}
+
+const int wins[3] = {2, 3, 1};
+const int loss[3] = {3, 1, 2};
+
+int get_my_score_2(char elf, char me)
+{
+ int elf_choice = (int)(elf - 'A') + 1;
+ int outcome = (int)(me - 'X') + 1;
+
+ if (outcome == 2)
+ return elf_choice + 3;
+
+ if (outcome == 1)
+ return loss[elf_choice - 1];
+ return 6 + wins[elf_choice - 1];
+}
+
+int main(int argc, char *argv[])
+{
+ char *fileName = argv[1];
+
+ FILE *file = fopen(fileName, "r");
+ char line[256];
+ char elf, me;
+
+ int score1 = 0;
+ int score2 = 0;
+ while (1)
+ {
+ int i = fscanf(file, "%c %c\n", &elf, &me);
+ if (i == EOF)
+ break;
+ score1 += get_my_score(elf, me);
+ score2 += get_my_score_2(elf, me);
+ }
+
+ printf("Score one: %d\n", score1);
+ printf("Score two: %d\n", score2);
+
+ fclose(file);
+ return 0;
+}
diff --git a/aoc_2022/day-02/.gitkeep b/aoc_2022/day-02/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-02/.gitkeep
diff --git a/aoc_2022/day-02/sol.clj b/aoc_2022/day-02/sol.clj
new file mode 100644
index 0000000..99783cc
--- /dev/null
+++ b/aoc_2022/day-02/sol.clj
@@ -0,0 +1,34 @@
+(require '[clojure.java.io])
+
+(defn find-recurring-characters [strs]
+ (reduce (fn [a x]
+ (into #{} (filter #(contains? a %) x)))
+ (into #{} (first strs))
+ strs))
+
+(defn get-priority [c]
+ (if (>= c 97)
+ (- c 96)
+ (- c 38)))
+
+(defn obtain-total-priorities [rucksacks]
+ (reduce + (map (fn [line]
+ (let [half (/ (count line) 2)]
+ (get-priority (int
+ (first (find-recurring-characters
+ (list (subs line 0 half)
+ (subs line half))))))))
+ rucksacks)))
+
+(defn obtain-total-priorities-2 [rucksacks]
+ (reduce + (map (fn [lines]
+ (get-priority (int (first (find-recurring-characters lines)))))
+ (partition 3 rucksacks))))
+
+(defn main []
+ (with-open [rdr (clojure.java.io/reader "input")]
+ (println (obtain-total-priorities (line-seq rdr))))
+ (with-open [rdr (clojure.java.io/reader "input")]
+ (println (obtain-total-priorities-2 (line-seq rdr))))
+ (System/exit 0))
+(main) \ No newline at end of file
diff --git a/aoc_2022/day-03/.gitkeep b/aoc_2022/day-03/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-03/.gitkeep
diff --git a/aoc_2022/day-03/sol.lisp b/aoc_2022/day-03/sol.lisp
new file mode 100644
index 0000000..7f9ba90
--- /dev/null
+++ b/aoc_2022/day-03/sol.lisp
@@ -0,0 +1,33 @@
+(ql:quickload "cl-ppcre")
+
+(defun get-ranges (line)
+ (ppcre:register-groups-bind ((#'parse-integer first second third fourth))
+ ("(\\d+)-(\\d+),(\\d+)-(\\d+)" line :sharedp t)
+ `((,first ,second) (,third ,fourth))))
+
+(defun ranges-may-subset-of-one (a b)
+ (member-if
+ (lambda (r)
+ (and
+ (>= (caar r) (caadr r))
+ (<= (cadar r) (cadadr r))))
+ `((,a ,b) (,b ,a))))
+
+(defun range-is-contained-at-all (a b)
+ (and
+ (<= (car a) (cadr b))
+ (>= (cadr a) (car b))))
+
+(defun main ()
+ (let ((lines (uiop:read-file-lines "input")))
+ (print
+ (mapcar (lambda (f)
+ (reduce (lambda (a x)
+ (if (apply f (get-ranges x))
+ (1+ a)
+ a))
+ lines
+ :initial-value 0))
+ '(range-is-contained range-may-be-subset-of-one)))))
+
+(main)
diff --git a/aoc_2022/day-04/.gitkeep b/aoc_2022/day-04/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-04/.gitkeep
diff --git a/aoc_2022/day-04/a.out b/aoc_2022/day-04/a.out
new file mode 100755
index 0000000..d31e159
--- /dev/null
+++ b/aoc_2022/day-04/a.out
Binary files differ
diff --git a/aoc_2022/day-04/sol.cpp b/aoc_2022/day-04/sol.cpp
new file mode 100644
index 0000000..d7847da
--- /dev/null
+++ b/aoc_2022/day-04/sol.cpp
@@ -0,0 +1,103 @@
+#include <tuple>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <sstream>
+#include <stack>
+#include <cmath>
+#include <array>
+#include <algorithm>
+#include <cstdint>
+#include <vector>
+
+using stack_type = std::stack<char>;
+
+enum PROBLEM
+{
+ PROBLEM_1 = 1,
+ PROBLEM_2 = 2
+};
+
+std::tuple<std::vector<stack_type>, int> build_stacks(std::vector<std::string> &lines)
+{
+ int num_stacks = std::ceil(lines[0].size() / 4.0);
+
+ std::vector<stack_type> stacks(num_stacks);
+
+ std::vector<int> stack_positions(num_stacks, 0);
+ int lines_of_stacks = 0;
+ for (std::string line : lines)
+ {
+ char l = '1';
+ for (int i = 0; i < line.size(); ++i)
+ if (line[i] == l)
+ {
+ stack_positions[l - '1'] = i;
+ l++;
+ }
+ if (l == num_stacks + '1')
+ break;
+ lines_of_stacks++;
+ }
+
+ for (int i = lines_of_stacks - 1; i >= 0; i--)
+ for (int j = 0; j < num_stacks; ++j)
+ if (lines[i][stack_positions[j]] != ' ')
+ stacks[j].push(lines[i][stack_positions[j]]);
+
+ return std::make_tuple(stacks, lines_of_stacks);
+}
+
+std::string solve(std::vector<stack_type> &stacks, std::vector<std::string> &lines, int start_from, PROBLEM problem)
+{
+ stack_type curr;
+ for (auto line = lines.begin() + start_from; line != lines.end(); ++line)
+ {
+ std::istringstream iss(*line);
+ std::string word;
+ int from = 0, to = 0, amount = 0;
+
+ while (iss >> word >> amount >> word >> from >> word >> to)
+ ;
+
+ if (problem == PROBLEM_1)
+ for (int i = 0; i < amount; ++i)
+ {
+ stacks[to - 1].push(stacks[from - 1].top());
+ stacks[from - 1].pop();
+ }
+ else
+ {
+ for (int i = 0; i < amount; ++i)
+ {
+ curr.push(stacks[from - 1].top());
+ stacks[from - 1].pop();
+ }
+ for (int i = 0; i < amount; ++i)
+ {
+ stacks[to - 1].push(curr.top());
+ curr.pop();
+ }
+ }
+ }
+
+ std::string result;
+ for (auto &stack : stacks)
+ result += stack.top();
+ return result;
+}
+
+int main()
+{
+ std::ifstream input("input");
+ std::vector<std::string> lines;
+ for (std::string line; std::getline(input, line);)
+ lines.push_back(line);
+
+ auto [stacks, start_from] = build_stacks(lines);
+ std::cout << "Solve 1: " << solve(stacks, lines, start_from + 1, PROBLEM_1) << std::endl;
+ auto [stacks2, start_from2] = build_stacks(lines);
+ std::cout << "Solve 2: " << solve(stacks2, lines, start_from2 + 1, PROBLEM_2) << std::endl;
+
+ return 0;
+}
diff --git a/aoc_2022/day-05/.gitkeep b/aoc_2022/day-05/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-05/.gitkeep
diff --git a/aoc_2022/day-05/sol.exs b/aoc_2022/day-05/sol.exs
new file mode 100644
index 0000000..e1dab2b
--- /dev/null
+++ b/aoc_2022/day-05/sol.exs
@@ -0,0 +1,28 @@
+defmodule Solution do
+ def solve(input, chunk) do
+ (String.split(input, "", trim: true)
+ |> Enum.chunk_every(chunk, 1, :discard)
+ |> Enum.map(fn window ->
+ Enum.reduce(window, %{}, fn char, acc ->
+ Map.put(acc, char, Map.get(acc, char, 0) + 1)
+ end)
+ end)
+ |> Enum.find_index(fn letter_counts ->
+ Enum.all?(letter_counts, fn {_key, value} ->
+ value == 1
+ end)
+ end)) + chunk
+ end
+
+ def main do
+ input = File.read!("input")
+
+ solve(input, 4)
+ |> IO.inspect()
+
+ solve(input, 14)
+ |> IO.inspect()
+ end
+end
+
+Solution.main()
diff --git a/aoc_2022/day-06/.gitkeep b/aoc_2022/day-06/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-06/.gitkeep
diff --git a/aoc_2022/day-06/package.json b/aoc_2022/day-06/package.json
new file mode 100644
index 0000000..3dbc1ca
--- /dev/null
+++ b/aoc_2022/day-06/package.json
@@ -0,0 +1,3 @@
+{
+ "type": "module"
+}
diff --git a/aoc_2022/day-06/sol.js b/aoc_2022/day-06/sol.js
new file mode 100644
index 0000000..28b7b0d
--- /dev/null
+++ b/aoc_2022/day-06/sol.js
@@ -0,0 +1,115 @@
+import input from "fs";
+
+class File {
+ constructor(name, size, parent) {
+ this.name = name;
+ this.fileSize = size;
+ this.parent = parent;
+ }
+
+ size() {
+ return this.fileSize;
+ }
+}
+
+class Directory {
+ constructor(name, parent) {
+ this.children = [];
+ this.name = name;
+ this.parent = parent;
+ }
+
+ add(child) {
+ this.children.push(child);
+ }
+
+ size() {
+ return this.children.reduce((acc, child) => acc + child.size(), 0);
+ }
+
+ searchDirectoresOfSizePredicate(sizeP) {
+ const dirs = [];
+ for (const child of this.children) {
+ if (child instanceof Directory) {
+ if (sizeP(child.size())) {
+ dirs.push(child);
+ }
+ dirs.push(...child.searchDirectoresOfSizePredicate(sizeP));
+ }
+ }
+ return dirs;
+ }
+}
+
+class OS {
+ constructor() {
+ this.root = new Directory("/", null);
+
+ this.current = this.root;
+ }
+
+ cd(path) {
+ if (path === "/") {
+ this.current = this.root;
+ } else if (path === ".." && this.current.parent) {
+ this.current = this.current.parent;
+ } else {
+ this.current = this.current.children.find((child) => child.name === path);
+ }
+ }
+
+ printFs() {
+ const print = (dir, depth) => {
+ for (const child of dir.children) {
+ console.log(" ".repeat(depth) + child.name);
+ if (child instanceof Directory) {
+ print(child, depth + 1);
+ }
+ }
+ };
+
+ print(this.root, 0);
+ }
+}
+
+const main = () => {
+ const os = new OS();
+ const lines = input.readFileSync("input", "utf8").split("\n");
+
+ let currentCommand = null;
+ for (const line of lines) {
+ if (line.startsWith("$")) {
+ const [command, path] = line.split(" ").splice(1);
+ if (command == "cd") os.cd(path);
+ currentCommand = command;
+ } else if (currentCommand == "ls") {
+ const [dirOrSize, name] = line.split(" ");
+ if (dirOrSize === "dir") {
+ const dir = new Directory(name, os.current);
+ os.current.add(dir);
+ } else {
+ const file = new File(name, parseInt(dirOrSize), os.current);
+ os.current.add(file);
+ }
+ }
+ }
+
+ //os.printFs();
+
+ console.log(
+ os.root
+ .searchDirectoresOfSizePredicate((size) => size <= 100000)
+ .reduce((a, x) => a + x.size(), 0)
+ );
+
+ const rootSize = os.root.size();
+ const freeSpace = 70000000 - rootSize;
+ console.log(
+ [...os.root.searchDirectoresOfSizePredicate(() => true), os.root]
+ .map((x) => x.size())
+ .filter((x) => freeSpace + x >= 30000000)
+ .reduce((a, x) => Math.min(a, x), Infinity)
+ );
+};
+
+main();
diff --git a/aoc_2022/day-07/.gitkeep b/aoc_2022/day-07/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-07/.gitkeep
diff --git a/aoc_2022/day-07/sol.hs b/aoc_2022/day-07/sol.hs
new file mode 100644
index 0000000..c6b8c35
--- /dev/null
+++ b/aoc_2022/day-07/sol.hs
@@ -0,0 +1,114 @@
+import Data.List (find, transpose)
+import qualified Data.Set as Set
+import qualified Data.Text as Text
+import qualified Data.Text.IO as Text
+
+countVisibleTrees ::
+ [[Int]] -> [Int] -> Int -> (Set.Set (Int, Int)) -> (Set.Set (Int, Int))
+countVisibleTrees [] _ _ seen = seen
+countVisibleTrees (row:rows) maxTrees depth seen =
+ countVisibleTrees
+ rows
+ (zipWith (\x y -> max x y) row maxTrees)
+ (depth + 1)
+ (foldl
+ (\acc x -> Set.insert x acc)
+ seen
+ (zipWith
+ (\i x ->
+ if x == 1
+ then (depth, i)
+ else (0, 0))
+ [0 ..]
+ (zipWith
+ (\x y ->
+ if x > y
+ then 1
+ else 0)
+ row
+ maxTrees)))
+
+treeScore :: [[Int]] -> (Int, Int) -> Int -> Int -> [Int]
+treeScore digits (x, y) width height =
+ let currentHeight = ((digits !! y) !! x)
+ in [ (case (find
+ (\x -> (digits !! y) !! x >= currentHeight)
+ [(x + 1) .. (width - 1)]) of
+ Just value -> (value - x)
+ Nothing -> (width - x - 1))
+ , (case (find
+ (\x -> (digits !! y) !! x >= currentHeight)
+ (reverse [0 .. (x - 1)])) of
+ Just value -> (x - value)
+ Nothing -> x)
+ , (case (find
+ (\y -> (digits !! y) !! x >= currentHeight)
+ (reverse [0 .. (y - 1)])) of
+ Just value -> (y - value)
+ Nothing -> y)
+ , (case (find
+ (\y -> (digits !! y) !! x >= currentHeight)
+ [(y + 1) .. (height - 1)]) of
+ Just value -> (value - y)
+ Nothing -> (height - y - 1))
+ ]
+
+getDigitsFromString :: String -> [Int]
+getDigitsFromString = map (read . (: ""))
+
+rotl :: [[Int]] -> [[Int]]
+rotl = reverse . transpose
+
+rotr :: [[Int]] -> [[Int]]
+rotr = transpose . reverse
+
+main = do
+ ls <- fmap Text.lines (Text.readFile "input")
+ let digits = map (getDigitsFromString . Text.unpack) ls
+ let height = length digits
+ let width = length (head digits)
+ let topDownSeen =
+ countVisibleTrees digits (take width (repeat (-1))) 0 Set.empty
+ let rightLeftSeen =
+ Set.map
+ (\x -> ((snd x), width - (fst x) - 1))
+ (countVisibleTrees
+ (rotl digits)
+ (take height (repeat (-1)))
+ 0
+ Set.empty)
+ let downTopSeen =
+ Set.map
+ (\x -> (height - (fst x) - 1, (snd x)))
+ (countVisibleTrees
+ (reverse digits)
+ (take width (repeat (-1)))
+ 0
+ Set.empty)
+ let leftRightSeen =
+ Set.map
+ (\x -> (height - (snd x) - 1, (fst x)))
+ (countVisibleTrees
+ (rotr digits)
+ (take height (repeat (-1)))
+ 0
+ Set.empty)
+ let allSeen =
+ (foldl
+ (\acc x -> Set.union acc x)
+ Set.empty
+ [topDownSeen, rightLeftSeen, downTopSeen, leftRightSeen])
+ print (Set.size allSeen)
+ print
+ (maximum
+ (map
+ (\y ->
+ maximum
+ (map
+ (\x ->
+ (foldl
+ (\acc x -> acc * x)
+ 1
+ (treeScore digits (x, y) width height)))
+ [0 .. (width - 1)]))
+ [0 .. (height - 1)]))
diff --git a/aoc_2022/day-08/.gitkeep b/aoc_2022/day-08/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-08/.gitkeep
diff --git a/aoc_2022/day-09/.gitkeep b/aoc_2022/day-09/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-09/.gitkeep
diff --git a/aoc_2022/day-10/.gitkeep b/aoc_2022/day-10/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-10/.gitkeep
diff --git a/aoc_2022/day-11/.gitkeep b/aoc_2022/day-11/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-11/.gitkeep
diff --git a/aoc_2022/day-11/sol.py b/aoc_2022/day-11/sol.py
new file mode 100644
index 0000000..9da8cec
--- /dev/null
+++ b/aoc_2022/day-11/sol.py
@@ -0,0 +1,67 @@
+
+def get_neighbors(grid, current):
+ neighbors = []
+ y, x = current
+ cur_height = ord(grid[y][x])
+ if (grid[y][x] == "S"):
+ cur_height = ord("a")
+ for i in range(-1, 2):
+ for j in range(-1, 2):
+ if i == 0 and j == 0 or (i != 0 and j != 0):
+ continue
+ if (y + i) < 0 or (y + i) >= len(grid):
+ continue
+ if (x + j) < 0 or (x + j) >= len(grid[y + i]):
+ continue
+ new_height = ord(grid[y + i][x + j])
+ if (grid[y + i][x + j] == "E"):
+ new_height = ord("z")
+ if abs(new_height - cur_height) <= 1 or new_height <= cur_height:
+ neighbors.append((y + i, x + j))
+ return neighbors
+
+def bfs(grid, start, end):
+ queue = []
+ queue.append(start)
+ visited = {}
+ visited[start] = 0
+ while queue:
+ current = queue.pop(0)
+ if current == end:
+ return visited[current]
+ for neighbor in get_neighbors(grid, current):
+ if neighbor not in visited:
+ queue.append(neighbor)
+ visited[neighbor] = visited[current] + 1
+ return False
+
+def main():
+ file = open("input", "r")
+ grid = file.readlines()
+ file.close()
+
+ start = (0, 0)
+ end = (0, 0)
+
+ for i in range(len(grid)):
+ for j in range(len(grid[i])):
+ if grid[i][j] == "S":
+ start = (i, j)
+ elif grid[i][j] == "E":
+ end = (i, j)
+
+ best = bfs(grid, start, end)
+ print(best)
+
+ for i in range(len(grid)):
+ for j in range(len(grid[i])):
+ if grid[i][j] == "a":
+ this_as_start = bfs(grid, (i, j), end)
+ if this_as_start and this_as_start < best:
+ best = this_as_start
+
+ print(best)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/aoc_2022/day-12/.gitignore b/aoc_2022/day-12/.gitignore
new file mode 100644
index 0000000..5bf19b0
--- /dev/null
+++ b/aoc_2022/day-12/.gitignore
@@ -0,0 +1,3 @@
+build/
+sol.js
+node_modules/
diff --git a/aoc_2022/day-12/.gitkeep b/aoc_2022/day-12/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-12/.gitkeep
diff --git a/aoc_2022/day-12/package-lock.json b/aoc_2022/day-12/package-lock.json
new file mode 100644
index 0000000..15123cd
--- /dev/null
+++ b/aoc_2022/day-12/package-lock.json
@@ -0,0 +1,46 @@
+{
+ "name": "day-12",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "devDependencies": {
+ "@types/node": "^18.11.14",
+ "typescript": "^4.9.4"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "18.11.14",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.14.tgz",
+ "integrity": "sha512-0KXV57tENYmmJMl+FekeW9V3O/rlcqGQQJ/hNh9r8pKIj304pskWuEd8fCyNT86g/TpO0gcOTiLzsHLEURFMIQ==",
+ "dev": true
+ },
+ "node_modules/typescript": {
+ "version": "4.9.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
+ "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ }
+ },
+ "dependencies": {
+ "@types/node": {
+ "version": "18.11.14",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.14.tgz",
+ "integrity": "sha512-0KXV57tENYmmJMl+FekeW9V3O/rlcqGQQJ/hNh9r8pKIj304pskWuEd8fCyNT86g/TpO0gcOTiLzsHLEURFMIQ==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "4.9.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
+ "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
+ "dev": true
+ }
+ }
+}
diff --git a/aoc_2022/day-12/package.json b/aoc_2022/day-12/package.json
new file mode 100644
index 0000000..cfc736a
--- /dev/null
+++ b/aoc_2022/day-12/package.json
@@ -0,0 +1,9 @@
+{
+ "devDependencies": {
+ "@types/node": "^18.11.14",
+ "typescript": "^4.9.4"
+ },
+ "scripts": {
+ "build": "tsc"
+ }
+}
diff --git a/aoc_2022/day-12/sol.ts b/aoc_2022/day-12/sol.ts
new file mode 100644
index 0000000..7143403
--- /dev/null
+++ b/aoc_2022/day-12/sol.ts
@@ -0,0 +1,59 @@
+import * as input from "fs";
+
+type NestedNumbers = Array<NestedNumbers | number>;
+
+const compare = (
+ a: NestedNumbers | number,
+ b: NestedNumbers | number
+): boolean => {
+ if (typeof a === typeof b && typeof b === "number") return a < b;
+ if (Array.isArray(a) && Array.isArray(b)) {
+ for (let i = 0; i < a.length; i++) {
+ if (i >= b.length) return false;
+ if (compare(a[i], b[i])) return true;
+ if (compare(b[i], a[i])) return false;
+ }
+ return compare(a.length, b.length);
+ }
+ return compare(Array.isArray(b) ? [a] : a, Array.isArray(a) ? [b] : b);
+};
+
+const main = (): void => {
+ const lines: NestedNumbers[] = input
+ .readFileSync("input", "utf-8")
+ .split("\n")
+ .filter((x) => x)
+ .map((x) => JSON.parse(x));
+
+ const pairs: [NestedNumbers, NestedNumbers][] = [];
+ for (let i = 0; i < lines.length; i += 2) {
+ const pair: [NestedNumbers, NestedNumbers] = [lines[i], lines[i + 1]];
+ pairs.push(pair);
+ }
+
+ console.log(
+ pairs.reduce((acc, [a, b], i) => acc + (compare(a, b) ? i + 1 : 0), 0)
+ );
+
+ lines.push([[2]]);
+ lines.push([[6]]);
+
+ const sorted = lines.sort((a, b) => {
+ if (compare(a, b)) return -1;
+ if (compare(b, a)) return 1;
+ return 0;
+ });
+
+ const isPacket = (num: number) => (x: NestedNumbers) =>
+ Array.isArray(x) &&
+ x.length === 1 &&
+ Array.isArray(x[0]) &&
+ x[0].length === 1 &&
+ x[0][0] === num;
+
+ console.log(
+ (sorted.findIndex(isPacket(6)) + 1) * (sorted.findIndex(isPacket(2)) + 1)
+ );
+};
+
+main();
diff --git a/aoc_2022/day-12/tsconfig.json b/aoc_2022/day-12/tsconfig.json
new file mode 100644
index 0000000..75dcaea
--- /dev/null
+++ b/aoc_2022/day-12/tsconfig.json
@@ -0,0 +1,103 @@
+{
+ "compilerOptions": {
+ /* Visit https://aka.ms/tsconfig to read more about this file */
+
+ /* Projects */
+ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
+ // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
+
+ /* Language and Environment */
+ "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+ // "jsx": "preserve", /* Specify what JSX code is generated. */
+ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
+ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+ // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
+ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
+
+ /* Modules */
+ "module": "commonjs", /* Specify what module code is generated. */
+ // "rootDir": "./", /* Specify the root folder within your source files. */
+ // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
+ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
+ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
+ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
+ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
+ // "types": [], /* Specify type package names to be included without being referenced in a source file. */
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
+ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
+ // "resolveJsonModule": true, /* Enable importing .json files. */
+ // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
+
+ /* JavaScript Support */
+ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
+ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+
+ /* Emit */
+ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
+ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+ // "outDir": "./", /* Specify an output folder for all emitted files. */
+ // "removeComments": true, /* Disable emitting comments. */
+ // "noEmit": true, /* Disable emitting files from a compilation. */
+ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
+ // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+ // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
+ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
+ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+ /* Interop Constraints */
+ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
+ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
+ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
+
+ /* Type Checking */
+ "strict": true, /* Enable all strict type-checking options. */
+ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
+ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
+ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
+ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
+ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
+ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
+ // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
+ // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
+
+ /* Completeness */
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
+ }
+}
diff --git a/aoc_2022/day-13/.gitkeep b/aoc_2022/day-13/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-13/.gitkeep
diff --git a/aoc_2022/day-13/sol.java b/aoc_2022/day-13/sol.java
new file mode 100644
index 0000000..7613dcd
--- /dev/null
+++ b/aoc_2022/day-13/sol.java
@@ -0,0 +1,147 @@
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Scanner;
+import java.awt.Point;
+import java.util.Set;
+
+public class sol {
+ enum PROBLEM {
+ PROBLEM_1, PROBLEM_2
+ }
+
+ class Grid {
+ private Set<Point> sand;
+ private Set<Point> filled;
+ private Point source;
+ private int maxYP2;
+
+ public Grid(Point source, ArrayList<ArrayList<Point>> paths) {
+ this.sand = new HashSet<Point>();
+ this.filled = new HashSet<Point>();
+ this.source = source;
+
+ for (ArrayList<Point> path : paths)
+ for (int i = 1; i < path.size(); i++) {
+ Point p1 = path.get(i - 1);
+ Point p2 = path.get(i);
+ for (int x = Math.min(p1.x, p2.x); x <= Math.max(p1.x, p2.x); x++)
+ for (int y = Math.min(p1.y, p2.y); y <= Math.max(p1.y, p2.y); y++)
+ this.filled.add(new Point(x, y));
+ }
+
+ maxYP2 = bottomRight().y + 1;
+ }
+
+ public boolean addSandGrain(PROBLEM problem) {
+ Point p = new Point(this.source.x, this.source.y);
+ while (true) {
+ if (this.filled.contains(p) || (problem == PROBLEM.PROBLEM_2 && p.y >= maxYP2)) {
+ if (problem == PROBLEM.PROBLEM_2 && p.x == this.source.x && p.y == this.source.y)
+ return false;
+
+ p.y--;
+ filled.add(p);
+ sand.add(p);
+ return true;
+ }
+
+ if (problem == PROBLEM.PROBLEM_1 && p.y >= bottomRight().y)
+ return false;
+
+ p.y++;
+ if (this.filled.contains(new Point(p.x, p.y))) {
+ if (!this.filled.contains(new Point(p.x - 1, p.y)))
+ p.x--;
+ else if (!this.filled.contains(new Point(p.x + 1, p.y)))
+ p.x++;
+ }
+ }
+ }
+
+ public Point topLeft() {
+ return new Point(
+ filled.stream().min((p1, p2) -> p1.x - p2.x).get().x,
+ filled.stream().min((p1, p2) -> p1.y - p2.y).get().y);
+ }
+
+ public Point bottomRight() {
+ return new Point(
+ filled.stream().max((p1, p2) -> p1.x - p2.x).get().x,
+ filled.stream().max((p1, p2) -> p1.y - p2.y).get().y);
+ }
+
+ public void print() {
+ Point topLeft = topLeft();
+ Point bottomRight = bottomRight();
+
+ Point curr = new Point(topLeft.x, topLeft.y);
+ for (; curr.y <= bottomRight.y; curr.y++) {
+ for (; curr.x <= bottomRight.x; curr.x++) {
+ if (sand.contains(curr))
+ System.out.print("o");
+ else if (filled.contains(curr))
+ System.out.print("#");
+ else
+ System.out.print(".");
+ }
+ curr.x = topLeft.x;
+ System.out.println();
+ }
+ }
+ }
+
+ public static ArrayList<ArrayList<Point>> parsePaths(ArrayList<String> inputList) {
+ ArrayList<ArrayList<Point>> paths = new ArrayList<ArrayList<Point>>();
+ for (String line : inputList) {
+ ArrayList<Point> path = new ArrayList<Point>();
+
+ String[] points = line.split(" -> ");
+ for (String point : points) {
+ String[] coords = point.split(",");
+ path.add(new Point(Integer.parseInt(coords[0]), Integer.parseInt(coords[1])));
+ }
+
+ paths.add(path);
+ }
+ return paths;
+ }
+
+ public static ArrayList<String> getInputLines(String file) {
+ ArrayList<String> inputList = new ArrayList<String>();
+
+ try {
+ File input = new File(file);
+ Scanner sc = new Scanner(input);
+
+ while (sc.hasNextLine())
+ inputList.add(sc.nextLine());
+
+ sc.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+
+ return inputList;
+ }
+
+ public static void main(String[] args) {
+ ArrayList<ArrayList<Point>> paths = parsePaths(getInputLines("input"));
+
+ sol s = new sol();
+ Grid gridP1 = s.new Grid(new Point(500, 0), paths);
+ int i = 0;
+ for (; gridP1.addSandGrain(PROBLEM.PROBLEM_1); i++) {
+ // gridP1.print();
+ }
+ System.out.println(i);
+
+ Grid gridP2 = s.new Grid(new Point(500, 0), paths);
+ i = 0;
+ for (; gridP2.addSandGrain(PROBLEM.PROBLEM_2); i++) {
+ // gridP2.print();
+ }
+ System.out.println(i);
+ }
+} \ No newline at end of file
diff --git a/aoc_2022/day-14/.gitkeep b/aoc_2022/day-14/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-14/.gitkeep
diff --git a/aoc_2022/day-15/.gitkeep b/aoc_2022/day-15/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-15/.gitkeep
diff --git a/aoc_2022/day-16/.gitkeep b/aoc_2022/day-16/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-16/.gitkeep
diff --git a/aoc_2022/day-17/.gitkeep b/aoc_2022/day-17/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-17/.gitkeep
diff --git a/aoc_2022/day-18/.gitkeep b/aoc_2022/day-18/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-18/.gitkeep
diff --git a/aoc_2022/day-19/.gitkeep b/aoc_2022/day-19/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-19/.gitkeep
diff --git a/aoc_2022/day-20/.gitkeep b/aoc_2022/day-20/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-20/.gitkeep
diff --git a/aoc_2022/day-21/.gitkeep b/aoc_2022/day-21/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-21/.gitkeep
diff --git a/aoc_2022/day-22/.gitkeep b/aoc_2022/day-22/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-22/.gitkeep
diff --git a/aoc_2022/day-23/.gitkeep b/aoc_2022/day-23/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-23/.gitkeep
diff --git a/aoc_2022/day-24/.gitkeep b/aoc_2022/day-24/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc_2022/day-24/.gitkeep