dependencies
| (this space intentionally left almost blank) | |||
(ns advent.core) | ||||
I don't do a whole lot. | (defn foo [x] (println x "Hello, World!")) | |||
(ns advent.day01) | ||||
--- Day 1: Not Quite Lisp --- | ||||
Santa was hoping for a white Christmas, but his weather machine's "snow" function is powered by stars, and he's fresh out! To save Christmas, he needs you to collect fifty stars by December 25th. | ||||
Collect stars by helping Santa solve puzzles. Two puzzles will be made available on each day in the advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck! | ||||
Here's an easy puzzle to warm you up. | ||||
Santa is trying to deliver presents in a large apartment building, but he can't find the right floor - the directions he got are a little confusing. He starts on the ground floor (floor 0) and then follows the instructions one character at a time. | ||||
An opening parenthesis, (, means he should go up one floor, and a closing parenthesis, ), means he should go down one floor. | ||||
The apartment building is very tall, and the basement is very deep; he will never find the top or bottom floors. | ||||
For example: | ||||
| ||||
To what floor do the instructions take Santa? | ||||
input file save to resource/day01.txt | (def data (slurp (clojure.java.io/resource "day01.txt"))) | |||
count the result | (defn solve-part1 [input]
(reduce + (map { \( 1 \) -1 } input))) | |||
(solve-part1 data) | ||||
--- Part Two --- | ||||
Now, given the same instructions, find the position of the first character that causes him to enter the basement (floor -1). The first character in the instructions has position 1, the second character has position 2, and so on. | ||||
For example: | ||||
) causes him to enter the basement at character position 1. ()()) causes him to enter the basement at character position 5. | ||||
What is the position of the character that causes Santa to first enter the basement? | ||||
(defn solve-part2 [input]
(let [data (map {\( 1\) -1} input)]
(loop [i 0 sum1 0]
(let [sum (+ sum1 (nth data i))]
(if (= -1 sum)
(inc i) ; array start in index 0, we add to +1
(recur (inc i) sum)))))) | ||||
(solve-part2 data) | ||||
(ns advent.day02) | ||||
--- Day 2: I Was Told There Would Be No Math --- | ||||
The elves are running low on wrapping paper, and so they need to submit an order for more. They have a list of the dimensions (length l, width w, and height h) of each present, and only want to order exactly as much as they need. | ||||
Fortunately, every present is a box (a perfect right rectangular prism), which makes calculating the required wrapping paper for each gift a little easier: find the surface area of the box, which is 2lw + 2wh + 2hl. The elves also need a little extra paper for each present: the area of the smallest side. | ||||
For example: | ||||
| ||||
All numbers in the elves' list are in feet. How many total square feet of wrapping paper should they order? | ||||
input file save to resource/day02.txt | (def data (slurp (clojure.java.io/resource "day02.txt"))) | |||
solve 1 problem | (defn solve-1 [input]
(let [[l w h] (map #(Integer/parseInt %)
(clojure.string/split input #"x"))
k (min (* l w) (* w h) (* h l))]
(+ (* 2 l w) (* 2 w h) (* 2 h l) k))) | |||
solve all problem, problem must separate by '\n' | (defn solve-part1 [input] (->> (map solve-1 (clojure.string/split input #"\n")) (reduce +))) | |||
(solve-part1 data) | ||||
--- Part Two --- | ||||
The elves are also running low on ribbon. Ribbon is all the same width, so they only have to worry about the length they need to order, which they would again like to be exact. | ||||
The ribbon required to wrap a present is the shortest distance around its sides, or the smallest perimeter of any one face. Each present also requires a bow made out of ribbon as well; the feet of ribbon required for the perfect bow is equal to the cubic feet of volume of the present. Don't ask how they tie the bow, though; they'll never tell. | ||||
For example: | ||||
A present with dimensions 2x3x4 requires 2+2+3+3 = 10 feet of ribbon to wrap the present plus 234 = 24 feet of ribbon for the bow, for a total of 34 feet. A present with dimensions 1x1x10 requires 1+1+1+1 = 4 feet of ribbon to wrap the present plus 1110 = 10 feet of ribbon for the bow, for a total of 14 feet. | ||||
How many total feet of ribbon should they order? | ||||
(defn solve-2 [input]
(let [[l w h] (map #(Integer/parseInt %)
(clojure.string/split input #"x"))
[m1 m2] (sort [l w h])]
(+ (+ m1 m1 m2 m2) (* l w h)))) | ||||
(defn solve-part2 [input]
(->> (map solve-2 (clojure.string/split input #"\n"))
(reduce +))) | ||||
(solve-part2 data) | ||||
(ns advent.day03) | ||||
--- Day 3: Perfectly Spherical Houses in a Vacuum --- | ||||
Santa is delivering presents to an infinite two-dimensional grid of houses. | ||||
He begins by delivering a present to the house at his starting location, and then an elf at the North Pole calls him via radio and tells him where to move next. Moves are always exactly one house to the north (^), south (v), east (>), or west (<). After each move, he delivers another present to the house at his new location. | ||||
However, the elf back at the north pole has had a little too much eggnog, and so his directions are a little off, and Santa ends up visiting some houses more than once. How many houses receive at least one present? | ||||
For example: | ||||
| ||||
input file save to resource/day03.txt | (def data (slurp (clojure.java.io/resource "day03.txt"))) | |||
part1 solver | (defn solve-part1 [input]
(let [result
(->> (map {\> [1 0] \< [-1 0] \^ [0 1] \v [0 -1]} input)
(reductions (fn [x y] (map + x y)))
(into #{})
count)]
;; the Santa delivers presents start from 2 house
(if (= result 1)
2
result))) | |||
(solve-part1 data) | ||||
--- Part Two --- | ||||
The next year, to speed up the process, Santa creates a robot version of himself, Robo-Santa, to deliver presents with him. | ||||
Santa and Robo-Santa start at the same location (delivering two presents to the same starting house), then take turns moving based on instructions from the elf, who is eggnoggedly reading from the same script as the previous year. | ||||
This year, how many houses receive at least one present? | ||||
For example: | ||||
^v delivers presents to 3 houses, because Santa goes north, and then Robo-Santa goes south. ^>v< now delivers presents to 3 houses, and Santa and Robo-Santa end up back where they started. ^v^v^v^v^v now delivers presents to 11 houses, with Santa going one direction and Robo-Santa going the other. | ||||
(defn moves [input]
(->> (map {\> [1 0] \< [-1 0] \^ [0 1] \v [0 -1]} input)
(reductions (fn [x y] (map + x y))))) | ||||
part2 solve function | (defn solve-2 [input]
(let [santa (take-nth 2 input)
robot (take-nth 2 (drop 1 input))]
(->> (concat (moves santa) (moves robot))
(into #{})
(count)))) | |||
part2 solver | (defn solve-part2 [input]
(let [result (solve-2 input)]
;; since robot and ranta go to different diration, the result always odd
(if (odd? result)
result
(inc result)))) | |||
(solve-part2 data) | ||||
(ns advent.day04 (:import [java.security.MessageDigest])) | ||||
--- Day 4: The Ideal Stocking Stuffer --- | ||||
Santa needs help mining some AdventCoins (very similar to bitcoins) to use as gifts for all the economically forward-thinking little girls and boys. | ||||
To do this, he needs to find MD5 hashes which, in hexadecimal, start with at least five zeroes. The input to the MD5 hash is some secret key (your puzzle input, given below) followed by a number in decimal. To mine AdventCoins, you must find Santa the lowest positive number (no leading zeroes: 1, 2, 3, ...) that produces such a hash. | ||||
For example: | ||||
If your secret key is abcdef, the answer is 609043, because the MD5 hash of abcdef609043 starts with five zeroes (000001dbbfa...), and it is the lowest such number to do so. If your secret key is pqrstuv, the lowest number it combines with to make an MD5 hash starting with five zeroes is 1048970; that is, the MD5 hash of pqrstuv1048970 looks like 000006136ef.... | ||||
Your puzzle input is ckczppom. | ||||
the puzzle input | (def data "ckczppom") | |||
method to calculate md5 | (defn md5 [s]
(->> (.getBytes s)
(.digest (java.security.MessageDigest/getInstance "MD5"))
(map #(format "%02x" %))
(apply str))) | |||
(defn solve-part1 [input]
(loop [c 0]
(if (= "00000"
(-> (str input c)
(md5)
(subs 0 5)))
(str c)
(recur (inc c))))) | ||||
(solve-part1 data) | ||||
--- Part Two --- | ||||
Now find one that starts with six zeroes. | ||||
Your puzzle input is still ckczppom. | ||||
(defn solve-part2 [input]
(loop [c 0]
(if (= "000000"
(-> (str input c)
(md5)
(subs 0 6)))
(str c)
(recur (inc c))))) | ||||
(solve-part2 data) | ||||
(ns advent.day05) | ||||
--- Day 5: Doesn't He Have Intern-Elves For This? --- | ||||
Santa needs help figuring out which strings in his text file are naughty or nice. | ||||
A nice string is one with all of the following properties: | ||||
| ||||
For example: | ||||
| ||||
How many strings are nice? | ||||
input file save to resource/day05.txt | (def data (slurp (clojure.java.io/resource "day05.txt"))) | |||
It contains at least three vowels (aeiou only), like aei, xazegov, or aeiouaeiouaeiou. | (defn rule-1 [s]
(->> (seq s)
(filter #{\a \e \i \o \u})
(count)
(<= 3))) | |||
It contains at least one letter that appears twice in a row, like xx, abcdde (dd), or aabbccdd (aa, bb, cc, or dd). | (defn rule-2 [s] (boolean (re-find #"(.)\1" s))) | |||
It does not contain the strings ab, cd, pq, or xy, even if they are part of one of the other requirements. | (defn rule-3 [s]
(let [forbidden #{"ab" "cd" "pq" "xy"}]
(not (some #(.contains s %) forbidden)))) | |||
A nice string must fit rule-1, rule-2 and rule-3. | (defn nice-string? [s] (and (rule-1 s) (rule-2 s) (rule-3 s))) | |||
solve all problem, problem must separate by '\n' | (defn solve-part1 [input] (->> (map nice-string? (clojure.string/split input #"\n")) (filter true?) (count))) | |||
(solve-part1 data) | ||||
--- Part Two --- | ||||
Realizing the error of his ways, Santa has switched to a better model of determining whether a string is naughty or nice. None of the old rules apply, as they are all clearly ridiculous. | ||||
Now, a nice string is one with all of the following properties: | ||||
| ||||
For example: | ||||
| ||||
How many strings are nice under these new rules? | ||||
It contains a pair of any two letters that appears at least twice in the string without overlapping, like xyxy (xy) or aabcdefgaa (aa), but not like aaa (aa, but it overlaps). | (defn rule-1* [s] (boolean (re-find #"([a-z][a-z]).*\1" s))) | |||
It contains at least one letter which repeats with exactly one letter between them, like xyx, abcdefeghi (efe), or even aaa. | (defn rule-2* [s] (boolean (re-find #"([a-z]).\1" s))) | |||
A nice string must fit rule-1* and rule-2* | (defn nice-string?* [s] (and (rule-1* s) (rule-2* s))) | |||
solve all problem, problem must separate by '\n' | (defn solve-part2 [input] (->> (map nice-string?* (clojure.string/split input #"\n")) (filter true?) (count))) | |||
(solve-part2 data) | ||||