├── .gitignore ├── Advent of Code ├── 2015 │ ├── 10 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 11 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 12 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 13 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 14 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 15 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 16 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 17 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 18 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 19 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 20 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 21 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 22 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 23 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 24 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 25 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 01 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 02 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 03 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 04 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 05 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 06 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 07 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 08 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 09 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── Project.toml │ ├── README.md │ └── src │ │ └── AdventOfCode2015.jl ├── 2016 │ ├── 10 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 11 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 12 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 13 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 14 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 15 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 16 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 17 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 18 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 19 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 20 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 21 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 01 │ │ ├── input.txt │ │ ├── part-1.py │ │ └── part-2.py │ ├── 02 │ │ ├── input.txt │ │ ├── part-1.py │ │ └── part-2.py │ ├── 04 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 05 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 06 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 07 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 08 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 09 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── Project.toml │ ├── README.md │ └── src │ │ └── AdventOfCode2016.jl ├── 2017 │ ├── 10 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 11 │ │ ├── cube-coordinates.png │ │ ├── input.txt │ │ └── puzzle1and2.py │ ├── 12 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 13 │ │ ├── input.txt │ │ ├── picoseconds.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 14 │ │ ├── grid.txt │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 15 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 16 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 17 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 18 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 19 │ │ ├── input.txt │ │ ├── input_test.txt │ │ └── puzzle1and2.py │ ├── 20 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 21 │ │ ├── input.txt │ │ └── puzzle1and2.py │ ├── 22 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 23 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 24 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 25 │ │ ├── input.txt │ │ └── puzzle1.py │ ├── 01 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 02 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 03 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 04 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 05 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 06 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 07 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 08 │ │ ├── input.txt │ │ └── puzzle1and2.py │ └── 09 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py ├── 2018 │ ├── 10 │ │ ├── input.txt │ │ ├── puzzle.py │ │ └── sample-input.txt │ ├── 11 │ │ └── puzzle.py │ ├── 12 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 13 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 14 │ │ └── puzzle.jl │ ├── 15 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 16 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 17 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 18 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 19 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 01 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 02 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 03 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 04 │ │ ├── input.txt │ │ └── puzzle.py │ ├── 05 │ │ ├── input.txt │ │ └── puzzle.py │ ├── 06 │ │ ├── input.txt │ │ └── puzzle.py │ ├── 07 │ │ ├── input.txt │ │ ├── puzzle1.py │ │ └── puzzle2.py │ ├── 08 │ │ ├── input.txt │ │ └── puzzle.py │ ├── 09 │ │ ├── README.md │ │ ├── analytic.py │ │ ├── input.txt │ │ ├── puzzle.py │ │ └── slow.py │ ├── Project.toml │ ├── README.md │ └── src │ │ └── AdventOfCode2018.jl ├── 2019 │ ├── 10 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 11 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 12 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 13 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 14 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 15 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 16 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 17 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 18 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 19 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 20 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 21 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 22 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 23 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 24 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 25 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 01 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 02 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 03 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 04 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 05 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 06 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 07 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 08 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 09 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── Project.toml │ ├── README.md │ └── src │ │ └── Advent2019.jl ├── 2020 │ ├── 10 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 11 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 12 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 13 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 14 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 15 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 16 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 17 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 18 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 19 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 20 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 21 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 22 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 23 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 24 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 25 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 01 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 02 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 03 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 04 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 05 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 06 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 07 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 08 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 09 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── Project.toml │ ├── README.md │ └── src │ │ └── AdventOfCode2020.jl ├── 2021 │ ├── 10 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 11 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 12 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 13 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 14 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 15 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 01 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 02 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 03 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 04 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 05 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 06 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 07 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 08 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 09 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── Project.toml │ └── src │ │ └── AdventOfCode2021.jl ├── 2022 │ ├── 10 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 11 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 12 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 13 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 20 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 21 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 22 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 23 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 24 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 25 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 01 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 02 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 03 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 04 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 05 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 06 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 07 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 08 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── 09 │ │ ├── input.txt │ │ └── puzzle.jl │ ├── Project.toml │ ├── README.md │ └── src │ │ └── AdventOfCode2022.jl └── README.md ├── Leetcode ├── 1. Two Sum.cpp ├── 100. Same Tree.py ├── 108. Convert Sorted Array to Binary Search Tree.py ├── 154. Find Minimum in Rotated Sorted Array II.py ├── 2. Add Two Numbers.cpp ├── 217. Contains Duplicate.py ├── 228. Summary Ranges.py ├── 242. Valid Anagram.py ├── 3. Longest Substring Without Repeating Characters.cpp ├── 4. Median of Two Sorted Arrays.py ├── 53. Maximum Subarray.py ├── 6. Zigzag Conversion.py └── 99. Recover Binary Search Tree.py ├── Project Genius ├── Grecian Computer.jl └── Project.toml └── README.md /Advent of Code/2015/01/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day1() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | result = map(readline(input) |> collect) do c 5 | c == '(' ? 1 : -1 6 | end |> cumsum 7 | 8 | result₁ = last(result) 9 | result₂ = findfirst(==(-1), result) 10 | 11 | # @assert result₁ == 138 12 | # @assert result₂ == 1771 13 | 14 | result₁, result₂ 15 | end 16 | 17 | export day1 18 | -------------------------------------------------------------------------------- /Advent of Code/2015/02/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day2() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | presents = split.(readlines(input), "x") .|> 5 | x -> parse.(Int, x) 6 | 7 | surfacearea(l, w, h) = 2(l * w) + 2(w * h) + 2(h * l) 8 | smallestsidearea(l, w, h) = min(l * w, w * h, h * l) 9 | smallestperimeter(l, w, h) = min(2l + 2w, 2w + 2h, 2h + 2l) 10 | volume(l, w, h) = l * w * h 11 | 12 | result₁ = sum(presents) do p 13 | surfacearea(p...) + smallestsidearea(p...) 14 | end 15 | 16 | result₂ = sum(presents) do p 17 | smallestperimeter(p...) + volume(p...) 18 | end 19 | 20 | # @assert result₁ == 1606483 21 | # @assert result₂ == 3842356 22 | 23 | result₁, result₂ 24 | end 25 | 26 | export day2 27 | -------------------------------------------------------------------------------- /Advent of Code/2015/03/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day3() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | c2ci = Dict('^' => CartesianIndex( 0, 1), 5 | '>' => CartesianIndex( 1, 0), 6 | 'v' => CartesianIndex( 0, -1), 7 | '<' => CartesianIndex(-1, 0)) 8 | 9 | instructions = map(x -> c2ci[x], collect(readline(input))) 10 | 11 | # -- Part One -- # 12 | 13 | santa = CartesianIndex(0, 0) 14 | visited = Dict{CartesianIndex,Int}(santa => 1) 15 | 16 | foreach(instructions) do step 17 | santa += step 18 | visited[santa] = get(visited, santa, 0) + 1 19 | end 20 | 21 | result₁ = length(visited) 22 | 23 | # -- Part Two -- # 24 | 25 | santa = CartesianIndex(0, 0) 26 | robosanta = CartesianIndex(0, 0) 27 | visited = Dict{CartesianIndex,Int}(santa => 2) 28 | 29 | for (i, s) in enumerate((santa, robosanta)) 30 | foreach(instructions[i:2:end]) do step 31 | s += step 32 | visited[s] = get(visited, s, 0) + 1 33 | end 34 | end 35 | 36 | result₂ = length(visited) 37 | 38 | # @assert result₁ == 2592 39 | # @assert result₂ == 2360 40 | 41 | result₁, result₂ 42 | end 43 | 44 | export day3 45 | -------------------------------------------------------------------------------- /Advent of Code/2015/04/input.txt: -------------------------------------------------------------------------------- 1 | ckczppom 2 | -------------------------------------------------------------------------------- /Advent of Code/2015/04/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day4() 2 | input = joinpath(@__DIR__, "input.txt") 3 | a = readline(input) 4 | 5 | function solve(prefix) 6 | for b = Iterators.countfrom(1) 7 | hash = a * string(b) |> md5 |> bytes2hex 8 | startswith(hash, prefix) && return b 9 | end 10 | end 11 | 12 | result₁ = solve("00000") 13 | result₂ = solve("000000") 14 | 15 | # @assert result₁ == 117946 16 | # @assert result₂ == 3938038 17 | 18 | result₁, result₂ 19 | end 20 | 21 | export day4 22 | -------------------------------------------------------------------------------- /Advent of Code/2015/05/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day5() 2 | input = joinpath(@__DIR__, "input.txt") 3 | strings = readlines(input) 4 | 5 | function isnice₁(s::String) 6 | cond₁ = count(c -> c ∈ "aeiou", s) >= 3 7 | cond₂ = 0 ∈ diff(collect(s)) 8 | cond₃ = !contains(s, r"ab|cd|pq|xy") 9 | cond₁ & cond₂ & cond₃ 10 | end 11 | 12 | function isnice₂(s::String) 13 | cond₁ = contains(s, r"(\w{2}).*\1") 14 | cond₂ = contains(s, r"(\w).\1") 15 | cond₁ & cond₂ 16 | end 17 | 18 | result₁ = count(isnice₁, strings) 19 | result₂ = count(isnice₂, strings) 20 | 21 | # @assert result₁ == 255 22 | # @assert result₂ == 55 23 | 24 | result₁, result₂ 25 | end 26 | 27 | export day5 28 | -------------------------------------------------------------------------------- /Advent of Code/2015/06/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day6() 2 | input = joinpath(@__DIR__, "input.txt") 3 | instructions = readlines(input) 4 | 5 | # -- Part One -- # 6 | 7 | lights = falses((1000, 1000)) 8 | 9 | for instruction in instructions 10 | x₁, y₁, x₂, y₂ = split(instruction) |> 11 | x -> parse.(Int, [split(x[end - 2], ',') 12 | split(x[end ], ',')]) .+ 1 13 | 14 | if startswith(instruction, "turn on") 15 | lights[x₁:x₂,y₁:y₂] .= true 16 | elseif startswith(instruction, "turn off") 17 | lights[x₁:x₂,y₁:y₂] .= false 18 | elseif startswith(instruction, "toggle") 19 | lights[x₁:x₂,y₁:y₂] .= .!lights[x₁:x₂,y₁:y₂] 20 | end 21 | end 22 | 23 | result₁ = count(lights) 24 | 25 | # -- Part Two -- # 26 | 27 | lights = zeros(Int, (1000, 1000)) 28 | 29 | for instruction in instructions 30 | x₁, y₁, x₂, y₂ = split(instruction) |> 31 | x -> parse.(Int, [split(x[end - 2], ',') 32 | split(x[end ], ',')]) .+ 1 33 | 34 | if startswith(instruction, "turn on") 35 | lights[x₁:x₂,y₁:y₂] .+= 1 36 | elseif startswith(instruction, "turn off") 37 | lights[x₁:x₂,y₁:y₂] .= max.(lights[x₁:x₂,y₁:y₂] .- 1, 0) 38 | elseif startswith(instruction, "toggle") 39 | lights[x₁:x₂,y₁:y₂] .+= 2 40 | end 41 | end 42 | 43 | result₂ = sum(lights) 44 | 45 | # @assert result₁ == 400410 46 | # @assert result₂ == 15343601 47 | 48 | result₁, result₂ 49 | end 50 | 51 | export day6 52 | -------------------------------------------------------------------------------- /Advent of Code/2015/08/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day8() 2 | input = joinpath(@__DIR__, "input.txt") 3 | strings = readlines(input) 4 | 5 | result₁ = sum(strings) do s 6 | length(s) - length(Meta.parse(s)) 7 | end 8 | 9 | result₂ = sum(strings) do s₀ 10 | s₁ = replace(s₀, "\\" => "\\\\") 11 | s₂ = replace(s₁, "\"" => "\\\"") 12 | s₃ = "\"" * s₂ * "\"" 13 | # @assert Meta.parse(s₃) == s₀ 14 | length(codeunits(s₃)) - length(s₀) 15 | end 16 | 17 | # @assert result₁ == 1342 18 | # @assert result₂ == 2074 19 | 20 | result₁, result₂ 21 | end 22 | 23 | export day8 24 | -------------------------------------------------------------------------------- /Advent of Code/2015/09/input.txt: -------------------------------------------------------------------------------- 1 | Faerun to Tristram = 65 2 | Faerun to Tambi = 129 3 | Faerun to Norrath = 144 4 | Faerun to Snowdin = 71 5 | Faerun to Straylight = 137 6 | Faerun to AlphaCentauri = 3 7 | Faerun to Arbre = 149 8 | Tristram to Tambi = 63 9 | Tristram to Norrath = 4 10 | Tristram to Snowdin = 105 11 | Tristram to Straylight = 125 12 | Tristram to AlphaCentauri = 55 13 | Tristram to Arbre = 14 14 | Tambi to Norrath = 68 15 | Tambi to Snowdin = 52 16 | Tambi to Straylight = 65 17 | Tambi to AlphaCentauri = 22 18 | Tambi to Arbre = 143 19 | Norrath to Snowdin = 8 20 | Norrath to Straylight = 23 21 | Norrath to AlphaCentauri = 136 22 | Norrath to Arbre = 115 23 | Snowdin to Straylight = 101 24 | Snowdin to AlphaCentauri = 84 25 | Snowdin to Arbre = 96 26 | Straylight to AlphaCentauri = 107 27 | Straylight to Arbre = 14 28 | AlphaCentauri to Arbre = 46 29 | -------------------------------------------------------------------------------- /Advent of Code/2015/09/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day9() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | locations = Set{String}() 5 | edge2dist = Dict{Tuple{String,String},Int}() 6 | 7 | for line = eachline(input) 8 | ts = split(line) 9 | push!(locations, ts[1]) 10 | push!(locations, ts[3]) 11 | edge2dist[(ts[1], ts[3])] = parse(Int, ts[5]) 12 | edge2dist[(ts[3], ts[1])] = parse(Int, ts[5]) 13 | end 14 | 15 | visited = Set{Array{String,1}}() 16 | 17 | for p = permutations(collect(locations)) 18 | if p ∉ visited && reverse(p) ∉ visited 19 | push!(visited, p) 20 | end 21 | end 22 | 23 | distances = map(collect(visited)) do path 24 | sum(1:length(path) - 1) do i 25 | edge2dist[(path[i], path[i + 1])] 26 | end 27 | end 28 | 29 | result₁, result₂ = extrema(distances) 30 | 31 | # @assert result₁ == 117 32 | # @assert result₂ == 909 33 | 34 | result₁, result₂ 35 | end 36 | 37 | export day9 38 | -------------------------------------------------------------------------------- /Advent of Code/2015/10/input.txt: -------------------------------------------------------------------------------- 1 | 1321131112 2 | -------------------------------------------------------------------------------- /Advent of Code/2015/10/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day10() 2 | input = joinpath(@__DIR__, "input.txt") 3 | seed = readline(input) 4 | 5 | function solve(seed, steps) 6 | curr = seed 7 | for step = 1:steps 8 | print("Current step: ", step) 9 | next = "" 10 | for m = eachmatch(r"(\d)\1*", curr) 11 | next = next * string(length(m.match)) * only(m.captures) 12 | end 13 | curr = next 14 | println(" --- ", length(curr)) 15 | end 16 | length(curr) 17 | end 18 | 19 | result₁ = solve(seed, 40) 20 | result₂ = solve(seed, 50) 21 | 22 | # @assert result₁ == 492982 23 | # @assert result₂ == 6989950 24 | 25 | result₁, result₂ 26 | end 27 | 28 | export day10 29 | -------------------------------------------------------------------------------- /Advent of Code/2015/11/input.txt: -------------------------------------------------------------------------------- 1 | cqjxjnds 2 | -------------------------------------------------------------------------------- /Advent of Code/2015/12/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day12() 2 | input = joinpath(@__DIR__, "input.txt") 3 | s = readline(input) 4 | 5 | m = eachmatch(r"(-*\d+)", s) 6 | result₁ = mapreduce(x -> parse.(Int, x.captures), sum ∘ vcat, m) 7 | 8 | solve(t::String) = 0 9 | solve(t::Number) = t 10 | solve(t::Array) = mapreduce(solve, +, t) 11 | solve(t::Dict; vs=values(t)) = "red" ∉ vs ? sum(solve.(vs)) : 0 12 | 13 | j = JSON.parse(s) 14 | result₂ = solve(j) 15 | 16 | # @assert result₁ == 111754 17 | # @assert result₂ == 65402 18 | 19 | result₁, result₂ 20 | end 21 | 22 | export day12 23 | -------------------------------------------------------------------------------- /Advent of Code/2015/13/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day13() 2 | input = joinpath(@__DIR__, "input.txt") 3 | people = readlines(input) .|> (x -> split(x)[1]) |> unique 4 | scores = Dict(split.(readlines(input), Ref((' ', '.'))) .|> x -> 5 | (x[1], x[11]) => (x[3] == "lose" ? -1 : 1) * parse(Int, x[4])) 6 | 7 | function optimize(people, scores) 8 | max_score = nothing 9 | opt_table = nothing 10 | 11 | people = copy(people) 12 | head = pop!(people) 13 | 14 | for x = permutations(people) 15 | total = 0 16 | table = [head; x] 17 | 18 | for i = 1:length(table) 19 | j = mod1(i + 1, length(table)) 20 | total += scores[(table[i], table[j])] 21 | total += scores[(table[j], table[i])] 22 | end 23 | 24 | if isnothing(max_score) || total > max_score 25 | max_score = total 26 | opt_table = table 27 | end 28 | end 29 | 30 | max_score, opt_table 31 | end 32 | 33 | result₁ = optimize(people, scores)[1] 34 | 35 | for guest ∈ people 36 | scores[("Myself", guest)] = 0 37 | scores[(guest, "Myself")] = 0 38 | end 39 | push!(people, "Myself") 40 | 41 | result₂ = optimize(people, scores)[1] 42 | 43 | # @assert result₁ == 664 44 | # @assert result₂ == 640 45 | 46 | result₁, result₂ 47 | end 48 | 49 | export day13 50 | -------------------------------------------------------------------------------- /Advent of Code/2015/14/input.txt: -------------------------------------------------------------------------------- 1 | Vixen can fly 8 km/s for 8 seconds, but then must rest for 53 seconds. 2 | Blitzen can fly 13 km/s for 4 seconds, but then must rest for 49 seconds. 3 | Rudolph can fly 20 km/s for 7 seconds, but then must rest for 132 seconds. 4 | Cupid can fly 12 km/s for 4 seconds, but then must rest for 43 seconds. 5 | Donner can fly 9 km/s for 5 seconds, but then must rest for 38 seconds. 6 | Dasher can fly 10 km/s for 4 seconds, but then must rest for 37 seconds. 7 | Comet can fly 3 km/s for 37 seconds, but then must rest for 76 seconds. 8 | Prancer can fly 9 km/s for 12 seconds, but then must rest for 97 seconds. 9 | Dancer can fly 37 km/s for 1 seconds, but then must rest for 36 seconds. 10 | -------------------------------------------------------------------------------- /Advent of Code/2015/14/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day14() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | reindeer = map(eachline(input)) do line 5 | rx = r"(\w+) can fly (\d+) km/s for (\d+) seconds, but then must rest for (\d+) seconds." 6 | name, vel, t_fly, t_rest = only(eachmatch(rx, line)).captures 7 | name, parse.(Int, (vel, t_fly, t_rest))... 8 | end 9 | 10 | distances = zeros(Int, length(reindeer)) 11 | points = zeros(Int, length(reindeer)) 12 | 13 | for t = 1:2503 14 | for (i, (_, vel, t_fly, t_rest)) in enumerate(reindeer) 15 | if mod1(t, t_fly + t_rest) <= t_fly 16 | distances[i] += vel 17 | end 18 | end 19 | 20 | lead = maximum(distances) 21 | cis = findall(==(lead), distances) 22 | points[cis] .+= 1 23 | end 24 | 25 | result₁ = maximum(distances) 26 | result₂ = maximum(points) 27 | 28 | # @assert result₁ == 2655 29 | # @assert result₂ == 1059 30 | 31 | result₁, result₂ 32 | end 33 | 34 | export day14 35 | -------------------------------------------------------------------------------- /Advent of Code/2015/15/input.txt: -------------------------------------------------------------------------------- 1 | Sugar: capacity 3, durability 0, flavor 0, texture -3, calories 2 2 | Sprinkles: capacity -3, durability 3, flavor 0, texture 0, calories 9 3 | Candy: capacity -1, durability 0, flavor 4, texture 0, calories 1 4 | Chocolate: capacity 0, durability 0, flavor -2, texture 2, calories 8 5 | -------------------------------------------------------------------------------- /Advent of Code/2015/16/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day16() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | sample = Dict("children" => 3, 5 | "cats" => 7, 6 | "samoyeds" => 2, 7 | "pomeranians" => 3, 8 | "akitas" => 0, 9 | "vizslas" => 0, 10 | "goldfish" => 5, 11 | "trees" => 3, 12 | "cars" => 2, 13 | "perfumes" => 1) 14 | 15 | list = map(eachline(input)) do line 16 | Dict(replace(line, r"Sue \d+: " => "") |> 17 | x -> split.(split(x, ", "), ": ") .|> 18 | x -> (x[1] => parse(Int, x[2]))) 19 | end 20 | 21 | list₁ = copy(list) 22 | list₂ = copy(list) 23 | 24 | for (k, v) ∈ sample 25 | filter!(x -> !haskey(x, k) || x[k] == v, list₁) 26 | end 27 | 28 | for (k, v) ∈ sample 29 | if k ∈ ("cats", "trees") 30 | filter!(x -> !haskey(x, k) || x[k] > v, list₂) 31 | elseif k ∈ ("pomeranians", "goldfish") 32 | filter!(x -> !haskey(x, k) || x[k] < v, list₂) 33 | else 34 | filter!(x -> !haskey(x, k) || x[k] == v, list₂) 35 | end 36 | end 37 | 38 | result₁ = findall(==(list₁ |> only), list) |> only 39 | result₂ = findall(==(list₂ |> only), list) |> only 40 | 41 | # @assert result₁ == 103 42 | # @assert result₂ == 405 43 | 44 | result₁, result₂ 45 | end 46 | 47 | export day16 48 | -------------------------------------------------------------------------------- /Advent of Code/2015/17/input.txt: -------------------------------------------------------------------------------- 1 | 50 2 | 44 3 | 11 4 | 49 5 | 42 6 | 46 7 | 18 8 | 32 9 | 26 10 | 40 11 | 21 12 | 7 13 | 18 14 | 43 15 | 10 16 | 47 17 | 36 18 | 24 19 | 22 20 | 40 21 | -------------------------------------------------------------------------------- /Advent of Code/2015/17/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day17() 2 | input = joinpath(@__DIR__, "input.txt") 3 | containers = parse.(Int, readlines(input)) 4 | 5 | part₁ = filter!(x -> sum(x) == 150, collect(combinations(containers))) 6 | result₁ = length(part₁) 7 | 8 | part₂ = filter!(x -> length(x) == minimum(length, part₁), part₁) 9 | result₂ = length(part₂) 10 | 11 | # @assert result₁ == 654 12 | # @assert result₂ == 57 13 | 14 | result₁, result₂ 15 | end 16 | 17 | export day17 18 | -------------------------------------------------------------------------------- /Advent of Code/2015/18/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day18() 2 | input = joinpath(@__DIR__, "input.txt") 3 | state₀ = mapreduce(collect, hcat, eachline(input)) 4 | 5 | neighbours = let 6 | steps = filter(!iszero, CartesianIndices(ntuple(_ -> -1:1, 2))) 7 | (A, I) -> map(steps) do step 8 | checkbounds(Bool, A, I + step) ? A[I + step] : nothing 9 | end 10 | end 11 | 12 | function turn_on_corners(state) 13 | state[1,1] = state[1,end] = state[end,1] = state[end,end] = '#' 14 | end 15 | 16 | function solve(state⁺, steps; part₂=false) 17 | state⁺ = copy(state⁺) 18 | state⁻ = similar(state⁺) # We need to track the previous state 19 | 20 | part₂ && turn_on_corners(state⁺) 21 | 22 | for step = 1:steps 23 | copyto!(state⁻, state⁺) 24 | 25 | @inbounds for i ∈ CartesianIndices(state⁺) 26 | 27 | if state⁻[i] == ('.') 28 | n = count(==('#'), neighbours(state⁻, i)) 29 | n == 3 && (state⁺[i] = '#') # turns on 30 | 31 | elseif state⁻[i] == ('#') 32 | n = count(==('#'), neighbours(state⁻, i)) 33 | !(2 <= n <= 3) && (state⁺[i] = '.') # turns off 34 | 35 | end 36 | end 37 | 38 | part₂ && turn_on_corners(state⁺) 39 | end 40 | 41 | count(==('#'), state⁺) 42 | end 43 | 44 | result₁ = solve(state₀, 100, part₂=false) 45 | result₂ = solve(state₀, 100, part₂=true) 46 | 47 | # @assert result₁ == 1061 48 | # @assert result₂ == 1006 49 | 50 | result₁, result₂ 51 | end 52 | 53 | export day18 54 | -------------------------------------------------------------------------------- /Advent of Code/2015/19/input.txt: -------------------------------------------------------------------------------- 1 | Al => ThF 2 | Al => ThRnFAr 3 | B => BCa 4 | B => TiB 5 | B => TiRnFAr 6 | Ca => CaCa 7 | Ca => PB 8 | Ca => PRnFAr 9 | Ca => SiRnFYFAr 10 | Ca => SiRnMgAr 11 | Ca => SiTh 12 | F => CaF 13 | F => PMg 14 | F => SiAl 15 | H => CRnAlAr 16 | H => CRnFYFYFAr 17 | H => CRnFYMgAr 18 | H => CRnMgYFAr 19 | H => HCa 20 | H => NRnFYFAr 21 | H => NRnMgAr 22 | H => NTh 23 | H => OB 24 | H => ORnFAr 25 | Mg => BF 26 | Mg => TiMg 27 | N => CRnFAr 28 | N => HSi 29 | O => CRnFYFAr 30 | O => CRnMgAr 31 | O => HP 32 | O => NRnFAr 33 | O => OTi 34 | P => CaP 35 | P => PTi 36 | P => SiRnFAr 37 | Si => CaSi 38 | Th => ThCa 39 | Ti => BP 40 | Ti => TiTi 41 | e => HF 42 | e => NAl 43 | e => OMg 44 | 45 | CRnSiRnCaPTiMgYCaPTiRnFArSiThFArCaSiThSiThPBCaCaSiRnSiRnTiTiMgArPBCaPMgYPTiRnFArFArCaSiRnBPMgArPRnCaPTiRnFArCaSiThCaCaFArPBCaCaPTiTiRnFArCaSiRnSiAlYSiThRnFArArCaSiRnBFArCaCaSiRnSiThCaCaCaFYCaPTiBCaSiThCaSiThPMgArSiRnCaPBFYCaCaFArCaCaCaCaSiThCaSiRnPRnFArPBSiThPRnFArSiRnMgArCaFYFArCaSiRnSiAlArTiTiTiTiTiTiTiRnPMgArPTiTiTiBSiRnSiAlArTiTiRnPMgArCaFYBPBPTiRnSiRnMgArSiThCaFArCaSiThFArPRnFArCaSiRnTiBSiThSiRnSiAlYCaFArPRnFArSiThCaFArCaCaSiThCaCaCaSiRnPRnCaFArFYPMgArCaPBCaPBSiRnFYPBCaFArCaSiAl 46 | -------------------------------------------------------------------------------- /Advent of Code/2015/19/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day19() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | replacements, molecule = split(read(input, String), "\n\n") |> 5 | x -> (split(x[1], '\n') .|> x -> Pair(split(x, " => ")...), 6 | eachmatch(r"([A-Z][a-z]*)", x[2]) |> collect .|> x -> only(x.captures)) 7 | 8 | function part₁(s) 9 | next = [] 10 | for (in, out) ∈ replacements 11 | for (i, c) = enumerate(s) 12 | if in == string(c) 13 | a = i > 1 ? s[1:i - 1] : "" 14 | c = i < length(s) ? s[i + 1:end] : "" 15 | push!(next, join([a; out; c])) 16 | end 17 | end 18 | end 19 | next |> unique |> length 20 | end 21 | 22 | function part₂(s) 23 | s = join(s) 24 | counter = 0 25 | while s != "e" 26 | for (k, v) ∈ replacements 27 | counter += count(v, s) 28 | s = replace(s, v => k) 29 | end 30 | end 31 | counter 32 | end 33 | 34 | result₁ = part₁(molecule) 35 | result₂ = part₂(molecule) 36 | 37 | # @assert result₁ == 518 38 | # @assert result₂ == 200 39 | 40 | result₁, result₂ 41 | end 42 | 43 | export day19 44 | -------------------------------------------------------------------------------- /Advent of Code/2015/20/input.txt: -------------------------------------------------------------------------------- 1 | 36000000 2 | -------------------------------------------------------------------------------- /Advent of Code/2015/20/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day20() 2 | input = joinpath(@__DIR__, "input.txt") 3 | target = parse(Int, readline(input)) 4 | 5 | houses = 1_000_000 6 | counters = zeros(Int, houses) 7 | for elfᵢ = 1:houses 8 | housesᵢ = range(elfᵢ, step=elfᵢ, stop=houses) 9 | counters[housesᵢ] .+= 10 * elfᵢ 10 | end 11 | result₁ = findfirst(>=(target), counters) 12 | 13 | houses = 100_000_000 14 | counters = zeros(Int, houses) 15 | for elfᵢ = 1:1_000_000 16 | housesᵢ = range(elfᵢ, step=elfᵢ, length=50) 17 | counters[housesᵢ] .+= 11 * elfᵢ 18 | end 19 | result₂ = findfirst(>=(target), counters) 20 | 21 | # @assert result₁ == 831600 22 | # @assert result₂ == 884520 23 | 24 | result₁, result₂ 25 | end 26 | 27 | export day20 28 | -------------------------------------------------------------------------------- /Advent of Code/2015/21/input.txt: -------------------------------------------------------------------------------- 1 | Hit Points: 100 2 | Damage: 8 3 | Armor: 2 4 | -------------------------------------------------------------------------------- /Advent of Code/2015/22/input.txt: -------------------------------------------------------------------------------- 1 | Hit Points: 55 2 | Damage: 8 3 | -------------------------------------------------------------------------------- /Advent of Code/2015/23/input.txt: -------------------------------------------------------------------------------- 1 | jio a, +18 2 | inc a 3 | tpl a 4 | inc a 5 | tpl a 6 | tpl a 7 | tpl a 8 | inc a 9 | tpl a 10 | inc a 11 | tpl a 12 | inc a 13 | inc a 14 | tpl a 15 | tpl a 16 | tpl a 17 | inc a 18 | jmp +22 19 | tpl a 20 | inc a 21 | tpl a 22 | inc a 23 | inc a 24 | tpl a 25 | inc a 26 | tpl a 27 | inc a 28 | inc a 29 | tpl a 30 | tpl a 31 | inc a 32 | inc a 33 | tpl a 34 | inc a 35 | inc a 36 | tpl a 37 | inc a 38 | inc a 39 | tpl a 40 | jio a, +8 41 | inc b 42 | jie a, +4 43 | tpl a 44 | inc a 45 | jmp +2 46 | hlf a 47 | jmp -7 48 | -------------------------------------------------------------------------------- /Advent of Code/2015/23/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day23() 2 | input = joinpath(@__DIR__, "input.txt") 3 | program = readlines(input) .|> x -> split(replace(x, "," => "")) 4 | 5 | function compute!(registers; ip=1) 6 | while 1 <= ip <= length(program) 7 | tokens = program[ip] 8 | instruction = first(tokens) 9 | 10 | if instruction == "hlf" 11 | r = tokens[2] 12 | registers[r] ÷= 2 13 | ip += 1 14 | elseif instruction == "tpl" 15 | r = tokens[2] 16 | registers[r] *= 3 17 | ip += 1 18 | elseif instruction == "inc" 19 | r = tokens[2] 20 | registers[r] += 1 21 | ip += 1 22 | elseif instruction == "jmp" 23 | offset = parse(Int, tokens[2]) 24 | ip += offset 25 | elseif instruction == "jie" 26 | r = tokens[2] 27 | offset = parse(Int, tokens[3]) 28 | iseven(registers[r]) ? (ip += offset) : (ip += 1) 29 | elseif instruction == "jio" 30 | r = tokens[2] 31 | offset = parse(Int, tokens[3]) 32 | isone(registers[r]) ? (ip += offset) : (ip += 1) 33 | end 34 | end 35 | 36 | registers 37 | end 38 | 39 | result₁ = compute!(Dict("a" => 0, "b" => 0))["b"] 40 | result₂ = compute!(Dict("a" => 1, "b" => 0))["b"] 41 | 42 | # @assert result₁ == 307 43 | # @assert result₂ == 160 44 | 45 | result₁, result₂ 46 | end 47 | 48 | export day23 49 | -------------------------------------------------------------------------------- /Advent of Code/2015/24/input.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 7 5 | 11 6 | 13 7 | 17 8 | 19 9 | 23 10 | 31 11 | 37 12 | 41 13 | 43 14 | 47 15 | 53 16 | 59 17 | 61 18 | 67 19 | 71 20 | 73 21 | 79 22 | 83 23 | 89 24 | 97 25 | 101 26 | 103 27 | 107 28 | 109 29 | 113 30 | -------------------------------------------------------------------------------- /Advent of Code/2015/25/input.txt: -------------------------------------------------------------------------------- 1 | To continue, please consult the code grid in the manual. Enter the code at row 3010, column 3019. 2 | -------------------------------------------------------------------------------- /Advent of Code/2015/25/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day25() 2 | input = joinpath(@__DIR__, "input.txt") 3 | r, c = (r"row (\d+), column (\d+)", readline(input)) |> 4 | x -> only(eachmatch(x...)) |> x -> parse.(Int, x.captures) 5 | 6 | function nth(r, c) 7 | if c == 1 8 | r == 1 ? 1 : nth(1, r - 1) 9 | else 10 | nth(r + c - 1, 1) + c 11 | end 12 | end 13 | 14 | code₀ = 20151125 15 | 16 | x = 252533 17 | p = nth(r, c) - 1 18 | m = 33554393 19 | 20 | result₁ = code₀ * powermod(x, p, m) % m 21 | 22 | # @assert result₁ == 8997277 23 | 24 | result₁, nothing 25 | end 26 | 27 | export day25 28 | -------------------------------------------------------------------------------- /Advent of Code/2015/Project.toml: -------------------------------------------------------------------------------- 1 | name = "AdventOfCode2015" 2 | uuid = "58431eaf-e7ad-48ce-9a0d-e50210bea6f0" 3 | authors = ["Henrique Ferrolho "] 4 | version = "0.1.0" 5 | 6 | [deps] 7 | BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" 8 | Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" 9 | JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" 10 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 11 | MD5 = "6ac74813-4b46-53a4-afec-0b5dc9d7885c" 12 | Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" 13 | -------------------------------------------------------------------------------- /Advent of Code/2015/README.md: -------------------------------------------------------------------------------- 1 | Start the Julia REPL from within this folder. 2 | -------------------------------------------------------------------------------- /Advent of Code/2015/src/AdventOfCode2015.jl: -------------------------------------------------------------------------------- 1 | module AdventOfCode2015 2 | 3 | using BenchmarkTools 4 | using Combinatorics 5 | using JSON 6 | using LinearAlgebra 7 | using MD5 8 | 9 | greet() = println("Hello, Advent of Code 2015!") 10 | 11 | include("../01/puzzle.jl") 12 | include("../02/puzzle.jl") 13 | include("../03/puzzle.jl") 14 | include("../04/puzzle.jl") 15 | include("../05/puzzle.jl") 16 | include("../06/puzzle.jl") 17 | include("../07/puzzle.jl") 18 | include("../08/puzzle.jl") 19 | include("../09/puzzle.jl") 20 | include("../10/puzzle.jl") 21 | include("../11/puzzle.jl") 22 | include("../12/puzzle.jl") 23 | include("../13/puzzle.jl") 24 | include("../14/puzzle.jl") 25 | include("../15/puzzle.jl") 26 | include("../16/puzzle.jl") 27 | include("../17/puzzle.jl") 28 | include("../18/puzzle.jl") 29 | include("../19/puzzle.jl") 30 | include("../20/puzzle.jl") 31 | include("../21/puzzle.jl") 32 | include("../22/puzzle.jl") 33 | include("../23/puzzle.jl") 34 | include("../24/puzzle.jl") 35 | include("../25/puzzle.jl") 36 | 37 | end # module 38 | -------------------------------------------------------------------------------- /Advent of Code/2016/01/input.txt: -------------------------------------------------------------------------------- 1 | R3, L5, R1, R2, L5, R2, R3, L2, L5, R5, L4, L3, R5, L1, R3, R4, R1, L3, R3, L2, L5, L2, R4, R5, R5, L4, L3, L3, R4, R4, R5, L5, L3, R2, R2, L3, L4, L5, R1, R3, L3, R2, L3, R5, L194, L2, L5, R2, R1, R1, L1, L5, L4, R4, R2, R2, L4, L1, R2, R53, R3, L5, R72, R2, L5, R3, L4, R187, L4, L5, L2, R1, R3, R5, L4, L4, R2, R5, L5, L4, L3, R5, L2, R1, R1, R4, L1, R2, L3, R5, L4, R2, L3, R1, L4, R4, L1, L2, R3, L1, L1, R4, R3, L4, R2, R5, L2, L3, L3, L1, R3, R5, R2, R3, R1, R2, L1, L4, L5, L2, R4, R5, L2, R4, R4, L3, R2, R1, L4, R3, L3, L4, L3, L1, R3, L2, R2, L4, L4, L5, R3, R5, R3, L2, R5, L2, L1, L5, L1, R2, R4, L5, R2, L4, L5, L4, L5, L2, L5, L4, R5, R3, R2, R2, L3, R3, L2, L5 2 | -------------------------------------------------------------------------------- /Advent of Code/2016/01/part-1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6 | 7 | def updateDirection(letter): 8 | global orientation 9 | 10 | if letter == 'R': orientation += 1 11 | elif letter == 'L': orientation -= 1 12 | 13 | orientation %= 4 14 | 15 | def walk(amount): 16 | if orientation == 0: coord[1] -= amount 17 | elif orientation == 1: coord[0] += amount 18 | elif orientation == 2: coord[1] += amount 19 | elif orientation == 3: coord[0] -= amount 20 | 21 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 22 | 23 | instructions = sys.stdin.readline() 24 | instructions = instructions.strip().split(', ') 25 | 26 | # 0 - north, 1 - east, 2 - south, 3 - west 27 | orientation = 0 28 | coord = [0, 0] 29 | 30 | for instruction in instructions: 31 | turn, amount = instruction[0], int(instruction[1:]) 32 | updateDirection(turn) 33 | walk(amount) 34 | 35 | print(sum(abs(i) for i in coord)) 36 | -------------------------------------------------------------------------------- /Advent of Code/2016/01/part-2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6 | 7 | def updateDirection(letter): 8 | global orientation 9 | 10 | if letter == 'R': orientation += 1 11 | elif letter == 'L': orientation -= 1 12 | 13 | orientation %= 4 14 | 15 | def walk(amount): 16 | global done 17 | 18 | axis = ~ orientation % 2 19 | start = coord[axis] 20 | step = 1 if orientation in (1, 2) else -1 21 | 22 | if orientation == 0: coord[axis] -= amount 23 | elif orientation == 1: coord[axis] += amount 24 | elif orientation == 2: coord[axis] += amount 25 | elif orientation == 3: coord[axis] -= amount 26 | 27 | for i in range(start, coord[axis], step): 28 | temp_coord = None 29 | 30 | if axis == 0: temp_coord = (i, coord[1]) 31 | elif axis == 1: temp_coord = (coord[0], i) 32 | 33 | if temp_coord in visited: 34 | done = True 35 | return temp_coord 36 | 37 | visited.add(temp_coord) 38 | 39 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 40 | 41 | instructions = sys.stdin.readline() 42 | instructions = instructions.strip().split(', ') 43 | 44 | # 0 - north, 1 - east, 2 - south, 3 - west 45 | orientation = 0 46 | coord = [0, 0] 47 | 48 | easterBunnyHQ = None 49 | done = False 50 | visited = set() 51 | 52 | for instruction in instructions: 53 | if done: break 54 | 55 | turn, amount = instruction[0], int(instruction[1:]) 56 | updateDirection(turn) 57 | easterBunnyHQ = walk(amount) 58 | 59 | print(sum(abs(i) for i in easterBunnyHQ)) 60 | -------------------------------------------------------------------------------- /Advent of Code/2016/02/part-1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6 | 7 | def buttonAt(coord): 8 | return keypad[coord[1]][coord[0]] 9 | 10 | def clamp(minvalue, value, maxvalue): 11 | return max(minvalue, min(value, maxvalue)) 12 | 13 | def processLine(line): 14 | global code 15 | 16 | for move in line: 17 | if move == 'L': coord[0] -= 1 18 | elif move == 'R': coord[0] += 1 19 | elif move == 'U': coord[1] -= 1 20 | elif move == 'D': coord[1] += 1 21 | 22 | coord[0] = clamp(0, coord[0], 2) 23 | coord[1] = clamp(0, coord[1], 2) 24 | 25 | code += buttonAt(coord) 26 | 27 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 28 | 29 | keypad = (('1', '2', '3'), ('4', '5', '6'), ('7', '8', '9')) 30 | 31 | # start is the '5' button 32 | coord = [1, 1] 33 | 34 | code = '' 35 | 36 | for line in sys.stdin: 37 | processLine(line) 38 | 39 | print(code) 40 | -------------------------------------------------------------------------------- /Advent of Code/2016/02/part-2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 6 | 7 | def buttonAt(coord): 8 | return keypad[coord[1]][coord[0]] 9 | 10 | def validMove(x, y): 11 | return 0 <= x < 5 and 0 <= y < 5 and keypad[y][x] 12 | 13 | def processLine(line): 14 | global code 15 | 16 | for move in line: 17 | if move == 'L' and validMove(coord[0] - 1, coord[1]): coord[0] -= 1 18 | elif move == 'R' and validMove(coord[0] + 1, coord[1]): coord[0] += 1 19 | elif move == 'U' and validMove(coord[0], coord[1] - 1): coord[1] -= 1 20 | elif move == 'D' and validMove(coord[0], coord[1] + 1): coord[1] += 1 21 | 22 | code += buttonAt(coord) 23 | 24 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25 | 26 | keypad = ( 27 | ( '', '', '1', '', ''), 28 | ( '', '2', '3', '4', ''), 29 | ('5', '6', '7', '8', '9'), 30 | ( '', 'A', 'B', 'C', ''), 31 | ( '', '', 'D', '', '')) 32 | 33 | # start is the '5' button 34 | coord = [0, 2] 35 | 36 | code = '' 37 | 38 | for line in sys.stdin: 39 | processLine(line) 40 | 41 | print(code) 42 | -------------------------------------------------------------------------------- /Advent of Code/2016/04/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day4() 2 | input = joinpath(@__DIR__, "input.txt") 3 | list = readlines(input) .|> 4 | x -> eachmatch(r"([\w-]+)-(\d+)\[(\w+)\]", x) |> 5 | only |> x -> x.captures |> 6 | x -> (replace(x[1], "-" => ""), parse(Int, x[2]), x[3]) 7 | 8 | function name2checksum(name) 9 | keys = unique(name) 10 | d = Dict(k => count(==(k), name) for k ∈ keys) 11 | sd = sort(collect(d), by=x -> (-x[2], x[1])) 12 | first.(sd[1:5]) |> join 13 | end 14 | 15 | result₁ = sum(list) do (name, sid, checksum) 16 | name2checksum(name) == checksum ? sid : 0 17 | end 18 | 19 | function decrypt(name, sid) 20 | map(x -> (x - 'a' + sid) % ('z' - 'a' + 1) + 'a', name) 21 | end 22 | 23 | result₂ = only(sid for (name, sid, checksum) ∈ list 24 | if name2checksum(name) == checksum && 25 | contains(decrypt(name, sid), r"north|pole")) 26 | 27 | # @assert result₁ == 361724 28 | # @assert result₂ == 482 29 | 30 | result₁, result₂ 31 | end 32 | 33 | export day4 34 | -------------------------------------------------------------------------------- /Advent of Code/2016/05/input.txt: -------------------------------------------------------------------------------- 1 | ffykfhsq 2 | -------------------------------------------------------------------------------- /Advent of Code/2016/05/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day5() 2 | input = joinpath(@__DIR__, "input.txt") 3 | door_id = readline(input) 4 | 5 | function solve(id; part₂=false, pw=part₂ ? fill(' ', 8) : []) 6 | for index = Iterators.countfrom(0) 7 | hash = id * string(index) |> md5 |> bytes2hex 8 | if startswith(hash, "00000") 9 | if part₂ 10 | x = tryparse(Int, string(hash[6])) 11 | (isnothing(x) || x > 7) && continue 12 | (pw[x + 1] == ' ') && (pw[x + 1] = hash[7]) 13 | all(!=(' '), pw) && return join(pw) 14 | else 15 | push!(pw, hash[6]) 16 | length(pw) == 8 && return join(pw) 17 | end 18 | end 19 | end 20 | end 21 | 22 | result₁ = solve(door_id, part₂=false) 23 | result₂ = solve(door_id, part₂=true) 24 | 25 | # @assert result₁ == "c6697b55" 26 | # @assert result₂ == "8c35d1ab" 27 | 28 | result₁, result₂ 29 | end 30 | 31 | export day5 32 | -------------------------------------------------------------------------------- /Advent of Code/2016/06/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day6() 2 | input = joinpath(@__DIR__, "input.txt") 3 | messages = readlines(input) 4 | 5 | stats = [Dict() for _ = 1:length(first(messages))] 6 | 7 | for m ∈ messages 8 | for (i, c) ∈ enumerate(m) 9 | d = stats[i] 10 | d[c] = get(d, c, 0) + 1 11 | end 12 | end 13 | 14 | result₁, result₂ = map(stats) do d 15 | sd = sort(collect(d), by=x -> x[2]) 16 | first(last(sd)), first(first(sd)) 17 | end |> x -> join.((first.(x), last.(x))) 18 | 19 | # @assert result₁ == "usccerug" 20 | # @assert result₂ == "cnvvtafc" 21 | 22 | result₁, result₂ 23 | end 24 | 25 | export day6 26 | -------------------------------------------------------------------------------- /Advent of Code/2016/07/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day7() 2 | input = joinpath(@__DIR__, "input.txt") 3 | ips = readlines(input) 4 | 5 | function supportsTLS(ip) 6 | a = eachmatch(r"(\w)(\w)\2\1", ip) 7 | b = eachmatch(r"(\w)(\w)\2\1\w*\]", ip) 8 | cond₁ = any(x -> !=(x.captures...), a) 9 | cond₂ = !any(x -> !=(x.captures...), b) 10 | cond₁ & cond₂ 11 | end 12 | 13 | function supportsSSL(ip) 14 | ip = ip * "[" 15 | aba = eachmatch(r"(\w)(\w)\1\w*\[", ip, overlap=true) 16 | bab = eachmatch(r"(\w)(\w)\1\w*\]", ip, overlap=true) 17 | for m₁ ∈ aba 18 | c₁₁, c₁₂ = m₁.captures 19 | c₁₁ == c₁₂ && continue 20 | for m₂ ∈ bab 21 | c₂₁, c₂₂ = m₂.captures 22 | c₁₁ == c₂₂ && c₁₂ == c₂₁ && return true 23 | end 24 | end 25 | false 26 | end 27 | 28 | result₁ = count(supportsTLS, ips) 29 | result₂ = count(supportsSSL, ips) 30 | 31 | # @assert result₁ == 118 32 | # @assert result₂ == 260 33 | 34 | result₁, result₂ 35 | end 36 | 37 | export day7 38 | -------------------------------------------------------------------------------- /Advent of Code/2016/08/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day8() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | showscreen(x) = foreach(x -> println(x...), eachrow(x)) 5 | 6 | screen = fill(' ', (6, 50)) 7 | 8 | for line = eachline(input) 9 | tokens = split(line) 10 | if tokens[1] == "rect" 11 | a, b = parse.(Int, split(tokens[2], 'x')) 12 | screen[1:b,1:a] .= '█' 13 | elseif tokens[1] == "rotate" 14 | if tokens[2] == "row" 15 | y = parse(Int, replace(tokens[3], "y=" => "")) + 1 16 | offset = parse(Int, tokens[5]) 17 | new = fill(' ', size(screen, 2)) 18 | for (i, c) = enumerate(screen[y,:]) 19 | new[mod1(i + offset, size(screen, 2))] = c 20 | end 21 | screen[y,:] = new 22 | elseif tokens[2] == "column" 23 | x = parse(Int, replace(tokens[3], "x=" => "")) + 1 24 | offset = parse(Int, tokens[5]) 25 | new = fill(' ', size(screen, 1)) 26 | for (i, c) = enumerate(screen[:,x]) 27 | new[mod1(i + offset, size(screen, 1))] = c 28 | end 29 | screen[:,x] = new 30 | end 31 | end 32 | end 33 | 34 | result₁ = count(==('█'), screen) 35 | result₂ = showscreen(screen) 36 | 37 | # @assert result₁ == 110 38 | # @assert result₂ == "ZJHRKCPLYJ" 39 | 40 | result₁, result₂ 41 | end 42 | 43 | export day8 44 | -------------------------------------------------------------------------------- /Advent of Code/2016/09/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day9() 2 | input = joinpath(@__DIR__, "input.txt") 3 | s = readline(input) 4 | 5 | function decompress(s; limit=0) 6 | prev = 1 7 | counter = 0 8 | for m = eachmatch(r"(? 13 | x -> replace(x, r"[\(\)]" => "") |> 14 | x -> split(x, "x") .|> 15 | x -> parse(Int, x) 16 | counter += length(s[prev:i - 1]) 17 | counter += n * (limit == 1 ? l : decompress(s[range(j, length=l)], limit=limit - 1)) 18 | prev = j + l 19 | end 20 | counter += length(s[prev:end]) 21 | end 22 | 23 | result₁ = decompress(s, limit=1) 24 | result₂ = decompress(s) 25 | 26 | # @assert result₁ == 97714 27 | # @assert result₂ == 10762972461 28 | 29 | result₁, result₂ 30 | end 31 | 32 | export day9 33 | -------------------------------------------------------------------------------- /Advent of Code/2016/11/input.txt: -------------------------------------------------------------------------------- 1 | The first floor contains a strontium generator, a strontium-compatible microchip, a plutonium generator, and a plutonium-compatible microchip. 2 | The second floor contains a thulium generator, a ruthenium generator, a ruthenium-compatible microchip, a curium generator, and a curium-compatible microchip. 3 | The third floor contains a thulium-compatible microchip. 4 | The fourth floor contains nothing relevant. 5 | -------------------------------------------------------------------------------- /Advent of Code/2016/12/input.txt: -------------------------------------------------------------------------------- 1 | cpy 1 a 2 | cpy 1 b 3 | cpy 26 d 4 | jnz c 2 5 | jnz 1 5 6 | cpy 7 c 7 | inc d 8 | dec c 9 | jnz c -2 10 | cpy a c 11 | inc a 12 | dec b 13 | jnz b -2 14 | cpy c b 15 | dec d 16 | jnz d -6 17 | cpy 16 c 18 | cpy 12 d 19 | inc a 20 | dec d 21 | jnz d -2 22 | dec c 23 | jnz c -5 24 | -------------------------------------------------------------------------------- /Advent of Code/2016/12/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day12() 2 | input = joinpath(@__DIR__, "input.txt") 3 | program = split.(readlines(input)) 4 | 5 | function compute!(registers; ip=1) 6 | while 1 <= ip <= length(program) 7 | tokens = program[ip] 8 | instruction = first(tokens) 9 | 10 | if instruction == "cpy" 11 | x, xi = tokens[2], tryparse(Int, tokens[2]) 12 | x = isnothing(xi) ? registers[x] : xi 13 | y = tokens[3] 14 | registers[y] = x 15 | ip += 1 16 | elseif instruction == "inc" 17 | x = tokens[2] 18 | registers[x] += 1 19 | ip += 1 20 | elseif instruction == "dec" 21 | x = tokens[2] 22 | registers[x] -= 1 23 | ip += 1 24 | elseif instruction == "jnz" 25 | x, xi = tokens[2], tryparse(Int, tokens[2]) 26 | x = isnothing(xi) ? registers[x] : xi 27 | y = parse(Int, tokens[3]) 28 | ip += (!iszero(x) ? y : 1) 29 | end 30 | end 31 | 32 | registers 33 | end 34 | 35 | result₁ = compute!(Dict(("a", "b", "c", "d") .=> (0, 0, 0, 0)))["a"] 36 | result₂ = compute!(Dict(("a", "b", "c", "d") .=> (0, 0, 1, 0)))["a"] 37 | 38 | # @assert result₁ == 318003 39 | # @assert result₂ == 9227657 40 | 41 | result₁, result₂ 42 | end 43 | 44 | export day12 45 | -------------------------------------------------------------------------------- /Advent of Code/2016/13/input.txt: -------------------------------------------------------------------------------- 1 | 1358 2 | -------------------------------------------------------------------------------- /Advent of Code/2016/14/input.txt: -------------------------------------------------------------------------------- 1 | ihaygndm 2 | -------------------------------------------------------------------------------- /Advent of Code/2016/14/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day14() 2 | function gethash(hashes, salt, i, stretch=false) 3 | if haskey(hashes, i) 4 | hashes[i] 5 | else 6 | hash = bytes2hex(md5(salt * string(i))) 7 | if stretch 8 | for _ = 1:2016 9 | hash = bytes2hex(md5(hash)) 10 | end 11 | end 12 | hashes[i] = hash 13 | end 14 | end 15 | 16 | function isvalid(hashes, salt, i, stretch=false) 17 | hash = gethash(hashes, salt, i, stretch) 18 | ms = eachmatch(r"(.)\1{2,}", hash) 19 | if !isempty(ms) 20 | c = only(first(ms).captures) 21 | for id = range(i + 1, length=1000) 22 | hash = gethash(hashes, salt, id, stretch) 23 | m = eachmatch(Regex("$(c){5,}"), hash) 24 | !isempty(m) && return true 25 | end 26 | end 27 | return false 28 | end 29 | 30 | function solve(salt; stretch=false) 31 | new_keys = Set{Int}() 32 | hashes = Dict{Int,String}() 33 | for i = Iterators.countfrom(0) 34 | isvalid(hashes, salt, i, stretch) && push!(new_keys, i) 35 | length(new_keys) == 64 && break 36 | end 37 | maximum(new_keys) 38 | end 39 | 40 | input = joinpath(@__DIR__, "input.txt") 41 | salt = readline(input) 42 | 43 | result₁ = solve(salt, stretch=false) 44 | result₂ = solve(salt, stretch=true) 45 | 46 | # @assert result₁ == 15035 47 | # @assert result₂ == 19968 48 | 49 | result₁, result₂ 50 | end 51 | 52 | export day14 53 | -------------------------------------------------------------------------------- /Advent of Code/2016/15/input.txt: -------------------------------------------------------------------------------- 1 | Disc #1 has 5 positions; at time=0, it is at position 2. 2 | Disc #2 has 13 positions; at time=0, it is at position 7. 3 | Disc #3 has 17 positions; at time=0, it is at position 10. 4 | Disc #4 has 3 positions; at time=0, it is at position 2. 5 | Disc #5 has 19 positions; at time=0, it is at position 9. 6 | Disc #6 has 7 positions; at time=0, it is at position 0. 7 | -------------------------------------------------------------------------------- /Advent of Code/2016/15/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day15() 2 | position(disc, t) = mod(disc.offset + t, disc.period) 3 | 4 | function solve(discs) 5 | accum_period = 1 6 | time_wait = 0 7 | for (i, discᵢ) = enumerate(discs) 8 | new_period = lcm(accum_period, discᵢ.period) 9 | for t = time_wait:accum_period:new_period 10 | if position(discᵢ, t + i) == 0 11 | accum_period = new_period 12 | time_wait = t 13 | break 14 | end 15 | end 16 | end 17 | time_wait 18 | end 19 | 20 | # -- Parse Input -- # 21 | 22 | rx = r"Disc #\d+ has (\d+) positions; at time=\d+, it is at position (\d+)." 23 | input = joinpath(@__DIR__, "input.txt") 24 | 25 | discs = map(eachmatch(rx, read(input, String))) do m 26 | a, b = parse.(Int, m.captures) 27 | (period = a, offset = b) 28 | end 29 | 30 | # -- Part One -- # 31 | 32 | result₁ = solve(discs) 33 | 34 | # -- Part Two -- # 35 | 36 | new_disc = (period = 11, offset = 0) 37 | push!(discs, new_disc) 38 | 39 | result₂ = solve(discs) 40 | 41 | # @assert result₁ == 148737 42 | # @assert result₂ == 2353212 43 | 44 | result₁, result₂ 45 | end 46 | 47 | export day15 48 | -------------------------------------------------------------------------------- /Advent of Code/2016/16/input.txt: -------------------------------------------------------------------------------- 1 | 11101000110010100 2 | -------------------------------------------------------------------------------- /Advent of Code/2016/16/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day16() 2 | input = joinpath(@__DIR__, "input.txt") 3 | a = readline(input) 4 | 5 | function ~(s::String) 6 | join(UInt8[c == '0' for c in s]) 7 | end 8 | 9 | function unfold(a) 10 | b = ~(reverse(a)) 11 | a * '0' * b 12 | end 13 | 14 | function checksum(a) 15 | result = map(Iterators.partition(a, 2)) do p 16 | p[1] == p[2] ? '1' : '0' 17 | end |> join 18 | iseven(length(result)) ? checksum(result) : result 19 | end 20 | 21 | function filldisk(a, minlength) 22 | while length(a) < minlength 23 | a = unfold(a) 24 | end 25 | a = first(a, minlength) 26 | checksum(a) 27 | end 28 | 29 | result₁ = filldisk(a, 272) 30 | result₂ = filldisk(a, 35651584) 31 | 32 | # @assert result₁ == "10100101010101101" 33 | # @assert result₂ == "01100001101101001" 34 | 35 | result₁, result₂ 36 | end 37 | 38 | export day16 39 | -------------------------------------------------------------------------------- /Advent of Code/2016/17/input.txt: -------------------------------------------------------------------------------- 1 | veumntbg 2 | -------------------------------------------------------------------------------- /Advent of Code/2016/17/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day17() 2 | input = joinpath(@__DIR__, "input.txt") 3 | passcode = readline(input) 4 | 5 | function explore(passcode) 6 | function bfs(node₀, target) 7 | char2step = let 8 | ks = collect("UDLR") 9 | vs = CartesianIndex.([(0, -1), (0, 1), (-1, 0), (1, 0)]) 10 | Dict(ks .=> vs) 11 | end 12 | 13 | isopen(door::Char) = 'b' <= door <= 'f' 14 | 15 | paths = Set{String}() 16 | 17 | Node = Tuple{CartesianIndex,String} 18 | queue = Node[node₀] # Nodes to be explored. 19 | 20 | while !isempty(queue) 21 | pos, path = popfirst!(queue) 22 | if pos == target 23 | push!(paths, replace(path, passcode => "")) 24 | else 25 | hash = bytes2hex(md5(path)) 26 | for (door, c) = zip(first(hash, 4), "UDLR") 27 | pos⁺ = pos + char2step[c] 28 | if isopen(door) && all(x -> 1 <= x <= 4, pos⁺.I) 29 | push!(queue, (pos⁺, path * c)) 30 | end 31 | end 32 | end 33 | end 34 | 35 | paths 36 | end 37 | 38 | node₀ = (CartesianIndex(1, 1), passcode) 39 | bfs(node₀, CartesianIndex(4, 4)) 40 | end 41 | 42 | paths = explore(passcode) 43 | minl, maxl = extrema(length, paths) 44 | result₁ = filter(x -> length(x) == minl, paths) |> first 45 | result₂ = maxl 46 | 47 | # @assert result₁ == "DDRRULRDRD" 48 | # @assert result₂ == 536 49 | 50 | result₁, result₂ 51 | end 52 | 53 | export day17 54 | -------------------------------------------------------------------------------- /Advent of Code/2016/18/input.txt: -------------------------------------------------------------------------------- 1 | .^^^.^.^^^^^..^^^..^..^..^^..^.^.^.^^.^^....^.^...^.^^.^^.^^..^^..^.^..^^^.^^...^...^^....^^.^^^^^^^ 2 | -------------------------------------------------------------------------------- /Advent of Code/2016/18/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day18() 2 | input = joinpath(@__DIR__, "input.txt") 3 | row₁ = readline(input) 4 | 5 | function isatrap(left, center, right) 6 | s₁ = left == center == '^' && (isnothing(right) || right == '.') 7 | s₂ = center == right == '^' && (isnothing(left) || left == '.') 8 | s₃ = left == '^' && center == '.' && (isnothing(right) || right == '.') 9 | s₄ = right == '^' && center == '.' && (isnothing(left) || left == '.') 10 | s₁ | s₂ | s₃ | s₄ 11 | end 12 | 13 | function nextrow(tiles) 14 | map(1:length(tiles)) do i 15 | center = tiles[i] 16 | left = i > 1 ? tiles[i - 1] : nothing 17 | right = i < length(tiles) ? tiles[i + 1] : nothing 18 | isatrap(left, center, right) ? '^' : '.' 19 | end 20 | end 21 | 22 | function calculaterows(row₁, n) 23 | rows = [collect(row₁)] 24 | for i = 2:n 25 | push!(rows, nextrow(rows[end])) 26 | end 27 | reduce(hcat, rows) 28 | end 29 | 30 | rows = calculaterows(row₁, 40) 31 | result₁ = count(==('.'), rows) 32 | 33 | rows = calculaterows(row₁, 400000) 34 | result₂ = count(==('.'), rows) 35 | 36 | # @assert result₁ == 1939 37 | # @assert result₂ == 19999535 38 | 39 | result₁, result₂ 40 | end 41 | 42 | export day18 43 | -------------------------------------------------------------------------------- /Advent of Code/2016/19/input.txt: -------------------------------------------------------------------------------- 1 | 3004953 2 | -------------------------------------------------------------------------------- /Advent of Code/2016/19/puzzle.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Singly-Linked Circular List (SLCL) 3 | """ 4 | mutable struct SLCL 5 | curr::Int 6 | list::Array 7 | num_items::Int 8 | 9 | function SLCL(list) 10 | slcl = similar(list) 11 | foreach(enumerate(list)) do (pos, x) 12 | # Indexing an element gives the element that comes after it 13 | slcl[x] = list[mod1(pos + 1, length(list))] 14 | end 15 | new(1, slcl, length(slcl)) 16 | end 17 | end 18 | 19 | function iterate!(slcl::SLCL) 20 | slcl.curr = slcl.list[slcl.curr] 21 | end 22 | 23 | function length(slcl::SLCL) 24 | slcl.num_items 25 | end 26 | 27 | function removenext!(slcl::SLCL) 28 | # "Stitch" gap from the removal 29 | slcl.list[slcl.curr] = slcl.list[slcl.list[slcl.curr]] 30 | slcl.num_items -= 1 31 | slcl 32 | end 33 | 34 | function day19() 35 | function part₁(elves) 36 | slcl = SLCL(elves) 37 | while length(slcl) > 1 38 | removenext!(slcl) 39 | iterate!(slcl) 40 | end 41 | slcl.curr 42 | end 43 | 44 | function part₂(elves) 45 | slcl = SLCL(elves) 46 | # Move the pointer across the circle 47 | for _ = 2:length(slcl) ÷ 2 48 | iterate!(slcl) 49 | end 50 | while length(slcl) > 1 51 | removenext!(slcl) 52 | iseven(length(slcl)) && iterate!(slcl) 53 | end 54 | slcl.curr 55 | end 56 | 57 | input = joinpath(@__DIR__, "input.txt") 58 | num_elves = parse(Int, readline(input)) 59 | elves = 1:num_elves 60 | 61 | result₁ = part₁(elves) 62 | result₂ = part₂(elves) 63 | 64 | # @assert result₁ == 1815603 65 | # @assert result₂ == 1410630 66 | 67 | result₁, result₂ 68 | end 69 | 70 | export day19 71 | -------------------------------------------------------------------------------- /Advent of Code/2016/20/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day20() 2 | input = joinpath(@__DIR__, "input.txt") 3 | blockedIPs = map(eachline(input)) do line 4 | a, b = parse.(Int, split(line, '-')) 5 | a:b 6 | end 7 | 8 | simplified = false 9 | while !simplified 10 | activity = false 11 | for i₁ = 1:length(blockedIPs) - 1 12 | for i₂ = i₁ + 1:length(blockedIPs) 13 | r₁ = blockedIPs[i₁] 14 | r₂ = blockedIPs[i₂] 15 | 16 | r₁_min, r₁_max = extrema(r₁) 17 | r₂_min, r₂_max = extrema(r₂) 18 | 19 | # If there is an overlap, merge the ranges. 20 | if any(x -> r₁_min - 1 <= x <= r₁_max + 1, (r₂_min, r₂_max)) || 21 | any(x -> r₂_min - 1 <= x <= r₂_max + 1, (r₁_min, r₁_max)) 22 | blockedIPs[i₁] = min(r₁_min, r₂_min):max(r₁_max, r₂_max) 23 | deleteat!(blockedIPs, i₂) 24 | activity = true 25 | break 26 | end 27 | end 28 | activity && break 29 | end 30 | !activity && (simplified = true) 31 | end 32 | 33 | isblocked(IP, blockedIPs) = any(x -> IP ∈ x, blockedIPs) 34 | 35 | IPs = 0:typemax(UInt32) 36 | result₁ = IPs[findfirst(x -> !isblocked(x, blockedIPs), IPs)] 37 | result₂ = length(IPs) - sum(length, blockedIPs) 38 | 39 | # @assert result₁ == 22887907 40 | # @assert result₂ == 109 41 | 42 | result₁, result₂ 43 | end 44 | 45 | export day20 46 | -------------------------------------------------------------------------------- /Advent of Code/2016/Project.toml: -------------------------------------------------------------------------------- 1 | name = "AdventOfCode2016" 2 | uuid = "58431eaf-e7ad-48ce-9a0d-e50210bea6f0" 3 | authors = ["Henrique Ferrolho "] 4 | version = "0.1.0" 5 | 6 | [deps] 7 | BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" 8 | Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" 9 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 10 | MD5 = "6ac74813-4b46-53a4-afec-0b5dc9d7885c" 11 | Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" 12 | -------------------------------------------------------------------------------- /Advent of Code/2016/README.md: -------------------------------------------------------------------------------- 1 | Start the Julia REPL from within this folder. 2 | -------------------------------------------------------------------------------- /Advent of Code/2016/src/AdventOfCode2016.jl: -------------------------------------------------------------------------------- 1 | module AdventOfCode2016 2 | 3 | using BenchmarkTools 4 | using Combinatorics 5 | using LinearAlgebra 6 | using MD5 7 | 8 | import Base.length 9 | 10 | greet() = println("Hello, Advent of Code 2016!") 11 | 12 | include("../04/puzzle.jl") 13 | include("../05/puzzle.jl") 14 | include("../06/puzzle.jl") 15 | include("../07/puzzle.jl") 16 | include("../08/puzzle.jl") 17 | include("../09/puzzle.jl") 18 | include("../10/puzzle.jl") 19 | include("../11/puzzle.jl") 20 | include("../12/puzzle.jl") 21 | include("../13/puzzle.jl") 22 | include("../14/puzzle.jl") 23 | include("../15/puzzle.jl") 24 | include("../16/puzzle.jl") 25 | include("../17/puzzle.jl") 26 | include("../18/puzzle.jl") 27 | include("../19/puzzle.jl") 28 | include("../20/puzzle.jl") 29 | include("../21/puzzle.jl") 30 | 31 | end # module 32 | -------------------------------------------------------------------------------- /Advent of Code/2017/01/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | for line in sys.stdin: 8 | line = line.strip() + line[0] 9 | 10 | sum = 0 11 | for i in range(len(line) - 1): 12 | if line[i] == line[i + 1]: 13 | sum += int(line[i]) 14 | 15 | print(sum) 16 | 17 | 18 | if __name__ == '__main__': 19 | main() 20 | -------------------------------------------------------------------------------- /Advent of Code/2017/01/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | for line in sys.stdin: 8 | line = line.strip() 9 | 10 | sum = 0 11 | for a in range(len(line)): 12 | b = (a + int(len(line) / 2)) % len(line) 13 | if line[a] == line[b]: 14 | sum += int(line[a]) 15 | 16 | print(sum) 17 | 18 | 19 | if __name__ == '__main__': 20 | main() 21 | -------------------------------------------------------------------------------- /Advent of Code/2017/02/input.txt: -------------------------------------------------------------------------------- 1 | 409 194 207 470 178 454 235 333 511 103 474 293 525 372 408 428 2 | 4321 2786 6683 3921 265 262 6206 2207 5712 214 6750 2742 777 5297 3764 167 3 | 3536 2675 1298 1069 175 145 706 2614 4067 4377 146 134 1930 3850 213 4151 4 | 2169 1050 3705 2424 614 3253 222 3287 3340 2637 61 216 2894 247 3905 214 5 | 99 797 80 683 789 92 736 318 103 153 749 631 626 367 110 805 6 | 2922 1764 178 3420 3246 3456 73 2668 3518 1524 273 2237 228 1826 182 2312 7 | 2304 2058 286 2258 1607 2492 2479 164 171 663 62 144 1195 116 2172 1839 8 | 114 170 82 50 158 111 165 164 106 70 178 87 182 101 86 168 9 | 121 110 51 122 92 146 13 53 34 112 44 160 56 93 82 98 10 | 4682 642 397 5208 136 4766 180 1673 1263 4757 4680 141 4430 1098 188 1451 11 | 158 712 1382 170 550 913 191 163 459 1197 1488 1337 900 1182 1018 337 12 | 4232 236 3835 3847 3881 4180 4204 4030 220 1268 251 4739 246 3798 1885 3244 13 | 169 1928 3305 167 194 3080 2164 192 3073 1848 426 2270 3572 3456 217 3269 14 | 140 1005 2063 3048 3742 3361 117 93 2695 1529 120 3480 3061 150 3383 190 15 | 489 732 57 75 61 797 266 593 324 475 733 737 113 68 267 141 16 | 3858 202 1141 3458 2507 239 199 4400 3713 3980 4170 227 3968 1688 4352 4168 17 | -------------------------------------------------------------------------------- /Advent of Code/2017/02/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | sum = 0 8 | for line in sys.stdin: 9 | values = [int(x) for x in line.strip().split()] 10 | sum += max(values) - min(values) 11 | print(sum) 12 | 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /Advent of Code/2017/02/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | sum = 0 8 | 9 | for line in sys.stdin: 10 | values = [int(x) for x in line.strip().split()] 11 | 12 | goToNextLine = False 13 | 14 | for i in range(len(values)): 15 | for j in range(len(values)): 16 | if i == j: 17 | continue 18 | 19 | if values[i] % values[j] == 0: 20 | sum += values[i] / values[j] 21 | goToNextLine = True 22 | break 23 | 24 | if goToNextLine: 25 | break 26 | 27 | print(sum) 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /Advent of Code/2017/03/input.txt: -------------------------------------------------------------------------------- 1 | 347991 2 | -------------------------------------------------------------------------------- /Advent of Code/2017/03/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import sys 5 | 6 | 7 | VELOCITIES = [[1, 0], [0, 1], [-1, 0], [0, -1]] 8 | 9 | 10 | def main(): 11 | for line in sys.stdin: 12 | distance = int(line.strip()) 13 | 14 | position = np.array([0, 0]) 15 | velocityIndex = 0 16 | 17 | counter = 1 18 | 19 | for steps in [i for i in range(1, 1000) for _ in range(2)]: 20 | for i in range(steps): 21 | position += VELOCITIES[velocityIndex] 22 | counter += 1 23 | 24 | # print(counter, position, sum(np.absolute(position))) 25 | if counter == distance: 26 | break 27 | 28 | velocityIndex = (velocityIndex + 1) % 4 29 | if counter == distance: 30 | break 31 | 32 | print(counter, position, sum(np.absolute(position))) 33 | 34 | 35 | if __name__ == '__main__': 36 | main() 37 | -------------------------------------------------------------------------------- /Advent of Code/2017/03/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import sys 5 | 6 | 7 | VELOCITIES = [[1, 0], [0, 1], [-1, 0], [0, -1]] 8 | 9 | 10 | def sumOfNeighbours(gridMap, x, y): 11 | sum = 0 12 | for i in range(-1, 2): 13 | for j in range(-1, 2): 14 | if (x + i, y + j) in gridMap: 15 | sum += gridMap[(x + i, y + j)] 16 | return sum 17 | 18 | 19 | def main(): 20 | gridMap = {} 21 | gridMap[(0, 0)] = 1 22 | 23 | for line in sys.stdin: 24 | distance = int(line.strip()) 25 | 26 | position = np.array([0, 0]) 27 | velocityIndex = 0 28 | 29 | done = False 30 | 31 | for steps in [i for i in range(1, 1000) for _ in range(2)]: 32 | for i in range(steps): 33 | position += VELOCITIES[velocityIndex] 34 | sum = sumOfNeighbours(gridMap, position[0], position[1]) 35 | gridMap[(position[0], position[1])] = sum 36 | 37 | print(position, "<-", sum) 38 | if sum > distance: 39 | done = True 40 | break 41 | 42 | velocityIndex = (velocityIndex + 1) % 4 43 | if done: 44 | break 45 | 46 | print() 47 | print(" Answer:", gridMap[(position[0], position[1])]) 48 | print() 49 | 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /Advent of Code/2017/04/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | counterValid = 0 8 | counterInvalid = 0 9 | 10 | for line in sys.stdin: 11 | tokens = line.strip().split() 12 | 13 | if len(tokens) != len(set(tokens)): 14 | counterInvalid += 1 15 | else: 16 | counterValid += 1 17 | 18 | print("Valid:", counterValid) 19 | print("Invalid:", counterInvalid) 20 | 21 | 22 | if __name__ == '__main__': 23 | main() 24 | -------------------------------------------------------------------------------- /Advent of Code/2017/04/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | counterValid = 0 8 | counterInvalid = 0 9 | 10 | for line in sys.stdin: 11 | tokens = line.strip().split() 12 | tokens = [''.join(sorted(token)) for token in tokens] 13 | 14 | if len(tokens) != len(set(tokens)): 15 | counterInvalid += 1 16 | else: 17 | counterValid += 1 18 | 19 | print("Valid:", counterValid) 20 | print("Invalid:", counterInvalid) 21 | 22 | 23 | if __name__ == '__main__': 24 | main() 25 | -------------------------------------------------------------------------------- /Advent of Code/2017/05/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | instructions = [int(jump.strip()) for jump in sys.stdin] 8 | current = 0 9 | counter = 0 10 | 11 | while 0 <= current and current < len(instructions): 12 | currentAux = current 13 | current += instructions[current] 14 | instructions[currentAux] += 1 15 | counter += 1 16 | 17 | print(" Steps taken until exit:", counter) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /Advent of Code/2017/05/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | instructions = [int(jump.strip()) for jump in sys.stdin] 8 | current = 0 9 | counter = 0 10 | 11 | while 0 <= current and current < len(instructions): 12 | currentAux = current 13 | current += instructions[current] 14 | if instructions[currentAux] >= 3: 15 | instructions[currentAux] -= 1 16 | else: 17 | instructions[currentAux] += 1 18 | counter += 1 19 | 20 | print(" Steps taken until exit:", counter) 21 | 22 | 23 | if __name__ == '__main__': 24 | main() 25 | -------------------------------------------------------------------------------- /Advent of Code/2017/06/input.txt: -------------------------------------------------------------------------------- 1 | 4 1 15 12 0 9 9 5 5 8 7 3 14 5 12 3 2 | -------------------------------------------------------------------------------- /Advent of Code/2017/06/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | for line in sys.stdin: 8 | seenStates = set() 9 | 10 | counter = 0 11 | state = [int(blocks) for blocks in line.strip().split()] 12 | print(state) 13 | 14 | done = False 15 | 16 | while not done: 17 | maxBankIndex = state.index(max(state)) 18 | blocks = state[maxBankIndex] 19 | state[maxBankIndex] = 0 20 | 21 | while (blocks): 22 | maxBankIndex = (maxBankIndex + 1) % len(state) 23 | state[maxBankIndex] += 1 24 | blocks -= 1 25 | 26 | counter += 1 27 | 28 | if tuple(state) in seenStates: 29 | print(counter) 30 | done = True 31 | 32 | seenStates.add(tuple(state)) 33 | 34 | 35 | if __name__ == '__main__': 36 | main() 37 | -------------------------------------------------------------------------------- /Advent of Code/2017/06/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | for line in sys.stdin: 8 | seenStates = set() 9 | 10 | counter = 0 11 | state = [int(blocks) for blocks in line.strip().split()] 12 | print(state) 13 | 14 | seenCounter = 0 15 | 16 | while seenCounter < 2: 17 | maxBankIndex = state.index(max(state)) 18 | blocks = state[maxBankIndex] 19 | state[maxBankIndex] = 0 20 | 21 | while (blocks): 22 | maxBankIndex = (maxBankIndex + 1) % len(state) 23 | state[maxBankIndex] += 1 24 | blocks -= 1 25 | 26 | counter += 1 27 | 28 | if tuple(state) in seenStates: 29 | print(counter) 30 | seenStates.clear() 31 | seenCounter += 1 32 | counter = 0 33 | 34 | seenStates.add(tuple(state)) 35 | 36 | 37 | if __name__ == '__main__': 38 | main() 39 | -------------------------------------------------------------------------------- /Advent of Code/2017/07/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | class Node: 7 | def __init__(self, name, weight): 8 | self.name = name 9 | self.weight = weight 10 | self.children = [] 11 | self.parent = None 12 | 13 | def __str__(self): 14 | return self.name + ' ' + str(self.weight) + ': ' + ', '.join(self.children) 15 | 16 | 17 | def main(): 18 | # A map of all the nodes indexed by their names. 19 | nameToNode = {} 20 | 21 | for line in sys.stdin: 22 | tokens = line.strip().split('->') 23 | 24 | name, weightRaw = tokens[0].split() 25 | weight = int(weightRaw[weightRaw.index('(') + 1:weightRaw.rindex(')')]) 26 | 27 | nameToNode[name] = Node(name, weight) 28 | 29 | if len(tokens) == 2: 30 | children = [x.strip() for x in tokens[1].split(',')] 31 | nameToNode[name].children = children 32 | 33 | # At this point we have a map with all the existing nodes, 34 | # but the only existing relationship is from parent to child. 35 | 36 | # This loop assigns a parent to every node but the root. 37 | for name in nameToNode: 38 | for child in nameToNode[name].children: 39 | nameToNode[child].parent = name 40 | 41 | root = '' 42 | 43 | # Find the node with no parent, i.e. the root. 44 | for name in nameToNode: 45 | if nameToNode[name].parent is None: 46 | root = name 47 | break 48 | 49 | print(root) 50 | 51 | 52 | if __name__ == '__main__': 53 | main() 54 | -------------------------------------------------------------------------------- /Advent of Code/2017/08/puzzle1and2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import operator 4 | import sys 5 | 6 | ops = { 7 | '<': operator.lt, '<=': operator.le, 8 | '==': operator.eq, '!=': operator.ne, 9 | '>=': operator.ge, '>': operator.gt 10 | } 11 | 12 | 13 | def main(): 14 | registers = {} 15 | maximumObserved = 0 16 | 17 | for line in sys.stdin: 18 | instruction, condition = line.strip().split('if') 19 | 20 | register, sign, amount = instruction.split() 21 | lhs, op, rhs = condition.split() 22 | 23 | sign = +1 if sign == 'inc' else -1 24 | amount = int(amount) 25 | rhs = int(rhs) 26 | 27 | if register not in registers: 28 | registers[register] = 0 29 | if lhs not in registers: 30 | registers[lhs] = 0 31 | 32 | if ops[op](registers[lhs], rhs): 33 | registers[register] += sign * amount 34 | 35 | if registers[register] > maximumObserved: 36 | maximumObserved = registers[register] 37 | 38 | maximum = max(registers, key=registers.get) 39 | 40 | print(' Maximum at the end:', registers[maximum]) 41 | print(' Maximum observed:', maximumObserved) 42 | 43 | 44 | if __name__ == '__main__': 45 | main() 46 | -------------------------------------------------------------------------------- /Advent of Code/2017/09/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from enum import Enum 4 | import sys 5 | 6 | 7 | class State(Enum): 8 | NOMINAL = 0 9 | GARBAGE = 1 10 | IGNORE = 2 11 | 12 | 13 | def main(): 14 | for line in sys.stdin: 15 | state = State.NOMINAL 16 | level = 0 17 | score = 0 18 | 19 | for char in line.strip(): 20 | if state is State.NOMINAL: 21 | if char == '{': 22 | level += 1 23 | elif char == '}': 24 | score += level 25 | level -= 1 26 | elif char == '<': 27 | state = State.GARBAGE 28 | elif state is State.GARBAGE: 29 | if char == '>': 30 | state = State.NOMINAL 31 | elif char == '!': 32 | state = state.IGNORE 33 | elif state is State.IGNORE: 34 | state = State.GARBAGE 35 | 36 | print(score) 37 | 38 | 39 | if __name__ == '__main__': 40 | main() 41 | -------------------------------------------------------------------------------- /Advent of Code/2017/09/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from enum import Enum 4 | import sys 5 | 6 | 7 | class State(Enum): 8 | NOMINAL = 0 9 | GARBAGE = 1 10 | IGNORE = 2 11 | 12 | 13 | def main(): 14 | for line in sys.stdin: 15 | state = State.NOMINAL 16 | level = 0 17 | score = 0 18 | counter = 0 19 | 20 | for char in line.strip(): 21 | if state is State.NOMINAL: 22 | if char == '{': 23 | level += 1 24 | elif char == '}': 25 | score += level 26 | level -= 1 27 | elif char == '<': 28 | state = State.GARBAGE 29 | elif state is State.GARBAGE: 30 | if char == '>': 31 | state = State.NOMINAL 32 | elif char == '!': 33 | state = state.IGNORE 34 | else: 35 | counter += 1 36 | elif state is State.IGNORE: 37 | state = State.GARBAGE 38 | 39 | print(counter) 40 | 41 | 42 | if __name__ == '__main__': 43 | main() 44 | -------------------------------------------------------------------------------- /Advent of Code/2017/10/input.txt: -------------------------------------------------------------------------------- 1 | 106,118,236,1,130,0,235,254,59,205,2,87,129,25,255,118 2 | -------------------------------------------------------------------------------- /Advent of Code/2017/10/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def reverseSublist(lst, start, end): 7 | while start < end: 8 | lst[start % len(lst)], lst[end % len(lst)] = lst[end % len(lst)], lst[start % len(lst)] 9 | 10 | start += 1 11 | end -= 1 12 | 13 | return lst 14 | 15 | 16 | def main(): 17 | for line in sys.stdin: 18 | lst = [x for x in range(256)] 19 | currentPosition = 0 20 | skipSize = 0 21 | lengths = [int(x) for x in line.strip().split(',')] 22 | 23 | for length in lengths: 24 | lst = reverseSublist(lst, currentPosition, currentPosition + length - 1) 25 | currentPosition = (currentPosition + length + skipSize) % len(lst) 26 | skipSize += 1 27 | 28 | print(lst[0] * lst[1]) 29 | 30 | 31 | if __name__ == '__main__': 32 | main() 33 | -------------------------------------------------------------------------------- /Advent of Code/2017/10/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import sys 5 | 6 | 7 | def reverseSublist(lst, start, end): 8 | while start < end: 9 | lst[start % len(lst)], lst[end % len(lst)] = lst[end % len(lst)], lst[start % len(lst)] 10 | 11 | start += 1 12 | end -= 1 13 | 14 | return lst 15 | 16 | 17 | def main(): 18 | for line in sys.stdin: 19 | lst = [x for x in range(256)] 20 | currentPosition = 0 21 | skipSize = 0 22 | lengths = [ord(x) for x in line.strip()] + [17, 31, 73, 47, 23] 23 | lengths *= 64 24 | 25 | for length in lengths: 26 | lst = reverseSublist(lst, currentPosition, currentPosition + length - 1) 27 | currentPosition = (currentPosition + length + skipSize) % len(lst) 28 | skipSize += 1 29 | 30 | denseHash = [] 31 | for x in range(0, 255, 16): 32 | denseHash.append(np.bitwise_xor.reduce(lst[x:x + 16])) 33 | 34 | knotHash = ''.join('%02x' % i for i in denseHash) 35 | print(knotHash) 36 | 37 | 38 | if __name__ == '__main__': 39 | main() 40 | -------------------------------------------------------------------------------- /Advent of Code/2017/11/cube-coordinates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ferrolho/coding-challenges/f4309f262fa491ac78908841e66772c8a47bdc34/Advent of Code/2017/11/cube-coordinates.png -------------------------------------------------------------------------------- /Advent of Code/2017/11/puzzle1and2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import sys 5 | 6 | cubeDirections = { 7 | 'se': (+1, -1, 0), 'ne': (+1, 0, -1), 'n': (0, +1, -1), 8 | 'nw': (-1, +1, 0), 'sw': (-1, 0, +1), 's': (0, -1, +1) 9 | } 10 | 11 | 12 | def cubeDistance(a, b): 13 | return int((abs(a[0] - b[0]) + abs(a[1] - b[1]) + abs(a[2] - b[2])) / 2) 14 | 15 | 16 | def main(): 17 | for line in sys.stdin: 18 | position = (0, 0, 0) 19 | steps = [dir for dir in line.strip().split(',')] 20 | maximumDistance = 0 21 | 22 | for step in steps: 23 | position = np.add(position, cubeDirections[step]) 24 | currentDistance = cubeDistance((0, 0, 0), position) 25 | 26 | if currentDistance > maximumDistance: 27 | maximumDistance = currentDistance 28 | 29 | print('Current distance:', cubeDistance((0, 0, 0), position)) 30 | print('Maximum distance:', maximumDistance) 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /Advent of Code/2017/12/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import networkx as nx 4 | import sys 5 | 6 | 7 | def main(): 8 | village = nx.Graph() 9 | 10 | for line in sys.stdin: 11 | node, neighbours = line.strip().split(' <-> ') 12 | 13 | node = int(node) 14 | neighbours = [int(x.strip()) for x in neighbours.split(',')] 15 | 16 | for neighbour in neighbours: 17 | village.add_edge(node, neighbour) 18 | 19 | print(len(nx.shortest_path(village, 0).keys())) 20 | 21 | 22 | if __name__ == '__main__': 23 | main() 24 | -------------------------------------------------------------------------------- /Advent of Code/2017/12/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import networkx as nx 4 | import sys 5 | 6 | 7 | def main(): 8 | village = nx.Graph() 9 | 10 | for line in sys.stdin: 11 | node, neighbours = line.strip().split(' <-> ') 12 | 13 | node = int(node) 14 | neighbours = [int(x.strip()) for x in neighbours.split(',')] 15 | 16 | for neighbour in neighbours: 17 | village.add_edge(node, neighbour) 18 | 19 | print(nx.number_connected_components(village)) 20 | 21 | 22 | if __name__ == '__main__': 23 | main() 24 | -------------------------------------------------------------------------------- /Advent of Code/2017/13/input.txt: -------------------------------------------------------------------------------- 1 | 0: 5 2 | 1: 2 3 | 2: 3 4 | 4: 4 5 | 6: 6 6 | 8: 4 7 | 10: 8 8 | 12: 6 9 | 14: 6 10 | 16: 8 11 | 18: 6 12 | 20: 9 13 | 22: 8 14 | 24: 10 15 | 26: 8 16 | 28: 8 17 | 30: 12 18 | 32: 8 19 | 34: 12 20 | 36: 10 21 | 38: 12 22 | 40: 12 23 | 42: 12 24 | 44: 12 25 | 46: 12 26 | 48: 14 27 | 50: 12 28 | 52: 14 29 | 54: 12 30 | 56: 14 31 | 58: 12 32 | 60: 14 33 | 62: 14 34 | 64: 14 35 | 66: 14 36 | 68: 14 37 | 70: 14 38 | 72: 14 39 | 76: 14 40 | 80: 18 41 | 84: 14 42 | 90: 18 43 | 92: 17 44 | -------------------------------------------------------------------------------- /Advent of Code/2017/13/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | class Layer: 7 | def __init__(self, depth, size=0): 8 | self.depth = depth 9 | self.size = size 10 | 11 | def scannerPosition(self, picosecond): 12 | offset = picosecond % ((self.size - 1) * 2) 13 | return 2 * (self.size - 1) - offset if offset > self.size - 1 else offset 14 | 15 | def severity(self, picosecond): 16 | return self.depth * (self.size if self.size > 0 and self.scannerPosition(picosecond) == 0 else 0) 17 | 18 | 19 | def main(): 20 | firewall = [] 21 | 22 | for line in sys.stdin: 23 | depth, scannerRange = line.strip().split(': ') 24 | depth = int(depth) 25 | scannerRange = int(scannerRange) 26 | 27 | while len(firewall) != depth: 28 | firewall.append(Layer(len(firewall))) 29 | 30 | firewall.append(Layer(depth, scannerRange)) 31 | 32 | severity = 0 33 | 34 | for step in range(len(firewall)): 35 | severity += firewall[step].severity(step) 36 | 37 | print(severity) 38 | 39 | 40 | if __name__ == '__main__': 41 | main() 42 | -------------------------------------------------------------------------------- /Advent of Code/2017/13/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import sys 5 | 6 | 7 | class Layer: 8 | def __init__(self, depth, size=0): 9 | self.depth = depth 10 | self.size = size 11 | 12 | def scannerPosition(self, picosecond): 13 | offset = picosecond % ((self.size - 1) * 2) 14 | return 2 * (self.size - 1) - offset if offset > self.size - 1 else offset 15 | 16 | def severity(self, picosecond): 17 | return self.depth * (self.size if self.size > 0 and self.scannerPosition(picosecond) == 0 else 0) 18 | 19 | 20 | def main(): 21 | firewall = [] 22 | 23 | for line in sys.stdin: 24 | depth, scannerRange = line.strip().split(': ') 25 | depth = int(depth) 26 | scannerRange = int(scannerRange) 27 | 28 | while len(firewall) != depth: 29 | firewall.append(Layer(len(firewall))) 30 | 31 | firewall.append(Layer(depth, scannerRange)) 32 | 33 | done = False 34 | picosecond = 0 35 | packageStream = np.zeros(int(5e6), dtype=bool) 36 | 37 | while not done: 38 | for layer in firewall: 39 | if layer.scannerPosition(picosecond) == 0: 40 | packageStream[picosecond - layer.depth] = True # Caught package 41 | 42 | picosecond += 1 43 | 44 | if picosecond >= len(firewall) and \ 45 | not packageStream[picosecond - len(firewall)]: 46 | done = True 47 | 48 | print(picosecond - len(firewall)) 49 | 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /Advent of Code/2017/14/input.txt: -------------------------------------------------------------------------------- 1 | hfdlxzhv 2 | -------------------------------------------------------------------------------- /Advent of Code/2017/14/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import os 4 | import sys 5 | 6 | hexToBin = { 7 | '0': '0000', 8 | '1': '0001', 9 | '2': '0010', 10 | '3': '0011', 11 | '4': '0100', 12 | '5': '0101', 13 | '6': '0110', 14 | '7': '0111', 15 | '8': '1000', 16 | '9': '1001', 17 | 'a': '1010', 18 | 'b': '1011', 19 | 'c': '1100', 20 | 'd': '1101', 21 | 'e': '1110', 22 | 'f': '1111' 23 | } 24 | 25 | 26 | def processKnotHash(str): 27 | return os.popen('echo ' + str + ' | ../10/puzzle2.py').readline().strip() 28 | 29 | 30 | def hashToRow(hash): 31 | return ''.join(hexToBin[char] for char in hash) 32 | 33 | 34 | def main(): 35 | for line in sys.stdin: 36 | keyString = line.strip() 37 | 38 | f = open('grid.txt', 'w') 39 | usedSquares = 0 40 | 41 | for row in range(128): 42 | hashInput = str(keyString) + '-' + str(row) 43 | knotHash = processKnotHash(hashInput) 44 | 45 | print(hashInput, knotHash) 46 | 47 | bin = hashToRow(knotHash) 48 | f.write(bin + '\n') 49 | usedSquares += bin.count('1') 50 | 51 | print('Used squares:', usedSquares) 52 | 53 | 54 | if __name__ == '__main__': 55 | main() 56 | -------------------------------------------------------------------------------- /Advent of Code/2017/14/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import sys 5 | 6 | 7 | def flood(grid, flooded, i, j): 8 | if flooded[i][j]: 9 | return 10 | 11 | flooded[i][j] = True 12 | 13 | for offset_y, offset_x in ((-1, 0), (1, 0), (0, -1), (0, 1)): 14 | if i + offset_y >= 0 and i + offset_y < 128 and \ 15 | j + offset_x >= 0 and j + offset_x < 128: 16 | if grid[i + offset_y][j + offset_x]: 17 | flood(grid, flooded, i + offset_y, j + offset_x) 18 | 19 | 20 | def main(): 21 | grid = [[square == '1' for square in line.strip()] for line in sys.stdin] 22 | flooded = np.zeros((128, 128), dtype=bool) 23 | 24 | regionCounter = 0 25 | 26 | for i in range(128): 27 | for j in range(128): 28 | if grid[i][j] and not flooded[i][j]: 29 | flood(grid, flooded, i, j) 30 | regionCounter += 1 31 | 32 | print(regionCounter) 33 | 34 | 35 | if __name__ == '__main__': 36 | main() 37 | -------------------------------------------------------------------------------- /Advent of Code/2017/15/input.txt: -------------------------------------------------------------------------------- 1 | Generator A starts with 277 2 | Generator B starts with 349 3 | -------------------------------------------------------------------------------- /Advent of Code/2017/15/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | prev_a, prev_b = [int(line.strip().split()[-1]) for line in sys.stdin.readlines()] 8 | 9 | count = 0 10 | 11 | for i in range(int(40e6)): 12 | next_a = (prev_a * 16807) % 2147483647 13 | next_b = (prev_b * 48271) % 2147483647 14 | 15 | prev_a = next_a 16 | prev_b = next_b 17 | 18 | if i % 1e6 == 0: 19 | print('Progress:', i) 20 | 21 | if format(next_a, '032b')[16:] == format(next_b, '032b')[16:]: 22 | count += 1 23 | 24 | print(count) 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /Advent of Code/2017/15/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | prev_a, prev_b = [int(line.strip().split()[-1]) for line in sys.stdin.readlines()] 8 | 9 | count = 0 10 | 11 | for i in range(int(5e6)): 12 | done = False 13 | while not done: 14 | next_a = (prev_a * 16807) % 2147483647 15 | prev_a = next_a 16 | done = next_a % 4 == 0 17 | 18 | done = False 19 | while not done: 20 | next_b = (prev_b * 48271) % 2147483647 21 | prev_b = next_b 22 | done = next_b % 8 == 0 23 | 24 | # print(prev_a, prev_b) 25 | 26 | if i % 1e6 == 0: 27 | print('Progress:', i) 28 | 29 | # print(format(next_a, '032b')[16:]) 30 | # print(format(next_b, '032b')[16:]) 31 | # print() 32 | 33 | if format(next_a, '032b')[16:] == format(next_b, '032b')[16:]: 34 | count += 1 35 | 36 | print(count) 37 | 38 | 39 | if __name__ == '__main__': 40 | main() 41 | -------------------------------------------------------------------------------- /Advent of Code/2017/16/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | programs = list('abcdefghijklmnop') 8 | dance = sys.stdin.readline().strip().split(',') 9 | 10 | for step in dance: 11 | if step[0] == 's': 12 | x = int(step[1:]) 13 | programs = programs[-x:] + programs[:-x] 14 | elif step[0] == 'x': 15 | pos_a, pos_b = [int(program) for program in step[1:].split('/')] 16 | programs[pos_a], programs[pos_b] = programs[pos_b], programs[pos_a] 17 | elif step[0] == 'p': 18 | a, b = [program for program in step[1:].split('/')] 19 | pos_a, pos_b = programs.index(a), programs.index(b) 20 | programs[pos_a], programs[pos_b] = programs[pos_b], programs[pos_a] 21 | 22 | print(''.join(programs)) 23 | 24 | 25 | if __name__ == '__main__': 26 | main() 27 | -------------------------------------------------------------------------------- /Advent of Code/2017/16/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | ONE_BILLION = 1000000000 6 | 7 | 8 | def main(): 9 | programs = list('abcdefghijklmnop') 10 | dance = sys.stdin.readline().strip().split(',') 11 | cache = {} 12 | 13 | for i in range(ONE_BILLION): 14 | programs_str = ''.join(programs) 15 | 16 | if programs_str in cache: 17 | programs = cache[programs_str] 18 | else: 19 | prev = programs_str 20 | 21 | for step in dance: 22 | if step[0] == 's': 23 | x = int(step[1:]) 24 | programs = programs[-x:] + programs[:-x] 25 | elif step[0] == 'x': 26 | pos_a, pos_b = [int(program) for program in step[1:].split('/')] 27 | programs[pos_a], programs[pos_b] = programs[pos_b], programs[pos_a] 28 | elif step[0] == 'p': 29 | a, b = [program for program in step[1:].split('/')] 30 | pos_a, pos_b = programs.index(a), programs.index(b) 31 | programs[pos_a], programs[pos_b] = programs[pos_b], programs[pos_a] 32 | 33 | cache[prev] = ''.join(programs) 34 | 35 | if i % 1e2 == 0: 36 | print('Progress: %.2f %% (%d/%d)' % (i * 100 / ONE_BILLION, i, ONE_BILLION), end='\r') 37 | 38 | print(''.join(programs)) 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /Advent of Code/2017/17/input.txt: -------------------------------------------------------------------------------- 1 | 394 2 | -------------------------------------------------------------------------------- /Advent of Code/2017/17/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | NUM_OPS = 2017 6 | 7 | 8 | def main(): 9 | steps = int(sys.stdin.readline().strip()) 10 | 11 | buffer = [0] 12 | currentPosition = 0 13 | 14 | for value in range(NUM_OPS): 15 | currentPosition = (currentPosition + steps + 1) % len(buffer) 16 | buffer.insert(currentPosition + 1, value + 1) 17 | 18 | print(buffer[buffer.index(2017) + 1]) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /Advent of Code/2017/17/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from collections import deque 4 | import sys 5 | 6 | NUM_OPS = 50000000 7 | 8 | 9 | def main(): 10 | steps = int(sys.stdin.readline().strip()) 11 | 12 | buffer = deque([0]) 13 | 14 | for value in range(1, NUM_OPS + 1): 15 | buffer.rotate(-steps) 16 | buffer.append(value) 17 | 18 | print(buffer[buffer.index(0) + 1]) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /Advent of Code/2017/18/input.txt: -------------------------------------------------------------------------------- 1 | set i 31 2 | set a 1 3 | mul p 17 4 | jgz p p 5 | mul a 2 6 | add i -1 7 | jgz i -2 8 | add a -1 9 | set i 127 10 | set p 316 11 | mul p 8505 12 | mod p a 13 | mul p 129749 14 | add p 12345 15 | mod p a 16 | set b p 17 | mod b 10000 18 | snd b 19 | add i -1 20 | jgz i -9 21 | jgz a 3 22 | rcv b 23 | jgz b -1 24 | set f 0 25 | set i 126 26 | rcv a 27 | rcv b 28 | set p a 29 | mul p -1 30 | add p b 31 | jgz p 4 32 | snd a 33 | set a b 34 | jgz 1 3 35 | snd b 36 | set f 1 37 | add i -1 38 | jgz i -11 39 | snd a 40 | jgz f -16 41 | jgz a -19 42 | -------------------------------------------------------------------------------- /Advent of Code/2017/18/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import operator 4 | import sys 5 | 6 | ops = {'add': operator.add, 'mod': operator.mod, 'mul': operator.mul} 7 | 8 | 9 | def main(): 10 | instructions = [instruction.strip() for instruction in sys.stdin.readlines()] 11 | 12 | current = 0 13 | lastFreq = None 14 | regs = {} 15 | 16 | while 0 <= current and current < len(instructions): 17 | cmd, x, *y = instructions[current].split() 18 | if y: y = y[0] 19 | 20 | if cmd == 'snd': 21 | lastFreq = regs[x] 22 | 23 | elif cmd == 'set': 24 | regs[x] = int(y) if y.lstrip('-').isdigit() else regs[y] 25 | 26 | elif cmd in ops.keys(): 27 | regs[x] = ops[cmd](regs[x] if x in regs else 0, int(y) if y.lstrip('-').isdigit() else regs[y]) 28 | 29 | elif cmd == 'rcv': 30 | if x != 0: 31 | print(lastFreq) 32 | break 33 | 34 | elif cmd == 'jgz': 35 | if x.lstrip('-').isdigit() > 0 or regs[x] > 0: 36 | current += (int(y) if y.lstrip('-').isdigit() else regs[y]) - 1 37 | 38 | current += 1 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /Advent of Code/2017/19/input_test.txt: -------------------------------------------------------------------------------- 1 | | 2 | | +--+ 3 | A | C 4 | F---|----E|--+ 5 | | | | D 6 | +B-+ +--+ 7 | -------------------------------------------------------------------------------- /Advent of Code/2017/19/puzzle1and2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from enum import Enum 4 | import numpy as np 5 | import operator 6 | import sys 7 | 8 | 9 | class Dir(Enum): 10 | LEFT = 1 11 | RIGHT = 2 12 | UP = 3 13 | DOWN = 4 14 | 15 | 16 | VELOCITY = {Dir.LEFT: (0, -1), Dir.RIGHT: (0, 1), Dir.UP: (-1, 0), Dir.DOWN: (1, 0)} 17 | 18 | 19 | def main(): 20 | diagram = [list(line.strip('\n')) for line in sys.stdin.readlines()] 21 | 22 | pos, dir = (0, diagram[0].index('|')), Dir.DOWN 23 | path, steps = [], 0 24 | 25 | diagram = np.asarray(diagram) 26 | 27 | done = False 28 | while not done: 29 | 30 | if diagram[pos].isalpha(): 31 | path.append(diagram[pos]) 32 | 33 | elif diagram[pos] == '+': 34 | if dir in [Dir.UP, Dir.DOWN]: 35 | char = diagram[tuple(map(operator.add, pos, VELOCITY[Dir.LEFT]))] 36 | dir = Dir.LEFT if char == '-' or char.isalpha() else Dir.RIGHT 37 | elif dir in [Dir.LEFT, Dir.RIGHT]: 38 | char = diagram[tuple(map(operator.add, pos, VELOCITY[Dir.UP]))] 39 | dir = Dir.UP if char == '|' or char.isalpha() else Dir.DOWN 40 | 41 | elif diagram[pos] == ' ': 42 | done = True 43 | break 44 | 45 | # print(pos, path) 46 | pos = tuple(map(operator.add, pos, VELOCITY[dir])) 47 | steps += 1 48 | 49 | print('Path:', ''.join(path)) 50 | print('Steps:', steps) 51 | 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /Advent of Code/2017/20/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | flatten = lambda l: [item for sublist in l for item in sublist] 6 | 7 | 8 | class Particle(): 9 | def __init__(self, pos_x, pos_y, pos_z, vel_x, vel_y, vel_z, acc_x, acc_y, acc_z): 10 | self.pos_x = pos_x 11 | self.pos_y = pos_y 12 | self.pos_z = pos_z 13 | 14 | self.vel_x = vel_x 15 | self.vel_y = vel_y 16 | self.vel_z = vel_z 17 | 18 | self.acc_x = acc_x 19 | self.acc_y = acc_y 20 | self.acc_z = acc_z 21 | 22 | def update(self): 23 | self.vel_x += self.acc_x 24 | self.vel_y += self.acc_y 25 | self.vel_z += self.acc_z 26 | 27 | self.pos_x += self.vel_x 28 | self.pos_y += self.vel_y 29 | self.pos_z += self.vel_z 30 | 31 | def distanceToOrigin(self): 32 | return abs(self.pos_x) + abs(self.pos_y) + abs(self.pos_z) 33 | 34 | 35 | def main(): 36 | particles = [[[int(value) 37 | for value in token[3:-1].split(',')] 38 | for token in line.strip().split(', ')] 39 | for line in sys.stdin.readlines()] 40 | 41 | particles = [Particle(*flatten(particle)) for particle in particles] 42 | 43 | for i in range(int(1e3)): 44 | for particle in particles: 45 | particle.update() 46 | 47 | distances = [particle.distanceToOrigin() for particle in particles] 48 | print(distances.index(min(distances))) 49 | 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /Advent of Code/2017/22/input.txt: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Advent of Code/2017/22/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import math 4 | import numpy as np 5 | import sys 6 | 7 | GRID_SIZE = 10001 8 | 9 | 10 | def main(): 11 | grid = np.zeros((GRID_SIZE, GRID_SIZE), dtype=int) 12 | map = [list(line.strip()) for line in sys.stdin.readlines()] 13 | 14 | for i in range(len(map)): 15 | for j in range(len(map[i])): 16 | grid[int(GRID_SIZE / 2 - len(map) / 2) + i][int(GRID_SIZE / 2 - len(map[i]) / 2) + j] = map[i][j] == '#' 17 | 18 | p_i = p_j = int(GRID_SIZE / 2) 19 | direction = math.pi 20 | 21 | infection_counter = 0 22 | 23 | for i in range(10000): 24 | direction += -math.pi / 2 if grid[p_i][p_j] else math.pi / 2 25 | 26 | grid[p_i][p_j] = not grid[p_i][p_j] 27 | 28 | if grid[p_i][p_j]: 29 | infection_counter += 1 30 | 31 | p_i += int(math.cos(direction)) 32 | p_j += int(math.sin(direction)) 33 | 34 | print(infection_counter) 35 | 36 | 37 | if __name__ == '__main__': 38 | main() 39 | -------------------------------------------------------------------------------- /Advent of Code/2017/22/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import math 4 | import numpy as np 5 | import sys 6 | 7 | GRID_SIZE = 10001 8 | 9 | 10 | def main(): 11 | grid = np.zeros((GRID_SIZE, GRID_SIZE), dtype=int) 12 | map = [list(line.strip()) for line in sys.stdin.readlines()] 13 | 14 | for i in range(len(map)): 15 | for j in range(len(map[i])): 16 | if map[i][j] == '#': 17 | grid[int(GRID_SIZE / 2 - len(map) / 2) + i][int(GRID_SIZE / 2 - len(map[i]) / 2) + j] = 2 18 | 19 | p_i = p_j = int(GRID_SIZE / 2) 20 | direction = math.pi 21 | 22 | # Node states: 23 | # ------------ 24 | # 0 - Clean 25 | # 1 - Weakened 26 | # 2 - Infected 27 | # 3 - Flagged 28 | 29 | infection_counter = 0 30 | 31 | for i in range(10000000): 32 | if grid[p_i][p_j] == 0: 33 | direction += math.pi / 2 34 | elif grid[p_i][p_j] == 2: 35 | direction -= math.pi / 2 36 | elif grid[p_i][p_j] == 3: 37 | direction += math.pi 38 | 39 | # Working around Float Point Arithmetic precision limitations... 40 | direction %= 2 * math.pi 41 | 42 | grid[p_i][p_j] = (grid[p_i][p_j] + 1) % 4 43 | 44 | if grid[p_i][p_j] == 2: 45 | infection_counter += 1 46 | 47 | p_i += int(math.cos(direction)) 48 | p_j += int(math.sin(direction)) 49 | 50 | print(infection_counter) 51 | 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /Advent of Code/2017/23/input.txt: -------------------------------------------------------------------------------- 1 | set b 81 2 | set c b 3 | jnz a 2 4 | jnz 1 5 5 | mul b 100 6 | sub b -100000 7 | set c b 8 | sub c -17000 9 | set f 1 10 | set d 2 11 | set e 2 12 | set g d 13 | mul g e 14 | sub g b 15 | jnz g 2 16 | set f 0 17 | sub e -1 18 | set g e 19 | sub g b 20 | jnz g -8 21 | sub d -1 22 | set g d 23 | sub g b 24 | jnz g -13 25 | jnz f 2 26 | sub h -1 27 | set g b 28 | sub g c 29 | jnz g 2 30 | jnz 1 3 31 | sub b -17 32 | jnz 1 -23 33 | -------------------------------------------------------------------------------- /Advent of Code/2017/23/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import operator 4 | import sys 5 | 6 | ops = {'add': operator.add, 'mod': operator.mod, 'mul': operator.mul, 'sub': operator.sub} 7 | 8 | 9 | def main(): 10 | instructions = [instruction.strip() for instruction in sys.stdin.readlines()] 11 | 12 | current = 0 13 | regs = {} 14 | 15 | mul_counter = 0 16 | 17 | while 0 <= current and current < len(instructions): 18 | cmd, x, *y = instructions[current].split() 19 | if y: y = y[0] 20 | 21 | if cmd == 'mul': 22 | mul_counter += 1 23 | 24 | if cmd == 'set': 25 | regs[x] = int(y) if y.lstrip('-').isdigit() else regs[y] 26 | elif cmd in ops.keys(): 27 | regs[x] = ops[cmd](regs[x] if x in regs else 0, int(y) if y.lstrip('-').isdigit() else regs[y]) 28 | elif cmd == 'jnz': 29 | if x.lstrip('-').isdigit() != 0 or (x in regs and regs[x] != 0): 30 | current += (int(y) if y.lstrip('-').isdigit() else regs[y]) - 1 31 | 32 | current += 1 33 | 34 | print(mul_counter) 35 | 36 | 37 | if __name__ == '__main__': 38 | main() 39 | -------------------------------------------------------------------------------- /Advent of Code/2017/23/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | 4 | def main(): 5 | h = 0 6 | 7 | for b in range(108100, 125100 + 1, 17): 8 | for d in range(2, b): 9 | if (b % d == 0): 10 | h += 1 11 | break 12 | 13 | print(h) 14 | 15 | 16 | if __name__ == '__main__': 17 | main() 18 | -------------------------------------------------------------------------------- /Advent of Code/2017/24/input.txt: -------------------------------------------------------------------------------- 1 | 48/5 2 | 25/10 3 | 35/49 4 | 34/41 5 | 35/35 6 | 47/35 7 | 34/46 8 | 47/23 9 | 28/8 10 | 27/21 11 | 40/11 12 | 22/50 13 | 48/42 14 | 38/17 15 | 50/33 16 | 13/13 17 | 22/33 18 | 17/29 19 | 50/0 20 | 20/47 21 | 28/0 22 | 42/4 23 | 46/22 24 | 19/35 25 | 17/22 26 | 33/37 27 | 47/7 28 | 35/20 29 | 8/36 30 | 24/34 31 | 6/7 32 | 7/43 33 | 45/37 34 | 21/31 35 | 37/26 36 | 16/5 37 | 11/14 38 | 7/23 39 | 2/23 40 | 3/25 41 | 20/20 42 | 18/20 43 | 19/34 44 | 25/46 45 | 41/24 46 | 0/33 47 | 3/7 48 | 49/38 49 | 47/22 50 | 44/15 51 | 24/21 52 | 10/35 53 | 6/21 54 | 14/50 55 | -------------------------------------------------------------------------------- /Advent of Code/2017/24/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import copy 4 | import numpy as np 5 | import sys 6 | 7 | flatten = lambda l: [item for sublist in l for item in sublist] 8 | strength = lambda bridge: sum([sum([int(port) for port in component.split('/')]) for component in bridge]) 9 | 10 | max_strength = 0 11 | 12 | 13 | class Bridge(): 14 | def __init__(self, head): 15 | self.components = [head] 16 | self.tailPins = sum([int(port) for port in head.split('/')]) 17 | 18 | 19 | def dfs(bridge, components_available): 20 | global max_strength 21 | 22 | if not components_available or \ 23 | bridge.tailPins not in np.unique(flatten([[int(pin) for pin in c.split('/')] for c in components_available])): 24 | if strength(bridge.components) > max_strength: 25 | max_strength = strength(bridge.components) 26 | print(max_strength, bridge.components) 27 | else: 28 | for component in components_available: 29 | if bridge.tailPins in [int(port) for port in component.split('/')]: 30 | extension = copy.deepcopy(bridge) 31 | extension.components.append(component) 32 | extension.tailPins = sum([int(port) for port in component.split('/')]) - extension.tailPins 33 | dfs(extension, [c for c in components_available if c != component]) 34 | 35 | 36 | def main(): 37 | components = [component.strip() for component in sys.stdin.readlines()] 38 | zeroPinPorts = [component for component in components if 0 in [int(port) for port in component.split('/')]] 39 | 40 | for zeroPinPort in zeroPinPorts: 41 | dfs(Bridge(zeroPinPort), [c for c in components if c != zeroPinPort]) 42 | 43 | print(max_strength) 44 | 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /Advent of Code/2017/25/input.txt: -------------------------------------------------------------------------------- 1 | Begin in state A. 2 | Perform a diagnostic checksum after 12317297 steps. 3 | 4 | In state A: 5 | If the current value is 0: 6 | - Write the value 1. 7 | - Move one slot to the right. 8 | - Continue with state B. 9 | If the current value is 1: 10 | - Write the value 0. 11 | - Move one slot to the left. 12 | - Continue with state D. 13 | 14 | In state B: 15 | If the current value is 0: 16 | - Write the value 1. 17 | - Move one slot to the right. 18 | - Continue with state C. 19 | If the current value is 1: 20 | - Write the value 0. 21 | - Move one slot to the right. 22 | - Continue with state F. 23 | 24 | In state C: 25 | If the current value is 0: 26 | - Write the value 1. 27 | - Move one slot to the left. 28 | - Continue with state C. 29 | If the current value is 1: 30 | - Write the value 1. 31 | - Move one slot to the left. 32 | - Continue with state A. 33 | 34 | In state D: 35 | If the current value is 0: 36 | - Write the value 0. 37 | - Move one slot to the left. 38 | - Continue with state E. 39 | If the current value is 1: 40 | - Write the value 1. 41 | - Move one slot to the right. 42 | - Continue with state A. 43 | 44 | In state E: 45 | If the current value is 0: 46 | - Write the value 1. 47 | - Move one slot to the left. 48 | - Continue with state A. 49 | If the current value is 1: 50 | - Write the value 0. 51 | - Move one slot to the right. 52 | - Continue with state B. 53 | 54 | In state F: 55 | If the current value is 0: 56 | - Write the value 0. 57 | - Move one slot to the right. 58 | - Continue with state C. 59 | If the current value is 1: 60 | - Write the value 0. 61 | - Move one slot to the right. 62 | - Continue with state E. 63 | -------------------------------------------------------------------------------- /Advent of Code/2018/01/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | print(sum([int(line) for line in sys.stdin])) 8 | 9 | 10 | if __name__ == '__main__': 11 | main() 12 | -------------------------------------------------------------------------------- /Advent of Code/2018/01/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def main(): 7 | frequency_change_list = [int(line) for line in sys.stdin] 8 | 9 | seen = set([0]) 10 | frequency = 0 11 | 12 | i = 0 13 | while True: 14 | frequency += frequency_change_list[i] 15 | 16 | # print(frequency, frequency in seen) 17 | 18 | if frequency in seen: 19 | print(frequency) 20 | break 21 | 22 | i = (i + 1) % len(frequency_change_list) 23 | seen.add(frequency) 24 | # print(seen) 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /Advent of Code/2018/02/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import collections 4 | import sys 5 | 6 | 7 | def main(): 8 | twice_count = 0 9 | thrice_count = 0 10 | 11 | for line in sys.stdin: 12 | char_to_count = collections.defaultdict(int) 13 | 14 | for c in line: 15 | char_to_count[c] += 1 16 | 17 | set_id_char_count = set(char_to_count.values()) 18 | 19 | # print(set_id_char_count) 20 | 21 | if 2 in set_id_char_count: 22 | twice_count += 1 23 | 24 | if 3 in set_id_char_count: 25 | thrice_count += 1 26 | 27 | print(twice_count * thrice_count) 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /Advent of Code/2018/02/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def id_diff(id1, id2): 7 | """ 8 | Returns difference metric between two IDs: 9 | 0: IDs are exactly the same 10 | 1: IDs only differ by one char 11 | 2: IDs differ by one char or more 12 | """ 13 | diff = 0 14 | 15 | for i in range(len(id1)): 16 | if id1[i] is not id2[i]: 17 | diff += 1 18 | 19 | if diff >= 2: 20 | break 21 | 22 | return diff 23 | 24 | 25 | def main(): 26 | list_of_ids = [line.strip() for line in sys.stdin] 27 | 28 | done = False 29 | 30 | for i in range(len(list_of_ids)): 31 | id1 = list_of_ids[i] 32 | 33 | for j in range(i + 1, len(list_of_ids)): 34 | id2 = list_of_ids[j] 35 | 36 | if id_diff(id1, id2) == 1: 37 | print(id1) 38 | print(id2) 39 | done = True 40 | break 41 | 42 | if done: 43 | break 44 | 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /Advent of Code/2018/03/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import re 5 | import sys 6 | 7 | 8 | def main(): 9 | fabric = np.zeros((1000, 1000), dtype=int) 10 | 11 | for line in sys.stdin: 12 | _, margin_left, margin_top, width, height = tuple( 13 | map(int, re.search(r'#(\w+) @ (\w+),(\w+): (\w+)x(\w+)', line).groups())) 14 | 15 | fabric[margin_top:margin_top + height, 16 | margin_left:margin_left + width] += 1 17 | 18 | print((fabric >= 2).sum()) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /Advent of Code/2018/03/puzzle2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import re 5 | import sys 6 | 7 | 8 | def main(): 9 | fabric = np.zeros((1000, 1000), dtype=int) 10 | candidates = set() 11 | 12 | for line in sys.stdin: 13 | claim_id, margin_left, margin_top, width, height = tuple( 14 | map(int, re.search(r'#(\w+) @ (\w+),(\w+): (\w+)x(\w+)', line).groups())) 15 | 16 | patch = fabric[margin_top:margin_top + height, 17 | margin_left:margin_left + width] 18 | 19 | if patch.sum() == 0: 20 | candidates.add(claim_id) 21 | else: 22 | candidates -= set(np.unique(patch)) 23 | 24 | fabric[margin_top:margin_top + height, 25 | margin_left:margin_left + width] = claim_id 26 | 27 | print(candidates) 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /Advent of Code/2018/04/puzzle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import re 5 | import sys 6 | 7 | 8 | def main(): 9 | data = sorted([line.strip() for line in sys.stdin]) 10 | 11 | stats = {} 12 | guard_id, last_start = 0, 0 13 | 14 | for entry in data: 15 | _, _, _, _, minute, event = re.search( 16 | r'\[(\w+)-(\w+)-(\w+) (\w+):(\w+)\] (.*)', entry).groups() 17 | minute = int(minute) 18 | 19 | if event[0] == 'w': 20 | # 'wakes up' 21 | if guard_id not in stats: 22 | stats[guard_id] = np.zeros(60, dtype=int) 23 | stats[guard_id][last_start:minute] += 1 24 | elif event[0] == 'f': 25 | # 'falls asleep' 26 | last_start = minute 27 | else: 28 | guard_id = int(re.findall(r'\d+', event)[0]) 29 | 30 | guard_id = max(stats.keys(), key=(lambda k: stats[k].sum())) 31 | print('Part 1: {}'.format(guard_id * np.argmax(stats[guard_id]))) 32 | 33 | guard_id = max(stats.keys(), key=(lambda k: np.max(stats[k]))) 34 | print('Part 2: {}'.format(guard_id * np.argmax(stats[guard_id]))) 35 | 36 | 37 | if __name__ == '__main__': 38 | main() 39 | -------------------------------------------------------------------------------- /Advent of Code/2018/05/puzzle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | def react(polymer): 7 | i, unstable = 0, True 8 | 9 | while unstable: 10 | if polymer[i] != polymer[i+1] and \ 11 | polymer[i].lower() == polymer[i+1].lower(): 12 | polymer = polymer[:i] + polymer[i+2:] 13 | i = max(0, i-1) 14 | else: 15 | i += 1 16 | 17 | unstable = i != len(polymer) - 1 18 | 19 | return polymer 20 | 21 | 22 | def main(): 23 | polymer = sys.stdin.readline() 24 | print('Part 1: {}'.format(len(react(polymer)))) 25 | 26 | stats = {} 27 | units = ''.join(set(polymer.lower())) 28 | 29 | for c in units: 30 | res = polymer.replace(c, '').replace(c.upper(), '') 31 | stats[c] = len(react(res)) 32 | 33 | print('Part 2: {}'.format(min(stats.values()))) 34 | 35 | 36 | if __name__ == '__main__': 37 | main() 38 | -------------------------------------------------------------------------------- /Advent of Code/2018/06/input.txt: -------------------------------------------------------------------------------- 1 | 181, 47 2 | 337, 53 3 | 331, 40 4 | 137, 57 5 | 200, 96 6 | 351, 180 7 | 157, 332 8 | 113, 101 9 | 285, 55 10 | 189, 188 11 | 174, 254 12 | 339, 81 13 | 143, 61 14 | 131, 155 15 | 239, 334 16 | 357, 291 17 | 290, 89 18 | 164, 149 19 | 248, 73 20 | 311, 190 21 | 54, 217 22 | 285, 268 23 | 354, 113 24 | 318, 191 25 | 182, 230 26 | 156, 252 27 | 114, 232 28 | 159, 299 29 | 324, 280 30 | 152, 155 31 | 295, 293 32 | 194, 214 33 | 252, 345 34 | 233, 172 35 | 272, 311 36 | 230, 82 37 | 62, 160 38 | 275, 96 39 | 335, 215 40 | 185, 347 41 | 134, 272 42 | 58, 113 43 | 112, 155 44 | 220, 83 45 | 153, 244 46 | 279, 149 47 | 302, 167 48 | 185, 158 49 | 72, 91 50 | 264, 67 -------------------------------------------------------------------------------- /Advent of Code/2018/07/puzzle1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import collections 4 | import re 5 | import sys 6 | 7 | 8 | def main(): 9 | tree = collections.defaultdict(set) 10 | tree_inv = collections.defaultdict(set) 11 | available = set() 12 | instructions = '' 13 | 14 | for line in sys.stdin: 15 | step, next_step = re.search( 16 | r'Step (.) must be finished before step (.) can begin.', line).groups() 17 | tree[step].add(next_step) 18 | tree_inv[next_step].add(step) 19 | 20 | # Finding the roots 21 | for _, children in tree_inv.items(): 22 | for node in children: 23 | if node not in tree_inv.keys(): 24 | available.add(node) 25 | 26 | while len(available) != 0: 27 | node = next(candidate for candidate in sorted(available) 28 | if all(elem in instructions for elem in tree_inv[candidate])) 29 | 30 | instructions += node 31 | available.update(tree[node]) 32 | available.remove(node) 33 | 34 | print('Part 1:', instructions) 35 | 36 | 37 | if __name__ == '__main__': 38 | main() 39 | -------------------------------------------------------------------------------- /Advent of Code/2018/08/puzzle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | 5 | 6 | class Node: 7 | def __init__(self): 8 | self.children = [] 9 | self.metadata = [] 10 | 11 | def checksum(self): 12 | return sum(self.metadata) + sum(node.checksum() 13 | for node in self.children) 14 | 15 | def value(self): 16 | return self.checksum() if len(self.children) == 0 \ 17 | else sum(self.children[i-1].value() 18 | for i in self.metadata 19 | if i <= len(self.children)) 20 | 21 | def to_string(self, level=0): 22 | return '{}{}\n'.format('\t'*level, self.metadata) + \ 23 | ''.join(node.to_string(level + 1) 24 | for node in self.children) 25 | 26 | 27 | def parse_node(data): 28 | node = Node() 29 | 30 | num_children = next(data) 31 | num_metadata = next(data) 32 | 33 | for _ in range(num_children): 34 | node.children.append(parse_node(data)) 35 | 36 | for _ in range(num_metadata): 37 | node.metadata.append(next(data)) 38 | 39 | return node 40 | 41 | 42 | def main(): 43 | data = map(int, sys.stdin.readline().split()) 44 | 45 | root = parse_node(data) 46 | # print(root.to_string()) 47 | 48 | print('Part 1:', root.checksum()) 49 | print('Part 2:', root.value()) 50 | 51 | 52 | if __name__ == '__main__': 53 | main() 54 | -------------------------------------------------------------------------------- /Advent of Code/2018/09/README.md: -------------------------------------------------------------------------------- 1 | # Day 9: Marble Mania 2 | 3 | I tried *three* different approaches to solve today's puzzle. Here is an overview of all of them: 4 | 5 | > **Disclaimer:** As of yet, only one of them managed to produce satisfactory results. 6 | 7 | **Attempt no. 1** 8 | The first approach ([slow.py](https://github.com/ferrolho/advent-of-code/blob/master/2018/9/slow.py)) used your average NumPy array and became infeasible for the input of part two. 9 | 10 | **Attempt no. 2** 11 | My second approach ([analytic.py](https://github.com/ferrolho/advent-of-code/blob/master/2018/9/analytic.py)) was trying to find an analytic solution, but I failed to get the pattern of the score for the marbles that get to be removed from the circle of marbles... Apparently, I was not the only one who spent hours on this: [r/adventofcode](https://www.reddit.com/r/adventofcode/comments/a4o1y9/could_day_9_have_a_closed_form_solution/). 12 | 13 | **Attempt no. 3** 14 | My third and final approach ([puzzle.py](https://github.com/ferrolho/advent-of-code/blob/master/2018/9/puzzle.py)) was to implement my own circular doubly linked list to get Θ(1) insertion/deletion complexity. 15 | -------------------------------------------------------------------------------- /Advent of Code/2018/09/analytic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from itertools import cycle 4 | import collections 5 | import numpy as np 6 | import re 7 | import sys 8 | 9 | INPUT_FORMAT = r'(\w+) players; last marble is worth (\w+) points' 10 | MULTIPLE = 23 11 | 12 | 13 | def scoring_order(num_players): 14 | players = [] 15 | current_round = 0 16 | marbles_counter = 1 17 | 18 | while len(players) != num_players: 19 | player = current_round % num_players + 1 20 | 21 | if (current_round + 1) % MULTIPLE == 0: 22 | marbles_counter -= 1 23 | players.append(player) 24 | else: 25 | marbles_counter += 1 26 | 27 | current_round += 1 28 | 29 | return players 30 | 31 | 32 | def main(): 33 | for line in sys.stdin: 34 | num_players, last_marble = map( 35 | int, re.search(INPUT_FORMAT, line).groups()) 36 | 37 | players_scoring_order = cycle(scoring_order(num_players)) 38 | game_rounds = round(last_marble / MULTIPLE) + 1 39 | 40 | scoreboard = collections.defaultdict(int) 41 | 42 | for i in np.arange(1, game_rounds): 43 | player = next(players_scoring_order) 44 | 45 | scoreboard[player] += i * MULTIPLE + 0 46 | 47 | print('Player {:3d} scored {:5d} + {:5d} = {:5d}'.format( 48 | player, i * MULTIPLE, 0, i * MULTIPLE + 0)) 49 | 50 | print(max(scoreboard.values())) 51 | 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /Advent of Code/2018/09/input.txt: -------------------------------------------------------------------------------- 1 | 9 players; last marble is worth 25 points 2 | 10 players; last marble is worth 1618 points 3 | 13 players; last marble is worth 7999 points 4 | 17 players; last marble is worth 1104 points 5 | 21 players; last marble is worth 6111 points 6 | 30 players; last marble is worth 5807 points 7 | 458 players; last marble is worth 71307 points 8 | 458 players; last marble is worth 7130700 points -------------------------------------------------------------------------------- /Advent of Code/2018/09/slow.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import collections 4 | import numpy as np 5 | import re 6 | import sys 7 | 8 | INPUT_FORMAT = r'(\w+) players; last marble is worth (\w+) points' 9 | 10 | 11 | def main(): 12 | for line in sys.stdin: 13 | players, last_marble = map(int, re.search(INPUT_FORMAT, line).groups()) 14 | 15 | current = 1 16 | marbles = np.array([0, 1]) 17 | scoreboard = collections.defaultdict(int) 18 | 19 | for i in range(1, last_marble): 20 | player = i % players + 1 21 | marble_value = i + 1 22 | 23 | if marble_value % 23 == 0: 24 | current = (current - 7) % len(marbles) 25 | scoreboard[player] += marble_value + marbles[current] 26 | # print('Player {} scored {} ({} + {})'.format(player, 27 | # marble_value + marbles[current], 28 | # marble_value, marbles[current])) 29 | marbles = np.delete(marbles, current) 30 | else: 31 | current += 2 32 | if current > len(marbles): 33 | current %= len(marbles) 34 | marbles = np.insert(marbles, current, marble_value) 35 | 36 | # print('{}: {} ({}) next at: {} actual: {}'.format( 37 | # player, marbles, marbles[aux], aux+2, current)) 38 | 39 | if (i % 0.5e5 == 0): 40 | print('\r{:.2f}% done'.format(i * 100 / last_marble)) 41 | # print(marbles) 42 | 43 | print(max(scoreboard.values())) 44 | # break 45 | 46 | # print('Part 1:', root.checksum()) 47 | # print('Part 2:', root.value()) 48 | 49 | 50 | if __name__ == '__main__': 51 | main() 52 | -------------------------------------------------------------------------------- /Advent of Code/2018/10/puzzle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import re 5 | import sys 6 | 7 | 8 | def main(): 9 | data = [line for line in sys.stdin] 10 | 11 | def line_parser(s): return list(map(int, re.findall(r'-?\d+', s))) 12 | points = np.array(list(map(line_parser, data))) 13 | 14 | pos = points[:, [0, 1]] 15 | vel = points[:, [2, 3]] 16 | 17 | counter = -2 18 | shrinking = True 19 | sky_shape_prev = None 20 | 21 | while shrinking: 22 | counter += 1 23 | 24 | x_min = min(pos[:, 0]) 25 | x_max = max(pos[:, 0]) 26 | 27 | y_min = min(pos[:, 1]) 28 | y_max = max(pos[:, 1]) 29 | 30 | sky_shape = (y_max - y_min + 1, x_max - x_min + 1) 31 | 32 | # Expansion started 33 | if sky_shape_prev and \ 34 | sky_shape[0] > sky_shape_prev[0] and \ 35 | sky_shape[1] > sky_shape_prev[1]: 36 | 37 | # Go back once 38 | pos -= vel 39 | 40 | # Create empty sky 41 | sky = np.full(sky_shape_prev, ' ', dtype=str) 42 | 43 | # Translate sky to positive quadrant 44 | pos[:, 0] -= min(pos[:, 0]) 45 | pos[:, 1] -= min(pos[:, 1]) 46 | 47 | # Mark poins in sky 48 | for (x, y) in pos: 49 | sky[y][x] = '#' 50 | 51 | sky_str = '\n'.join([''.join(row) for row in sky]) 52 | 53 | print('Part 1:\n{}'.format(sky_str)) 54 | print('Part 2: {} seconds'.format(counter)) 55 | 56 | shrinking = False 57 | 58 | sky_shape_prev = sky_shape 59 | pos += vel 60 | 61 | 62 | if __name__ == '__main__': 63 | main() 64 | -------------------------------------------------------------------------------- /Advent of Code/2018/10/sample-input.txt: -------------------------------------------------------------------------------- 1 | position=< 9, 1> velocity=< 0, 2> 2 | position=< 7, 0> velocity=<-1, 0> 3 | position=< 3, -2> velocity=<-1, 1> 4 | position=< 6, 10> velocity=<-2, -1> 5 | position=< 2, -4> velocity=< 2, 2> 6 | position=<-6, 10> velocity=< 2, -2> 7 | position=< 1, 8> velocity=< 1, -1> 8 | position=< 1, 7> velocity=< 1, 0> 9 | position=<-3, 11> velocity=< 1, -2> 10 | position=< 7, 6> velocity=<-1, -1> 11 | position=<-2, 3> velocity=< 1, 0> 12 | position=<-4, 3> velocity=< 2, 0> 13 | position=<10, -3> velocity=<-1, 1> 14 | position=< 5, 11> velocity=< 1, -2> 15 | position=< 4, 7> velocity=< 0, -1> 16 | position=< 8, -2> velocity=< 0, 1> 17 | position=<15, 0> velocity=<-2, 0> 18 | position=< 1, 6> velocity=< 1, 0> 19 | position=< 8, 9> velocity=< 0, -1> 20 | position=< 3, 3> velocity=<-1, 1> 21 | position=< 0, 5> velocity=< 0, -1> 22 | position=<-2, 2> velocity=< 2, 0> 23 | position=< 5, -2> velocity=< 1, 2> 24 | position=< 1, 4> velocity=< 2, 1> 25 | position=<-2, 7> velocity=< 2, -2> 26 | position=< 3, 6> velocity=<-1, -1> 27 | position=< 5, 0> velocity=< 1, 0> 28 | position=<-6, 0> velocity=< 2, 0> 29 | position=< 5, 9> velocity=< 1, -2> 30 | position=<14, 7> velocity=<-2, 0> 31 | position=<-3, 6> velocity=< 2, -1> -------------------------------------------------------------------------------- /Advent of Code/2018/11/puzzle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import numpy as np 4 | import re 5 | import sys 6 | 7 | SIZE = 300 8 | 9 | 10 | def main(): 11 | sn = int(sys.stdin.readline()) 12 | grid = np.zeros((SIZE + 1, SIZE + 1), dtype=int) 13 | 14 | for y in range(1, SIZE + 1): 15 | for x in range(1, SIZE + 1): 16 | rack_id = x + 10 17 | pwr_lvl = (rack_id * y + sn) * rack_id 18 | pwr_lvl = int(str(pwr_lvl)[-3]) if pwr_lvl >= 100 else 0 19 | grid[y][x] = pwr_lvl - 5 20 | 21 | max_pwr = 0 22 | descriptor = None 23 | 24 | for y in range(1, SIZE - 2): 25 | for x in range(1, SIZE - 2): 26 | pwr = np.sum(grid[y:y+3, x:x+3]) 27 | 28 | if pwr > max_pwr: 29 | max_pwr = pwr 30 | descriptor = (x, y, pwr) 31 | 32 | print('Part 1: {},{} ({})'.format(*descriptor)) 33 | 34 | for y in range(1, SIZE - 2): 35 | print('\rWorking... {:.2f} %'.format(100 * y / (SIZE - 3)), end='') 36 | for x in range(1, SIZE - 2): 37 | for l in range(1, SIZE + 1 - max(x, y)): 38 | pwr = np.sum(grid[y:y+l, x:x+l]) 39 | 40 | if pwr > max_pwr: 41 | max_pwr = pwr 42 | descriptor = (x, y, l, pwr) 43 | 44 | print('\nPart 2: {},{},{} ({})'.format(*descriptor)) 45 | 46 | 47 | if __name__ == '__main__': 48 | main() 49 | -------------------------------------------------------------------------------- /Advent of Code/2018/12/input.txt: -------------------------------------------------------------------------------- 1 | initial state: #.#..#.##.#..#.#..##.######...####.........#..##...####.#.###......#.#.##..#.#.###.#..#.#.####....## 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 | -------------------------------------------------------------------------------- /Advent of Code/2018/12/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day12() 2 | input = joinpath(@__DIR__, "input.txt") 3 | a, b = split(read(input, String), "\n\n") 4 | 5 | plants = findall(==('#'), replace(a, "initial state: " => "")) .- 1 6 | 7 | rules = split.(split(b, '\n', keepempty=false), " => ") |> 8 | (x -> filter(x -> x[2] == "#", x)) .|> first |> 9 | (x -> findall.(==('#'), x)) .|> 10 | (x -> (x...,) .- 3) |> Set 11 | 12 | neighbours(pot) = pot .+ (-2:2) 13 | spawns(p) = (sort(plants ∩ neighbours(p) .- p)...,) ∈ rules 14 | 15 | function simulate(generations) 16 | result = zeros(Int16, generations) 17 | for gen = 1:generations 18 | l, r = extrema(plants) .+ (-2, 2) 19 | plants = Set{Int16}(p for p = l:r if spawns(p)) 20 | result[gen] = sum(plants) 21 | end 22 | result 23 | end 24 | 25 | N = 150 26 | result = simulate(N) 27 | calculate(n) = n < N ? result[n] : result[end] + 22 * (n - N) 28 | 29 | result₁ = calculate(20) 30 | result₂ = calculate(50_000_000_000) 31 | 32 | # @assert result₁ == 1991 33 | # @assert result₂ == 1100000000511 34 | 35 | result₁, result₂ 36 | end 37 | 38 | export day12 39 | -------------------------------------------------------------------------------- /Advent of Code/2018/14/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day14(n) 2 | score_at(x) = scoreboard[x+1] # Julia is 1-indexed 3 | 4 | function create_more() 5 | new_recipe = score_at(elfs[1]) + score_at(elfs[2]) 6 | append!(scoreboard, parse.(Int, new_recipe |> string |> collect)) 7 | map!(x -> (x + score_at(x) + 1) % length(scoreboard), elfs, elfs) 8 | end 9 | 10 | elfs = [0, 1] 11 | scoreboard = [3, 7] 12 | while length(scoreboard) < n+10; create_more() end 13 | result₁ = string(scoreboard[n+1:n+10]...) 14 | 15 | result₂ = 0 16 | needle = string(n) 17 | 18 | elfs = [0, 1] 19 | scoreboard = [3, 7] 20 | for i = 0:100_000_000 21 | create_more() 22 | if length(scoreboard) ≥ length(needle)+1 23 | haystack = string(scoreboard[end-length(needle):end]...) 24 | pos = findfirst(needle, haystack) 25 | if !isnothing(pos) 26 | result₂ = length(scoreboard) - length(needle) + pos[1] - 2 27 | break 28 | end 29 | end 30 | end 31 | result₂ 32 | 33 | result₁, result₂ 34 | end 35 | 36 | export day14 37 | -------------------------------------------------------------------------------- /Advent of Code/2018/15/input.txt: -------------------------------------------------------------------------------- 1 | ################################ 2 | ################.G#...##...##### 3 | #######..#######..#.G..##..##### 4 | #######....#####........##.##### 5 | ######.....#####.....GG.##.##### 6 | ######..GG.##.###G.........##### 7 | #####........G####.......####### 8 | ######.#..G...####........###### 9 | ##########....#####...G...###### 10 | ########.......###..........#### 11 | #########...GG####............## 12 | #########....................### 13 | ######........#####...E......### 14 | ####....G....#######........#### 15 | ###.........#########.......#### 16 | #...#.G..G..#########..........# 17 | #..###..#...#########E.E....E### 18 | #..##...#...#########.E...E...## 19 | #.....G.....#########.........## 20 | #......G.G...#######........#### 21 | ###..G...#....#####........##### 22 | ###########....G........EE..#### 23 | ##########...................### 24 | ##########...................### 25 | #######.............E....##E#### 26 | #######................######### 27 | ########.#.............######### 28 | #######..#####.#......########## 29 | ######...#######...##.########## 30 | ################..###.########## 31 | ###############.......########## 32 | ################################ -------------------------------------------------------------------------------- /Advent of Code/2018/18/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day18() 2 | input = joinpath(@__DIR__, "input.txt") 3 | state⁺ = mapreduce(collect, hcat, eachline(input)) 4 | 5 | function resourcevalue(state) 6 | trees = count(==('|'), state) 7 | lumberyards = count(==('#'), state) 8 | trees * lumberyards 9 | end 10 | 11 | select(A, I, neighbours) = map(neighbours) do step 12 | checkbounds(Bool, A, I + step) ? A[I + step] : nothing 13 | end 14 | 15 | neighbours = filter(!iszero, CartesianIndices(ntuple(_ -> -1:1, 2))) 16 | state⁻ = similar(state⁺) # We need to track the previous state 17 | 18 | minute2value = map(1:1000) do minute 19 | copyto!(state⁻, state⁺) 20 | 21 | @inbounds for i ∈ CartesianIndices(state⁺) 22 | 23 | if state⁻[i] == ('.') 24 | trees = count(==('|'), select(state⁻, i, neighbours)) 25 | (trees >= 3) && (state⁺[i] = '|') # becomes trees 26 | 27 | elseif state⁻[i] == ('|') 28 | lumberyards = count(==('#'), select(state⁻, i, neighbours)) 29 | (lumberyards >= 3) && (state⁺[i] = '#') # becomes a lumberyard 30 | 31 | elseif state⁻[i] == ('#') 32 | trees = count(==('|'), select(state⁻, i, neighbours)) 33 | lumberyards = count(==('#'), select(state⁻, i, neighbours)) 34 | !(lumberyards >= 1 && trees >= 1) && (state⁺[i] = '.') # becomes open 35 | 36 | end 37 | end 38 | 39 | resourcevalue(state⁺) 40 | end 41 | 42 | result₁ = minute2value[10] 43 | result₂ = minute2value[801:end][mod1(1_000_000_000, 200)] 44 | 45 | # @assert result₁ == 589931 46 | # @assert result₂ == 222332 47 | 48 | result₁, result₂ 49 | end 50 | 51 | export day18 52 | -------------------------------------------------------------------------------- /Advent of Code/2018/19/input.txt: -------------------------------------------------------------------------------- 1 | #ip 3 2 | addi 3 16 3 3 | seti 1 0 4 4 | seti 1 7 2 5 | mulr 4 2 1 6 | eqrr 1 5 1 7 | addr 1 3 3 8 | addi 3 1 3 9 | addr 4 0 0 10 | addi 2 1 2 11 | gtrr 2 5 1 12 | addr 3 1 3 13 | seti 2 6 3 14 | addi 4 1 4 15 | gtrr 4 5 1 16 | addr 1 3 3 17 | seti 1 3 3 18 | mulr 3 3 3 19 | addi 5 2 5 20 | mulr 5 5 5 21 | mulr 3 5 5 22 | muli 5 11 5 23 | addi 1 6 1 24 | mulr 1 3 1 25 | addi 1 13 1 26 | addr 5 1 5 27 | addr 3 0 3 28 | seti 0 6 3 29 | setr 3 1 1 30 | mulr 1 3 1 31 | addr 3 1 1 32 | mulr 3 1 1 33 | muli 1 14 1 34 | mulr 1 3 1 35 | addr 5 1 5 36 | seti 0 0 0 37 | seti 0 3 3 38 | -------------------------------------------------------------------------------- /Advent of Code/2018/Project.toml: -------------------------------------------------------------------------------- 1 | name = "AdventOfCode2018" 2 | uuid = "b6081afc-f272-4f7b-aed6-7feeb6493722" 3 | authors = ["Henrique Ferrolho "] 4 | version = "0.1.0" 5 | 6 | [deps] 7 | BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" 8 | DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" 9 | IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e" 10 | Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" 11 | Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" 12 | SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" 13 | -------------------------------------------------------------------------------- /Advent of Code/2018/README.md: -------------------------------------------------------------------------------- 1 | Start the Julia REPL from within this folder. 2 | -------------------------------------------------------------------------------- /Advent of Code/2018/src/AdventOfCode2018.jl: -------------------------------------------------------------------------------- 1 | module AdventOfCode2018 2 | 3 | # using Colors 4 | using DelimitedFiles 5 | using IterTools 6 | using Plots 7 | using SparseArrays 8 | 9 | greet() = println("Hello, Advent of Code 2018!") 10 | 11 | include("../12/puzzle.jl") 12 | include("../13/puzzle.jl") 13 | include("../14/puzzle.jl") 14 | include("../15/puzzle.jl") 15 | include("../16/puzzle.jl") 16 | include("../17/puzzle.jl") 17 | include("../18/puzzle.jl") 18 | include("../19/puzzle.jl") 19 | 20 | end # module 21 | -------------------------------------------------------------------------------- /Advent of Code/2019/01/input.txt: -------------------------------------------------------------------------------- 1 | 56017 2 | 141632 3 | 71303 4 | 148129 5 | 59828 6 | 83478 7 | 136501 8 | 97611 9 | 92298 10 | 107697 11 | 102886 12 | 57037 13 | 58458 14 | 121031 15 | 119944 16 | 147894 17 | 110097 18 | 146857 19 | 137133 20 | 126985 21 | 81583 22 | 106275 23 | 130025 24 | 99276 25 | 76704 26 | 105244 27 | 111534 28 | 110405 29 | 88847 30 | 106736 31 | 109562 32 | 112705 33 | 50061 34 | 146911 35 | 143213 36 | 126404 37 | 131161 38 | 82251 39 | 56396 40 | 86306 41 | 110074 42 | 94474 43 | 113640 44 | 60274 45 | 102171 46 | 97755 47 | 142020 48 | 100304 49 | 100155 50 | 80432 51 | 124345 52 | 79730 53 | 105762 54 | 114971 55 | 141583 56 | 135170 57 | 87585 58 | 105794 59 | 101571 60 | 62313 61 | 62865 62 | 136660 63 | 121434 64 | 67603 65 | 53325 66 | 76232 67 | 93160 68 | 99580 69 | 90716 70 | 102187 71 | 115997 72 | 134281 73 | 64593 74 | 87597 75 | 131885 76 | 68041 77 | 88209 78 | 136400 79 | 127058 80 | 141613 81 | 66822 82 | 62441 83 | 136063 84 | 134204 85 | 52078 86 | 135123 87 | 95428 88 | 91311 89 | 55524 90 | 97099 91 | 80454 92 | 91710 93 | 130396 94 | 130089 95 | 127464 96 | 86160 97 | 53158 98 | 64908 99 | 98321 100 | 112176 101 | -------------------------------------------------------------------------------- /Advent of Code/2019/01/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day1() 2 | numbers = vec(readdlm("./01/input.txt", Int)) 3 | 4 | map!(x -> floor(x / 3) - 2, numbers, numbers) 5 | result_1 = sum(numbers) 6 | 7 | result_2 = result_1 8 | while !isempty(numbers) 9 | map!(x -> floor(x / 3) - 2, numbers, numbers) 10 | filter!(x -> x ≥ 0, numbers) 11 | result_2 += sum(numbers) 12 | end 13 | 14 | result_1, result_2 15 | end 16 | 17 | export day1 18 | -------------------------------------------------------------------------------- /Advent of Code/2019/02/input.txt: -------------------------------------------------------------------------------- 1 | 1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,13,19,1,9,19,23,1,6,23,27,2,27,9,31,2,6,31,35,1,5,35,39,1,10,39,43,1,43,13,47,1,47,9,51,1,51,9,55,1,55,9,59,2,9,59,63,2,9,63,67,1,5,67,71,2,13,71,75,1,6,75,79,1,10,79,83,2,6,83,87,1,87,5,91,1,91,9,95,1,95,10,99,2,9,99,103,1,5,103,107,1,5,107,111,2,111,10,115,1,6,115,119,2,10,119,123,1,6,123,127,1,127,5,131,2,9,131,135,1,5,135,139,1,139,10,143,1,143,2,147,1,147,5,0,99,2,0,14,0 2 | -------------------------------------------------------------------------------- /Advent of Code/2019/02/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day2_part1(program, noun, verb) 2 | # Julia is 1-indexed 3 | pos(x) = x + 1 4 | get(x) = program[pos(x)] 5 | set!(x, value) = (program[pos(x)] = value) 6 | 7 | # Restore the gravity assist program 8 | set!(1, noun) 9 | set!(2, verb) 10 | 11 | # Execute Intcode program 12 | i = 0 13 | while get(i) != 99 14 | opcode = get(i) 15 | val1 = get(i + 1) 16 | val2 = get(i + 2) 17 | dest = get(i + 3) 18 | 19 | # @show opcode val1 val2 dest 20 | 21 | if opcode == 1 22 | set!(dest, get(val1) + get(val2)) 23 | elseif opcode == 2 24 | set!(dest, get(val1) * get(val2)) 25 | end 26 | 27 | # Move to next instruction 28 | i += 4 29 | end 30 | 31 | get(0) 32 | end 33 | 34 | function day2() 35 | program = vec(readdlm("./02/input.txt", ',', Int)) 36 | result_1 = day2_part1(copy(program), 12, 2) 37 | 38 | result_2 = 0 39 | for noun = 0:99, verb = 0:99 # Brute force 40 | output = day2_part1(copy(program), noun, verb) 41 | if output == 19690720 42 | result_2 = 100 * noun + verb 43 | break 44 | end 45 | end 46 | 47 | result_1, result_2 48 | end 49 | 50 | export day2 51 | -------------------------------------------------------------------------------- /Advent of Code/2019/04/input.txt: -------------------------------------------------------------------------------- 1 | 278384-824795 2 | -------------------------------------------------------------------------------- /Advent of Code/2019/04/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day4() 2 | input = vec(readdlm("./04/input.txt", '-', Int)) 3 | range = input[1]:input[2] 4 | 5 | not_decreasing(s) = join(sort(collect(s))) == s 6 | 7 | function rule_1(s) 8 | # Scan string 9 | for i = 1:length(s)-1 10 | s[i] == s[i+1] && return true 11 | end 12 | return false 13 | end 14 | 15 | function rule_2(s) 16 | # Corner cases 17 | s[1] == s[2] != s[3] && return true 18 | s[end-2] != s[end-1] == s[end] && return true 19 | # Check rest of the string 20 | for i = 2:length(s)-2 21 | s[i-1] != s[i] == s[i+1] != s[i+2] && return true 22 | end 23 | return false 24 | end 25 | 26 | meets_criteria_1(s) = not_decreasing(s) && rule_1(s) 27 | meets_criteria_2(s) = not_decreasing(s) && rule_2(s) 28 | 29 | result_1 = count(x -> meets_criteria_1(string(x)), range) 30 | result_2 = count(x -> meets_criteria_2(string(x)), range) 31 | 32 | result_1, result_2 33 | end 34 | 35 | export day4 36 | -------------------------------------------------------------------------------- /Advent of Code/2019/06/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day6() 2 | # Universal Orbit Map (UOM) 3 | uom_raw = vec(readdlm("./06/input.txt", String)) 4 | uom = map(x -> tuple(split(x, ')')...), uom_raw) 5 | # display(uom) 6 | 7 | # Set of objects in the Universe 8 | objects = Set(vec(readdlm("./06/input.txt", ')', String))) 9 | delete!(objects, "COM") 10 | # display(objects) 11 | 12 | # Helper functions 13 | orbits_around(a, b) = (b, a) ∈ uom 14 | atractor_of(a) = first([x for x ∈ uom if x[2] == a])[1] 15 | distance_to_com(a) = orbits_around(a, "COM") ? 1 : 1 + distance_to_com(atractor_of(a)) 16 | path_to_com(a) = orbits_around(a, "COM") ? [a, "COM"] : [a ; path_to_com(atractor_of(a))] 17 | 18 | result_1 = sum([distance_to_com(x) for x ∈ objects]) 19 | 20 | A = Set(path_to_com(atractor_of("SAN"))) 21 | B = Set(path_to_com(atractor_of("YOU"))) 22 | result_2 = length(setdiff(A, B) ∪ setdiff(B, A)) 23 | 24 | result_1, result_2 25 | end 26 | 27 | export day6 28 | -------------------------------------------------------------------------------- /Advent of Code/2019/07/input.txt: -------------------------------------------------------------------------------- 1 | 3,8,1001,8,10,8,105,1,0,0,21,30,47,64,81,98,179,260,341,422,99999,3,9,1001,9,5,9,4,9,99,3,9,1002,9,5,9,101,4,9,9,102,2,9,9,4,9,99,3,9,102,3,9,9,101,2,9,9,1002,9,3,9,4,9,99,3,9,1001,9,5,9,1002,9,3,9,1001,9,3,9,4,9,99,3,9,1002,9,3,9,101,2,9,9,102,5,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,99,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,99 2 | -------------------------------------------------------------------------------- /Advent of Code/2019/08/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day8() 2 | # Read and store input as ::Array{Char} 3 | data = collect(first(readdlm("./08/input.txt", String))) 4 | 5 | width, height = 25, 6 6 | num_layers = length(data) ÷ (width * height) 7 | 8 | image = parse.(Int, reshape(data, (width,height,num_layers))) 9 | image = permutedims(image, [2,1,3]) # Transpose each layer; Julia is column-major 10 | 11 | layerₖ = argmin(count.(iszero, eachslice(image, dims=3))) 12 | n₁ = count(x -> x == 1, image[:,:,layerₖ]) 13 | n₂ = count(x -> x == 2, image[:,:,layerₖ]) 14 | result₁ = n₁ * n₂ 15 | 16 | # Helper function 17 | rendering_complete(img) = count(x -> x == 2, img) == 0 18 | 19 | render = fill(2, (height,width)) 20 | for layer in eachslice(image, dims=3) 21 | # Overwrite transparent pixels 22 | indices = findall(x -> x == 2, render) 23 | render[indices] = layer[indices] 24 | # _If_ render has completed _then_ break the loop 25 | rendering_complete(render) && break 26 | end 27 | result₂ = plot(Gray.(render), aspect_ratio=1, axis=nothing, bg=:black) 28 | 29 | result₁, result₂ 30 | end 31 | 32 | export day8 33 | -------------------------------------------------------------------------------- /Advent of Code/2019/10/input.txt: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Advent of Code/2019/12/input.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Advent of Code/2019/16/input.txt: -------------------------------------------------------------------------------- 1 | 59754835304279095723667830764559994207668723615273907123832849523285892960990393495763064170399328763959561728553125232713663009161639789035331160605704223863754174835946381029543455581717775283582638013183215312822018348826709095340993876483418084566769957325454646682224309983510781204738662326823284208246064957584474684120465225052336374823382738788573365821572559301715471129142028462682986045997614184200503304763967364026464055684787169501819241361777789595715281841253470186857857671012867285957360755646446993278909888646724963166642032217322712337954157163771552371824741783496515778370667935574438315692768492954716331430001072240959235708 2 | -------------------------------------------------------------------------------- /Advent of Code/2019/16/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day16() 2 | input = parse.(Int, readline("./16/input.txt") |> collect) 3 | 4 | # Helper functions 5 | ones_digit(x::Number) = abs(x) % 10 6 | patternₖ(base::Array, x::Int) = repeat(base, inner = x, outer = ceil(Int, n / (4 * x) + 1))[2:n + 1] 7 | 8 | # Part 1 9 | signalᵢ = copy(input) 10 | signalᵢ₊₁ = copy(input) 11 | n = length(signalᵢ) 12 | patterns = Dict(i => patternₖ([0, 1, 0, -1], i) for i = 1:n) 13 | 14 | for phaseᵢ = 1:100 15 | for i = 1:n; signalᵢ₊₁[i] = signalᵢ ⋅ patterns[i] |> ones_digit end 16 | signalᵢ = signalᵢ₊₁ 17 | end 18 | result₁ = parse(Int, signalᵢ₊₁[1:8] |> join) 19 | 20 | # Part 2 21 | offset = parse(Int, input[1:7] |> join) 22 | signalᵢ = copy(repeat(input, 10000))[offset + 1:end] 23 | n = length(signalᵢ) 24 | 25 | for phaseᵢ = 1:100 26 | signalᵢ = signalᵢ |> reverse |> cumsum |> reverse .|> ones_digit 27 | end 28 | result₂ = parse(Int, signalᵢ[1:8] |> join) 29 | 30 | result₁, result₂ 31 | end 32 | 33 | export day16 34 | -------------------------------------------------------------------------------- /Advent of Code/2019/19/input.txt: -------------------------------------------------------------------------------- 1 | 109,424,203,1,21102,1,11,0,1105,1,282,21101,18,0,0,1106,0,259,2101,0,1,221,203,1,21102,1,31,0,1106,0,282,21101,0,38,0,1106,0,259,21002,23,1,2,22102,1,1,3,21101,0,1,1,21102,57,1,0,1106,0,303,2102,1,1,222,21002,221,1,3,21002,221,1,2,21101,0,259,1,21101,0,80,0,1105,1,225,21101,123,0,2,21101,91,0,0,1105,1,303,1201,1,0,223,20101,0,222,4,21101,259,0,3,21102,225,1,2,21101,0,225,1,21102,118,1,0,1105,1,225,21001,222,0,3,21102,58,1,2,21101,133,0,0,1105,1,303,21202,1,-1,1,22001,223,1,1,21102,1,148,0,1106,0,259,1201,1,0,223,20101,0,221,4,21002,222,1,3,21101,20,0,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21101,195,0,0,105,1,109,20207,1,223,2,20102,1,23,1,21101,-1,0,3,21102,214,1,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2101,0,-4,249,22102,1,-3,1,22102,1,-2,2,22101,0,-1,3,21101,250,0,0,1105,1,225,21202,1,1,-4,109,-5,2105,1,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,21201,-2,0,-2,109,-3,2106,0,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,22102,1,-2,3,21102,1,343,0,1105,1,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21201,-4,0,1,21102,1,384,0,1106,0,303,1105,1,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,21201,1,0,-4,109,-5,2105,1,0 2 | -------------------------------------------------------------------------------- /Advent of Code/2019/24/input.txt: -------------------------------------------------------------------------------- 1 | ..#.# 2 | .#.## 3 | ..?#. 4 | ...## 5 | #.### 6 | -------------------------------------------------------------------------------- /Advent of Code/2019/Project.toml: -------------------------------------------------------------------------------- 1 | name = "Advent2019" 2 | uuid = "14784a84-53a6-491f-b53f-dc1a71467a96" 3 | authors = ["Henrique Ferrolho "] 4 | version = "0.1.0" 5 | 6 | [deps] 7 | BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" 8 | DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" 9 | DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" 10 | IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e" 11 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 12 | Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" 13 | SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" 14 | -------------------------------------------------------------------------------- /Advent of Code/2019/README.md: -------------------------------------------------------------------------------- 1 | Start the Julia REPL from within this folder. 2 | -------------------------------------------------------------------------------- /Advent of Code/2019/src/Advent2019.jl: -------------------------------------------------------------------------------- 1 | module Advent2019 2 | 3 | using BenchmarkTools 4 | using DataStructures 5 | using DelimitedFiles 6 | using IterTools 7 | using LinearAlgebra: ⋅, norm 8 | using Plots 9 | using SparseArrays 10 | 11 | greet() = println("Hello, Advent of Code 2019!") 12 | 13 | include("../01/puzzle.jl") 14 | include("../02/puzzle.jl") 15 | include("../03/puzzle.jl") 16 | include("../04/puzzle.jl") 17 | include("../05/puzzle.jl") 18 | include("../06/puzzle.jl") 19 | include("../07/puzzle.jl") 20 | include("../08/puzzle.jl") 21 | include("../09/puzzle.jl") 22 | include("../10/puzzle.jl") 23 | include("../11/puzzle.jl") 24 | include("../12/puzzle.jl") 25 | include("../13/puzzle.jl") 26 | include("../14/puzzle.jl") 27 | include("../15/puzzle.jl") 28 | include("../16/puzzle.jl") 29 | include("../17/puzzle.jl") 30 | include("../18/puzzle.jl") 31 | include("../19/puzzle.jl") 32 | include("../20/puzzle.jl") 33 | include("../21/puzzle.jl") 34 | include("../22/puzzle.jl") 35 | include("../23/puzzle.jl") 36 | include("../24/puzzle.jl") 37 | include("../25/puzzle.jl") 38 | 39 | export greet 40 | 41 | end # module 42 | -------------------------------------------------------------------------------- /Advent of Code/2020/01/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day1() 2 | expenses = vec(readdlm(joinpath(@__DIR__, "input.txt"), Int)) 3 | 4 | function part1(expenses) 5 | for i = 1:length(expenses) - 1 6 | for j = i + 1:length(expenses) 7 | if expenses[i] + expenses[j] == 2020 8 | return expenses[i] * expenses[j] 9 | end 10 | end 11 | end 12 | end 13 | 14 | function part2(expenses) 15 | for i = 1:length(expenses) - 2 16 | for j = i + 1:length(expenses) - 1 17 | for k = i + j + 1:length(expenses) 18 | if expenses[i] + expenses[j] + expenses[k] == 2020 19 | return expenses[i] * expenses[j] * expenses[k] 20 | end 21 | end 22 | end 23 | end 24 | end 25 | 26 | result₁ = @btime $part1($expenses) 27 | result₂ = @btime $part2($expenses) 28 | 29 | result₁, result₂ 30 | end 31 | 32 | export day1 33 | -------------------------------------------------------------------------------- /Advent of Code/2020/02/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day2() 2 | entries = readlines(joinpath(@__DIR__, "input.txt")) 3 | entries = [(parse(Int, l), parse(Int, u), first(c), pw) 4 | for (l, u, c, pw) in split.(entries, r"[- :]", keepempty=false)] 5 | 6 | function part1(entries) 7 | count(entries) do (l, u, c, pw) 8 | l ≤ count(==(c), pw) ≤ u 9 | end 10 | end 11 | 12 | function part2(entries) 13 | count(entries) do (l, u, c, pw) 14 | (pw[l] == c) ⊻ (pw[u] == c) 15 | end 16 | end 17 | 18 | result₁ = @btime $part1($entries) 19 | result₂ = @btime $part2($entries) 20 | 21 | result₁, result₂ 22 | end 23 | 24 | export day2 25 | -------------------------------------------------------------------------------- /Advent of Code/2020/03/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day3() 2 | input = joinpath(@__DIR__, "input.txt") 3 | trees = mapreduce(collect, hcat, eachline(input)) |> permutedims 4 | 5 | function count_trees_for_slope(trees, slope) 6 | # Number of coordinates to be checked 7 | n = cld(size(trees, 1), slope.down) 8 | 9 | # Row- and column-coordinates to be checked 10 | rs = range(1, step=slope.down, length=n) 11 | cs = range(0, step=slope.right, length=n) 12 | 13 | # The problem says the tree pattern repeats to the right indefinitely. 14 | # Trick: we don't actually need to copy the pattern; instead, 15 | # we can simply wrap the column-coordinates around. 16 | cs = map(x -> x % size(trees, 2) + 1, cs) 17 | 18 | idxs = CartesianIndex.(rs, cs) 19 | count(==('#'), trees[idxs]) 20 | end 21 | 22 | function part1(trees) 23 | slope = (right = 3, down = 1) 24 | count_trees_for_slope(trees, slope) 25 | end 26 | 27 | function part2(trees) 28 | slopes = [(right = 1, down = 1) 29 | (right = 3, down = 1) 30 | (right = 5, down = 1) 31 | (right = 7, down = 1) 32 | (right = 1, down = 2)] 33 | 34 | prod(x -> count_trees_for_slope(trees, x), slopes) 35 | end 36 | 37 | result₁ = part1(trees) 38 | result₂ = part2(trees) 39 | 40 | # result₁ = @btime $part1($trees) 41 | # result₂ = @btime $part2($trees) 42 | 43 | result₁, result₂ 44 | end 45 | 46 | export day3 47 | -------------------------------------------------------------------------------- /Advent of Code/2020/05/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day5() 2 | input = joinpath(@__DIR__, "input.txt") 3 | bps = readlines(input) 4 | 5 | function seatid(bp) 6 | rows, cols = 0:127, 0:7 7 | 8 | for c in bp 9 | c == 'F' && (rows = first(rows):floor(Int, median(rows))) 10 | c == 'B' && (rows = ceil(Int, median(rows)):last(rows)) 11 | c == 'L' && (cols = first(cols):floor(Int, median(cols))) 12 | c == 'R' && (cols = ceil(Int, median(cols)):last(cols)) 13 | end 14 | 15 | only(rows) * 8 + only(cols) # Seat ID formula 16 | end 17 | 18 | seat_ids = seatid.(bps) 19 | max_id = maximum(seat_ids) 20 | min_id = minimum(seat_ids) 21 | 22 | result₁ = max_id 23 | result₂ = setdiff(min_id:max_id, seat_ids) |> only 24 | 25 | result₁, result₂ 26 | end 27 | 28 | """ 29 | Alternative solution to day 5. It is a modification to my original solution, which 30 | replaces the `seatid` function with a clever one-liner I found in an online discussion. 31 | The trick: converting the boarding pass to a 10-bit integer directly results in the seat ID. 32 | """ 33 | function day5spoiled() 34 | input = joinpath(@__DIR__, "input.txt") 35 | bps = readlines(input) 36 | 37 | # This is the clever one-liner stolen from Reddit. 38 | seatid(bp) = parse(Int, map(c -> c ∈ ('B', 'R') ? '1' : '0', bp), base=2) 39 | 40 | seat_ids = seatid.(bps) 41 | max_id = maximum(seat_ids) 42 | min_id = minimum(seat_ids) 43 | 44 | result₁ = max_id 45 | result₂ = setdiff(min_id:max_id, seat_ids) |> only 46 | 47 | result₁, result₂ 48 | end 49 | 50 | export day5 51 | -------------------------------------------------------------------------------- /Advent of Code/2020/06/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day6() 2 | input = joinpath(@__DIR__, "input.txt") 3 | groups = split(read(input, String), "\n\n") 4 | 5 | group_chars = map(groups) do s 6 | replace(s, "\n" => "") |> unique 7 | end 8 | 9 | result₁ = sum(length.(group_chars)) 10 | 11 | result₂ = 0 12 | 13 | for (chars, ppl) in zip(group_chars, split.(groups)) 14 | result₂ += count(chars) do c # Count the chars that occur 15 | all(occursin.(c, ppl)) # in all people from that group. 16 | end 17 | end 18 | 19 | result₁, result₂ 20 | end 21 | 22 | export day6 23 | -------------------------------------------------------------------------------- /Advent of Code/2020/07/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day7() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | rules = Dict{String,Union{Nothing,Dict}}() 5 | 6 | for line in eachline(input) 7 | bag, content = split(line, "bags contain") .|> strip 8 | 9 | if occursin("no other bags", content) 10 | rules[bag] = nothing 11 | else 12 | content = replace(content, r"(\bbags?\b)|(\.)" => "") 13 | content = split(content, ",") .|> strip .|> x -> split(x, limit=2) 14 | keys, values = last.(content), parse.(Int, first.(content)) 15 | rules[bag] = Dict{String,Int}(keys .=> values) 16 | end 17 | end 18 | 19 | function containsbag(haystack::AbstractString, needle) 20 | if isnothing(rules[haystack]) 21 | false 22 | elseif needle ∈ keys(rules[haystack]) 23 | true 24 | else 25 | any(containsbag.(keys(rules[haystack]), needle)) 26 | end 27 | end 28 | 29 | cache = Dict{String,Int}() 30 | 31 | function totalbags(bag) 32 | haskey(cache, bag) && return cache[bag] 33 | 34 | if isnothing(rules[bag]) 35 | cache[bag] = 0 36 | else 37 | cache[bag] = sum(rules[bag]) do (k, v) 38 | v + v * totalbags(k) 39 | end 40 | end 41 | 42 | cache[bag] 43 | end 44 | 45 | result₁ = count(keys(rules)) do bag 46 | containsbag(bag, "shiny gold") 47 | end 48 | 49 | result₂ = totalbags("shiny gold") 50 | 51 | result₁, result₂ 52 | end 53 | 54 | export day7 55 | -------------------------------------------------------------------------------- /Advent of Code/2020/09/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day9() 2 | input = joinpath(@__DIR__, "input.txt") 3 | data = parse.(Int, readlines(input)) 4 | 5 | validsum(number, valid) = any((number - term) ∈ valid for term ∈ valid) 6 | 7 | function part1(data; preamble=25) 8 | for i = preamble + 1:length(data) 9 | number = data[i] 10 | valid = @view data[i - preamble:i - 1] 11 | 12 | !validsum(number, valid) && return number 13 | end 14 | end 15 | 16 | function part2(data, target; preamble=25) 17 | for i = 1:length(data) - 1 # idx of contiguous set *start* 18 | for j = i + 1:length(data) # idx of contiguous set *end* 19 | window = @view data[i:j] 20 | total = sum(window) 21 | if total == target 22 | return sum(extrema(window)) 23 | elseif total > target 24 | break 25 | end 26 | end 27 | end 28 | end 29 | 30 | result₁ = part1(data) 31 | result₂ = part2(data, result₁) 32 | 33 | # @btime $part1($data) 34 | # @btime $part2($data, $result₁) 35 | 36 | result₁, result₂ 37 | end 38 | 39 | export day9 40 | -------------------------------------------------------------------------------- /Advent of Code/2020/10/input.txt: -------------------------------------------------------------------------------- 1 | 153 2 | 17 3 | 45 4 | 57 5 | 16 6 | 147 7 | 39 8 | 121 9 | 75 10 | 70 11 | 85 12 | 134 13 | 128 14 | 115 15 | 51 16 | 139 17 | 44 18 | 65 19 | 119 20 | 168 21 | 122 22 | 72 23 | 105 24 | 31 25 | 103 26 | 89 27 | 154 28 | 114 29 | 55 30 | 25 31 | 48 32 | 38 33 | 132 34 | 157 35 | 84 36 | 71 37 | 113 38 | 143 39 | 83 40 | 64 41 | 109 42 | 129 43 | 120 44 | 100 45 | 151 46 | 79 47 | 125 48 | 22 49 | 161 50 | 167 51 | 19 52 | 26 53 | 118 54 | 142 55 | 4 56 | 158 57 | 11 58 | 35 59 | 56 60 | 18 61 | 40 62 | 7 63 | 150 64 | 99 65 | 54 66 | 152 67 | 60 68 | 27 69 | 164 70 | 78 71 | 47 72 | 82 73 | 63 74 | 46 75 | 91 76 | 32 77 | 135 78 | 3 79 | 108 80 | 10 81 | 159 82 | 127 83 | 69 84 | 110 85 | 126 86 | 133 87 | 28 88 | 15 89 | 104 90 | 138 91 | 160 92 | 98 93 | 90 94 | 144 95 | 1 96 | 2 97 | 92 98 | 41 99 | 86 100 | 66 101 | 95 102 | 12 103 | -------------------------------------------------------------------------------- /Advent of Code/2020/10/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day10() 2 | input = joinpath(@__DIR__, "input.txt") 3 | data = parse.(Int, readlines(input)) |> sort 4 | data = [ 0 ; data ; data[end] + 3 ] 5 | 6 | function part1(data) 7 | diffs = diff(data) 8 | 9 | diff₁ = count(==(1), diffs) 10 | diff₃ = count(==(3), diffs) 11 | 12 | diff₁ * diff₃ 13 | end 14 | 15 | function part2(data) 16 | strs = split(string(diff(data)...), "3", keepempty=false) 17 | 18 | l₂ = count(s -> length(s) == 2, strs) 19 | l₃ = count(s -> length(s) == 3, strs) 20 | l₄ = count(s -> length(s) == 4, strs) 21 | 22 | 2^l₂ * 4^l₃ * 7^l₄ 23 | end 24 | 25 | result₁ = part1(data) 26 | result₂ = part2(data) 27 | 28 | # @btime $part1($data) 29 | # @btime $part2($data) 30 | 31 | result₁, result₂ 32 | end 33 | 34 | export day10 35 | -------------------------------------------------------------------------------- /Advent of Code/2020/13/input.txt: -------------------------------------------------------------------------------- 1 | 1000186 2 | 17,x,x,x,x,x,x,x,x,x,x,37,x,x,x,x,x,907,x,x,x,x,x,x,x,x,x,x,x,19,x,x,x,x,x,x,x,x,x,x,23,x,x,x,x,x,29,x,653,x,x,x,x,x,x,x,x,x,41,x,x,13 3 | -------------------------------------------------------------------------------- /Advent of Code/2020/13/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day13() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | function parseinput(input) 5 | lines = readlines(input) 6 | 7 | timestamp = parse(Int, lines[1]) 8 | periods = map(id -> parse(Int, id), split(lines[2], (',', 'x'), keepempty=false)) 9 | 10 | tokens = tryparse.(Int, split(lines[2], ',')) 11 | offsets = range(0, length=length(tokens)) .=> tokens 12 | offsets = filter!(x -> !isnothing(x[2]), offsets) .|> first 13 | 14 | timestamp, periods, offsets 15 | end 16 | 17 | function part₁(t, periods) 18 | due = periods .* cld.(t, periods) 19 | wait = minimum(due) - t 20 | id = periods[argmin(due)] 21 | return id * wait 22 | end 23 | 24 | function merge(offsets, periods) 25 | for t = 0:periods[1]:lcm(periods...) 26 | ts = t .+ offsets 27 | if ts[2] .% periods[2] == 0 28 | return ts[1], lcm(periods...) 29 | end 30 | end 31 | end 32 | 33 | function part₂(offsets, periods) 34 | bus = (0, 1) # Start with a bus with T=1 35 | 36 | for i = 1:length(periods) 37 | new_offsets = (bus[1], offsets[i] + bus[1]) 38 | new_periods = (bus[2], periods[i]) 39 | bus = merge(new_offsets, new_periods) 40 | end 41 | 42 | bus[1] 43 | end 44 | 45 | timestamp, periods, offsets = parseinput(input) 46 | result₁ = part₁(timestamp, periods) 47 | result₂ = part₂(offsets, periods) 48 | 49 | # @btime $part₁($timestamp, $periods) 50 | # @btime $part₂($offsets, $periods) 51 | 52 | result₁, result₂ 53 | end 54 | 55 | export day13 56 | -------------------------------------------------------------------------------- /Advent of Code/2020/15/input.txt: -------------------------------------------------------------------------------- 1 | 1,0,15,2,10,13 2 | -------------------------------------------------------------------------------- /Advent of Code/2020/15/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day15() 2 | input = joinpath(@__DIR__, "input.txt") 3 | start = vec(readdlm(input, ',', Int)) 4 | 5 | memory = Dict{Int,Array{Int,1}}(start .=> [[i] for i = 1:length(start)]) 6 | 7 | prev = last(start) 8 | curr = nothing 9 | 10 | result₁ = nothing 11 | result₂ = nothing 12 | 13 | for i = length(start) + 1:30000000 14 | 15 | if length(memory[prev]) == 1 16 | curr = 0 17 | else 18 | tₙ = memory[prev][end] 19 | tₙ₋₁ = memory[prev][end - 1] 20 | curr = tₙ - tₙ₋₁ 21 | end 22 | 23 | (curr ∉ keys(memory)) && (memory[curr] = []) 24 | push!(memory[curr], i) 25 | 26 | (i == 2020) && (result₁ = curr) 27 | (i == 30000000) && (result₂ = curr) 28 | 29 | prev = curr 30 | 31 | end 32 | 33 | result₁, result₂ 34 | end 35 | 36 | export day15 37 | -------------------------------------------------------------------------------- /Advent of Code/2020/17/input.txt: -------------------------------------------------------------------------------- 1 | ..#....# 2 | ##.#..## 3 | .###.... 4 | #....#.# 5 | #.###### 6 | ##.#.... 7 | #....... 8 | .#...... 9 | -------------------------------------------------------------------------------- /Advent of Code/2020/17/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day17() 2 | input = joinpath(@__DIR__, "input.txt") 3 | state₀ = mapreduce(collect, hcat, eachline(input)) 4 | 5 | isactive = ==('#') 6 | 7 | select(A, I, neighbours) = map(neighbours) do step 8 | checkbounds(Bool, A, I + step) ? A[I + step] : return nothing 9 | end 10 | 11 | function solve(state₀; cycles=6, dims=3) 12 | neighbours = filter(!iszero, CartesianIndices(ntuple(_ -> -1:1, dims))) 13 | 14 | state₀ = reshape(state₀, size(state₀)..., fill(1, dims - 2)...) 15 | 16 | state⁺ = fill('.', fill(19, dims)...) # Create world 17 | offset = cld.(size(state⁺), 2) .- cld.(size(state₀), 2) 18 | Rdest = CartesianIndices(state₀) .+ CartesianIndex(offset) 19 | state⁺[Rdest] = state₀ # Copy initial state to the center 20 | 21 | state⁻ = similar(state⁺) # We need to track the previous state 22 | 23 | for _ = 1:cycles 24 | 25 | copyto!(state⁻, state⁺) 26 | 27 | @inbounds for i ∈ CartesianIndices(state⁺) 28 | 29 | if state⁻[i] |> isactive 30 | active = count(isactive, select(state⁻, i, neighbours)) 31 | !(2 <= active <= 3) && (state⁺[i] = '.') # becomes empty 32 | 33 | else 34 | active = count(isactive, select(state⁻, i, neighbours)) 35 | (active == 3) && (state⁺[i] = '#') # becomes active 36 | 37 | end 38 | end 39 | end 40 | 41 | count(isactive, state⁺) 42 | end 43 | 44 | result₁ = solve(state₀, dims=3) 45 | result₂ = solve(state₀, dims=4) 46 | 47 | result₁, result₂ 48 | end 49 | 50 | export day17 51 | -------------------------------------------------------------------------------- /Advent of Code/2020/18/puzzle.jl: -------------------------------------------------------------------------------- 1 | ⟰ = ⩎ = + # Define unicode operators to override precedence 2 | 3 | """ 4 | "Borrowed" from @dgkf's solution. :-) 5 | 6 | For a complete list of *every* Julia operator's precedence, see the top of this file: 7 | [`src/julia-parser.scm`](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm). 8 | """ 9 | function day18() 10 | input = joinpath(@__DIR__, "input.txt") 11 | expressions = readlines(input) 12 | 13 | result₁, result₂ = (sum(expressions) do expression 14 | replace(expression, '+' => ch) |> Meta.parse |> eval 15 | end for ch ∈ ('⩎', '⟰')) 16 | 17 | # @assert result₁ == 86311597203806 18 | # @assert result₂ == 276894767062189 19 | 20 | result₁, result₂ 21 | end 22 | 23 | export day18 24 | -------------------------------------------------------------------------------- /Advent of Code/2020/19/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day19() 2 | input = joinpath(@__DIR__, "input.txt") 3 | rules_str, messages_str = split(read(input, String), "\n\n") .|> 4 | x -> split(x, '\n', keepempty=false) 5 | 6 | rules = Dict{Int,Union{Char,Array{Array{Int,1},1}}}() 7 | 8 | for str ∈ rules_str 9 | k, v = split(str, ": ") 10 | k = parse(Int, k) 11 | 12 | if v == "\"a\"" 13 | rules[k] = 'a' 14 | elseif v == "\"b\"" 15 | rules[k] = 'b' 16 | else 17 | options = split.(split(v, "|")) .|> 18 | x -> parse.(Int, x) 19 | rules[k] = options 20 | end 21 | end 22 | 23 | function aux(rules, k, part₂=false) 24 | if typeof(rules[k]) == Char 25 | rules[k] 26 | else 27 | "(" * join(map(rules[k]) do rule 28 | "(" * join(map(rule) do x 29 | if part₂ && x == 8 30 | p42 = aux(rules, 42) 31 | "$p42+" 32 | elseif part₂ && x == 11 33 | p42 = aux(rules, 42) 34 | p31 = aux(rules, 31) 35 | "(?$p42\\g?$p31)" 36 | else 37 | aux(rules, x) 38 | end 39 | end) * ")" 40 | end, "|") * ")" 41 | end 42 | end 43 | 44 | rx = Regex(string("\\b", aux(rules, 0), "\\b")) 45 | result₁ = count(x -> occursin(rx, x), messages_str) 46 | 47 | rx = Regex(string("\\b", aux(rules, 0, true), "\\b")) 48 | result₂ = count(x -> occursin(rx, x), messages_str) 49 | 50 | # @assert result₁ == 162 51 | # @assert result₂ == 267 52 | 53 | result₁, result₂ 54 | end 55 | 56 | export day19 57 | -------------------------------------------------------------------------------- /Advent of Code/2020/22/input.txt: -------------------------------------------------------------------------------- 1 | Player 1: 2 | 28 3 | 13 4 | 25 5 | 16 6 | 38 7 | 3 8 | 14 9 | 6 10 | 29 11 | 2 12 | 47 13 | 20 14 | 35 15 | 43 16 | 30 17 | 39 18 | 21 19 | 42 20 | 50 21 | 48 22 | 23 23 | 11 24 | 34 25 | 24 26 | 41 27 | 28 | Player 2: 29 | 27 30 | 37 31 | 9 32 | 10 33 | 17 34 | 31 35 | 19 36 | 33 37 | 40 38 | 12 39 | 32 40 | 1 41 | 18 42 | 36 43 | 49 44 | 46 45 | 26 46 | 4 47 | 45 48 | 8 49 | 15 50 | 5 51 | 44 52 | 22 53 | 7 54 | -------------------------------------------------------------------------------- /Advent of Code/2020/22/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day22() 2 | input = joinpath(@__DIR__, "input.txt") 3 | p₁, p₂ = split(read(input, String), "\n\n") .|> 4 | x -> parse.(Int, split(x, '\n', keepempty=false)[2:end]) 5 | 6 | function play(p₁, p₂, part₂) 7 | seen = Set{Tuple{Array,Array}}([]) 8 | 9 | while !any(isempty.((p₁, p₂))) 10 | (p₁, p₂) ∈ seen && return 1, p₁ # infinite-game-prevention rule 11 | push!(seen, copy.((p₁, p₂))) 12 | 13 | c₁, c₂ = popfirst!.((p₁, p₂)) # both players draw their top card 14 | 15 | if part₂ && all(length.((p₁, p₂)) .>= (c₁, c₂)) 16 | w, _ = play(copy.((p₁[1:c₁], p₂[1:c₂]))..., part₂) 17 | elseif c₁ > c₂ w = 1 18 | elseif c₂ > c₁ w = 2 19 | else @error "Unexpected case: c₁ == c₂" end 20 | 21 | w == 1 && push!(p₁, c₁, c₂) # player 1 wins 22 | w == 2 && push!(p₂, c₂, c₁) # player 2 wins 23 | end 24 | 25 | !isempty(p₁) ? (1, p₁) : (2, p₂) 26 | end 27 | 28 | result₁, result₂ = map([false, true]) do part₂ 29 | _, deck = play(copy.((p₁, p₂))..., part₂) 30 | multipliers = length(deck):-1:1 31 | sum(deck .* multipliers) 32 | end 33 | 34 | result₁, result₂ 35 | end 36 | 37 | export day22 38 | -------------------------------------------------------------------------------- /Advent of Code/2020/23/input.txt: -------------------------------------------------------------------------------- 1 | 792845136 2 | -------------------------------------------------------------------------------- /Advent of Code/2020/24/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day24() 2 | input = joinpath(@__DIR__, "input.txt") 3 | 4 | cube_directions = Dict{String,Tuple}( 5 | "e" => (+1, -1, 0), "ne" => (+1, 0, -1), "nw" => (0, +1, -1), 6 | "w" => (-1, +1, 0), "sw" => (-1, 0, +1), "se" => (0, -1, +1), 7 | # See https://www.redblobgames.com/grids/hexagons/#neighbors-cube 8 | ) 9 | 10 | counter = Dict{Tuple,Int}() 11 | 12 | for line = eachline(input) 13 | m = eachmatch(r"(e|ne|nw|w|sw|se)", line) 14 | instructions = map(x -> only(x.captures), collect(m)) 15 | steps = map(x -> collect(cube_directions[x]), instructions) 16 | 17 | destination = sum(steps) 18 | key = tuple(destination...) 19 | counter[key] = get(counter, key, 0) + 1 20 | end 21 | 22 | black_tiles = Set(k for (k, v) ∈ counter if isodd(v)) 23 | 24 | result₁ = length(black_tiles) 25 | # @assert result₁ == 488 26 | 27 | neighbours(coord) = map(x -> coord .+ x, values(cube_directions)) 28 | 29 | for day = 1:100 30 | tobechecked = black_tiles ∪ reduce(∪, neighbours.(black_tiles)) 31 | 32 | next_black_tiles = Set([]) 33 | 34 | for tile ∈ tobechecked 35 | n = length(neighbours(tile) ∩ black_tiles) 36 | 37 | if n == 0 || n > 2 38 | # becomes white 39 | elseif n == 2 || tile ∈ black_tiles 40 | # becomes black 41 | push!(next_black_tiles, tile) 42 | end 43 | end 44 | 45 | black_tiles = next_black_tiles 46 | 47 | day % 10 == 0 && println("Day $(day): $(length(black_tiles))") 48 | end 49 | 50 | result₂ = length(black_tiles) 51 | # @assert result₂ == 4118 52 | 53 | result₁, result₂ 54 | end 55 | 56 | export day24 57 | -------------------------------------------------------------------------------- /Advent of Code/2020/25/input.txt: -------------------------------------------------------------------------------- 1 | 10604480 2 | 4126658 3 | -------------------------------------------------------------------------------- /Advent of Code/2020/25/puzzle.jl: -------------------------------------------------------------------------------- 1 | """ 2 | See [Diffie–Hellman key exchange](https://en.wikipedia.org/wiki/Diffie–Hellman_key_exchange). 3 | """ 4 | function day25() 5 | input = joinpath(@__DIR__, "input.txt") 6 | pkᶜ, pkᵈ = parse.(Int, readlines(input)) 7 | 8 | sn, p = 7, 20201227 9 | 10 | function transform(sn, ls; value=1) 11 | for _ = 1:ls 12 | value = value * sn % p 13 | end 14 | value 15 | end 16 | 17 | function findls(sn, pk; value=1) 18 | ls = 0 19 | while value != pk 20 | value = value * sn % p 21 | ls += 1 22 | end 23 | ls 24 | end 25 | 26 | ekᶜ = transform(pkᵈ, findls(sn, pkᶜ)) 27 | ekᵈ = transform(pkᶜ, findls(sn, pkᵈ)) 28 | @assert ekᶜ == ekᵈ 29 | 30 | ekᶜ 31 | end 32 | 33 | export day25 34 | -------------------------------------------------------------------------------- /Advent of Code/2020/Project.toml: -------------------------------------------------------------------------------- 1 | name = "AdventOfCode2020" 2 | uuid = "58431eaf-e7ad-48ce-9a0d-e50210bea6f0" 3 | authors = ["Henrique Ferrolho "] 4 | version = "0.1.0" 5 | 6 | [deps] 7 | BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" 8 | DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" 9 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 10 | Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" 11 | Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 12 | -------------------------------------------------------------------------------- /Advent of Code/2020/README.md: -------------------------------------------------------------------------------- 1 | Start the Julia REPL from within this folder. 2 | -------------------------------------------------------------------------------- /Advent of Code/2020/src/AdventOfCode2020.jl: -------------------------------------------------------------------------------- 1 | module AdventOfCode2020 2 | 3 | using BenchmarkTools 4 | using DelimitedFiles 5 | using LinearAlgebra 6 | using Statistics 7 | 8 | greet() = println("Hello, Advent of Code 2020!") 9 | 10 | include("../01/puzzle.jl") 11 | include("../02/puzzle.jl") 12 | include("../03/puzzle.jl") 13 | include("../04/puzzle.jl") 14 | include("../05/puzzle.jl") 15 | include("../06/puzzle.jl") 16 | include("../07/puzzle.jl") 17 | include("../08/puzzle.jl") 18 | include("../09/puzzle.jl") 19 | include("../10/puzzle.jl") 20 | include("../11/puzzle.jl") 21 | include("../12/puzzle.jl") 22 | include("../13/puzzle.jl") 23 | include("../14/puzzle.jl") 24 | include("../15/puzzle.jl") 25 | include("../16/puzzle.jl") 26 | include("../17/puzzle.jl") 27 | include("../18/puzzle.jl") 28 | include("../19/puzzle.jl") 29 | include("../20/puzzle.jl") 30 | include("../21/puzzle.jl") 31 | include("../22/puzzle.jl") 32 | include("../23/puzzle.jl") 33 | include("../24/puzzle.jl") 34 | include("../25/puzzle.jl") 35 | 36 | end # module 37 | -------------------------------------------------------------------------------- /Advent of Code/2021/01/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day1_parseinput() 2 | vec(readdlm(joinpath(@__DIR__, "input.txt"), Int)) 3 | end 4 | 5 | day1_part1(input) = diff(input) |> x -> count(>(0), x) 6 | day1_part2(input) = partition(input, 3, 1) .|> sum |> diff |> x -> count(>(0), x) 7 | 8 | @testset "day01" begin 9 | day1_input = day1_parseinput() 10 | @test day1_part1(day1_input) == 1696 11 | @test day1_part2(day1_input) == 1737 12 | end 13 | 14 | export day1_parseinput, day1_part1, day1_part2 15 | -------------------------------------------------------------------------------- /Advent of Code/2021/02/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day2_parseinput() 2 | input = joinpath(@__DIR__, "input.txt") 3 | map(eachline(input)) do cmd 4 | dir, units = split(cmd) |> x -> (x[1], parse(Int, x[2])) 5 | if dir == "forward" 6 | CartesianIndex(units, 0) 7 | elseif dir == "down" 8 | CartesianIndex(0, units) 9 | elseif dir == "up" 10 | CartesianIndex(0, -units) 11 | end 12 | end 13 | end 14 | 15 | day2_part1(input) = sum(input) |> x -> prod(x.I) 16 | 17 | function day2_part2(input) 18 | pos, aim = CartesianIndex(0, 0), 0 19 | for cmd in input 20 | aim += cmd[2] 21 | pos += CartesianIndex(cmd[1], aim * cmd[1]) 22 | end 23 | prod(pos.I) 24 | end 25 | 26 | @testset "day02" begin 27 | input = day2_parseinput() 28 | @test day2_part1(input) == 1693300 29 | @test day2_part2(input) == 1857958050 30 | end 31 | 32 | export day2_parseinput, day2_part1, day2_part2 33 | -------------------------------------------------------------------------------- /Advent of Code/2021/03/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day3_parseinput() 2 | input = joinpath(@__DIR__, "input.txt") 3 | mapreduce(collect, hcat, eachline(input)) |> permutedims 4 | end 5 | 6 | function day3_most_common(x) 7 | num_0s = count(==('0'), x) 8 | num_1s = count(==('1'), x) 9 | num_0s > num_1s ? '0' : '1' 10 | end 11 | 12 | function day3_least_common(x) 13 | num_0s = count(==('0'), x) 14 | num_1s = count(==('1'), x) 15 | num_0s <= num_1s ? '0' : '1' 16 | end 17 | 18 | rate_aux(f, input) = mapreduce(f, string, eachcol(input)) |> binary_string_to_decimal 19 | day3_gamma_rate(input) = rate_aux(day3_most_common, input) 20 | day3_epsilon_rate(input) = rate_aux(day3_least_common, input) 21 | 22 | function rating_aux(f, input) 23 | for j = 1:size(input, 2) 24 | colⱼ = input[:,j] 25 | input = input[colⱼ .== f(colⱼ), :] 26 | size(input, 1) == 1 && break 27 | end 28 | string(input...) |> binary_string_to_decimal 29 | end 30 | 31 | day3_oxygen_generator_rating(input) = rating_aux(day3_most_common, input) 32 | day3_CO2_scrubber_rating(input) = rating_aux(day3_least_common, input) 33 | 34 | function day3_part1(input) 35 | gamma_rate = day3_gamma_rate(input) 36 | epsilon_rate = day3_epsilon_rate(input) 37 | power_consumption = gamma_rate * epsilon_rate 38 | end 39 | 40 | function day3_part2(input) 41 | oxygen_generator_rating = day3_oxygen_generator_rating(input) 42 | CO2_scrubber_rating = day3_CO2_scrubber_rating(input) 43 | life_support_rating = oxygen_generator_rating * CO2_scrubber_rating 44 | end 45 | 46 | @testset "day03" begin 47 | input = day3_parseinput() 48 | @test day3_part1(input) == 4138664 49 | @test day3_part2(input) == 4273224 50 | end 51 | 52 | export day3_parseinput, day3_part1, day3_part2 53 | -------------------------------------------------------------------------------- /Advent of Code/2021/05/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day5_parseinput() 2 | input = read(joinpath(@__DIR__, "input.txt"), String) 3 | split(input, "\n", keepempty = false) .|> x -> split(x) |> 4 | x -> (parse.(Int, split(x[1], ",")) |> SVector{2,Int}, 5 | parse.(Int, split(x[3], ",")) |> SVector{2,Int}) 6 | end 7 | 8 | function day5_drawline!(diagram, p1, p2; keepdiagonals = false) 9 | !keepdiagonals && (p1[1] != p2[1] && p1[2] != p2[2]) && return 10 | 11 | dir = normalize(p2 - p1, Inf) .|> round .|> Int 12 | num_steps = norm(p2 - p1, Inf) |> Int 13 | 14 | foreach(0:num_steps) do steps 15 | x, y = p1 + steps * dir 16 | diagram[x, y] += 1 17 | end 18 | end 19 | 20 | day5_drawline!(diagram, (p1, p2); keepdiagonals = false) = day5_drawline!(diagram, p1, p2; keepdiagonals) 21 | 22 | function day5_solve(input; keepdiagonals = false) 23 | diagram = DefaultDict{Tuple{Int,Int},Int}(0) 24 | foreach(x -> day5_drawline!(diagram, x; keepdiagonals), input) 25 | count(>(1), values(diagram)) 26 | end 27 | 28 | day5_part1(input) = day5_solve(input; keepdiagonals = false) 29 | day5_part2(input) = day5_solve(input; keepdiagonals = true) 30 | 31 | @testset "day05" begin 32 | input = day5_parseinput() 33 | @test day5_part1(input) == 5632 34 | @test day5_part2(input) == 22213 35 | end 36 | 37 | export day5_parseinput, day5_part1, day5_part2 38 | -------------------------------------------------------------------------------- /Advent of Code/2021/06/input.txt: -------------------------------------------------------------------------------- 1 | 3,5,4,1,2,1,5,5,1,1,1,1,4,1,4,5,4,5,1,3,1,1,1,4,1,1,3,1,1,5,3,1,1,3,1,3,1,1,1,4,1,2,5,3,1,4,2,3,1,1,2,1,1,1,4,1,1,1,1,2,1,1,1,3,1,1,4,1,4,1,5,1,4,2,1,1,5,4,4,4,1,4,1,1,1,1,3,1,5,1,4,5,3,1,4,1,5,2,2,5,1,3,2,2,5,4,2,3,4,1,2,1,1,2,1,1,5,4,1,1,1,1,3,1,5,4,1,5,1,1,4,3,4,3,1,5,1,1,2,1,1,5,3,1,1,1,1,1,5,1,1,1,1,1,1,1,2,2,5,5,1,2,1,2,1,1,5,1,3,1,5,2,1,4,1,5,3,1,1,1,2,1,3,1,4,4,1,1,5,1,1,4,1,4,2,3,5,2,5,1,3,1,2,1,4,1,1,1,1,2,1,4,1,3,4,1,1,1,1,1,1,1,2,1,5,1,1,1,1,2,3,1,1,2,3,1,1,3,1,1,3,1,3,1,3,3,1,1,2,1,3,2,3,1,1,3,5,1,1,5,5,1,2,1,2,2,1,1,1,5,3,1,1,3,5,1,3,1,5,3,4,2,3,2,1,3,1,1,3,4,2,1,1,3,1,1,1,1,1,1 2 | -------------------------------------------------------------------------------- /Advent of Code/2021/06/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day6_parseinput() 2 | input = joinpath(@__DIR__, "input.txt") |> readline 3 | parse.(Int, split(input, ",")) 4 | end 5 | 6 | function day6_slow(input, days) 7 | state = fill(Int8(8), 1_000_000) 8 | num_fish = length(input) 9 | state[1:num_fish] = input 10 | for _ = 1:days 11 | state[1:num_fish] .-= 1 12 | inds = findall(<(0), state) 13 | num_fish += length(inds) 14 | state[inds] .= 6 15 | end 16 | num_fish 17 | end 18 | 19 | function day6_fast(input, days) 20 | state = @MVector [count(==(t), input) for t = 0:8] 21 | for _ = 1:days 22 | state[8] += state[1] 23 | state = circshift(state, -1) 24 | end 25 | sum(state) 26 | end 27 | 28 | day6_part1(input) = day6_fast(input, 80) 29 | day6_part2(input) = day6_fast(input, 256) 30 | 31 | @testset "day06" begin 32 | input = day6_parseinput() 33 | @test day6_part1(input) == 374927 34 | @test day6_part2(input) == 1687617803407 35 | end 36 | 37 | export day6_parseinput, day6_part1, day6_part2 38 | -------------------------------------------------------------------------------- /Advent of Code/2021/07/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day7_parseinput() 2 | input = joinpath(@__DIR__, "input.txt") |> readline 3 | parse.(Int, split(input, ",")) 4 | end 5 | 6 | function day7_part1(input) 7 | target = median(input) |> Int 8 | sum(x -> abs(x - target), input) 9 | end 10 | 11 | function day7_part2(input) 12 | target = mean(input) |> floor |> Int 13 | sum(x -> sum(1:abs(x - target)), input) 14 | end 15 | 16 | @testset "day07" begin 17 | input = day7_parseinput() 18 | @test day7_part1(input) == 333755 19 | @test day7_part2(input) == 94017638 20 | end 21 | 22 | export day7_parseinput, day7_part1, day7_part2 23 | -------------------------------------------------------------------------------- /Advent of Code/2021/11/input.txt: -------------------------------------------------------------------------------- 1 | 2566885432 2 | 3857414357 3 | 6761543247 4 | 5477332114 5 | 3731585385 6 | 1716783173 7 | 1277321612 8 | 3371176148 9 | 1162578285 10 | 6144726367 11 | -------------------------------------------------------------------------------- /Advent of Code/2021/11/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day11_parseinput() 2 | input = joinpath(@__DIR__, "input.txt") 3 | mapreduce(collect, hcat, eachline(input)) |> 4 | permutedims .|> x -> parse(Int, x) 5 | end 6 | 7 | function day11_neighbours(A, ci) 8 | steps = filter(!iszero, CartesianIndices(ntuple(_ -> -1:1, 2))) 9 | [ci + step for step in steps if checkbounds(Bool, A, ci + step)] 10 | end 11 | 12 | function day11(input) 13 | state = copy(input) 14 | total_flashes = 0 15 | 16 | result₁ = 0 17 | result₂ = 0 18 | 19 | flashed = Set(CartesianIndex{2}[]) 20 | 21 | for step = Iterators.countfrom(1) 22 | state .+= 1 23 | 24 | empty!(flashed) 25 | 26 | while true 27 | overpowered = findall(>(9), state) 28 | isempty(overpowered) && break 29 | 30 | filter!(∉(flashed), overpowered) 31 | union!(flashed, overpowered) 32 | state[overpowered] .= 0 33 | 34 | for ci ∈ overpowered 35 | neighbours = day11_neighbours(state, ci) 36 | filter!(∉(flashed), neighbours) 37 | state[neighbours] .+= 1 38 | end 39 | end 40 | 41 | total_flashes += length(flashed) 42 | 43 | (step == 100) && (result₁ = total_flashes) 44 | (length(flashed) == length(state)) && (result₂ = step) 45 | 46 | all(!iszero, (result₁, result₂)) && break 47 | end 48 | 49 | result₁, result₂ 50 | end 51 | 52 | @testset "day11" begin 53 | input = day11_parseinput() 54 | result₁, result₂ = day11(input) 55 | 56 | @test result₁ == 1647 57 | @test result₂ == 348 58 | end 59 | 60 | export day11_parseinput, day11 61 | -------------------------------------------------------------------------------- /Advent of Code/2021/12/input.txt: -------------------------------------------------------------------------------- 1 | fs-end 2 | he-DX 3 | fs-he 4 | start-DX 5 | pj-DX 6 | end-zg 7 | zg-sl 8 | zg-pj 9 | pj-he 10 | RW-he 11 | fs-DX 12 | pj-RW 13 | zg-RW 14 | start-pj 15 | he-WI 16 | zg-he 17 | pj-fs 18 | start-RW 19 | -------------------------------------------------------------------------------- /Advent of Code/2021/13/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day13_parseinput() 2 | input = read(joinpath(@__DIR__, "input.txt"), String) 3 | raw_points, raw_instructions = split(input, "\n\n") 4 | points = split.(split(raw_points), ",") .|> 5 | x -> parse.(Int, x) |> x -> CartesianIndex(x...) + CartesianIndex(1, 1) 6 | instructions = split(raw_instructions, "\n", keepempty = false) .|> 7 | x -> split(split(x)[3], "=") |> x -> (x[1] == "x" ? 1 : 2, parse(Int, x[2])) 8 | points, instructions 9 | end 10 | 11 | function day13_fold(points, dim, at) 12 | static_points = filter(x -> x[dim] ≤ at, points) 13 | moving_points = filter(x -> x[dim] > at, points) 14 | 15 | moving_points = map(moving_points) do x 16 | dim == 1 ? 17 | CartesianIndex(x[1] - 2(x[1] - 1 - at), x[2]) : 18 | CartesianIndex(x[1], x[2] - 2(x[2] - 1 - at)) 19 | end 20 | 21 | static_points ∪ moving_points 22 | end 23 | 24 | function day13_part1(points, instructions) 25 | dim, at = first(instructions) 26 | points = day13_fold(points, dim, at) 27 | return length(points) 28 | end 29 | 30 | function day13_part2(points, instructions) 31 | for (dim, at) in instructions 32 | points = day13_fold(points, dim, at) 33 | end 34 | 35 | # # Uncomment the lines below to display the result. 36 | # origami = fill(" ", maximum(points).I) 37 | # origami[points] .= "#" 38 | # origami = permutedims(origami) 39 | # foreach(x -> println(join(x)), eachrow(origami)) 40 | 41 | return length(points) 42 | end 43 | 44 | @testset "day13" begin 45 | points, instructions = day13_parseinput() 46 | @test day13_part1(points, instructions) == 666 47 | @test day13_part2(points, instructions) == 97 # CJHAZHKU 48 | end 49 | 50 | export day13_parseinput, day13_part1, day13_part2 51 | -------------------------------------------------------------------------------- /Advent of Code/2021/14/input.txt: -------------------------------------------------------------------------------- 1 | OOVSKSPKPPPNNFFBCNOV 2 | 3 | BC -> C 4 | PP -> O 5 | SK -> K 6 | KH -> N 7 | OK -> S 8 | PC -> O 9 | VP -> K 10 | CF -> K 11 | HC -> H 12 | FV -> V 13 | PB -> P 14 | NK -> H 15 | CK -> F 16 | FH -> H 17 | SV -> B 18 | NH -> C 19 | CP -> S 20 | HP -> O 21 | HS -> O 22 | BK -> B 23 | KC -> P 24 | VV -> B 25 | OF -> O 26 | KP -> V 27 | FO -> V 28 | FK -> V 29 | VH -> K 30 | KB -> P 31 | KF -> H 32 | SH -> S 33 | HF -> O 34 | BB -> F 35 | FC -> O 36 | SO -> S 37 | BS -> O 38 | HH -> C 39 | BO -> S 40 | CO -> F 41 | VC -> V 42 | KS -> N 43 | OC -> N 44 | FP -> P 45 | HN -> B 46 | HV -> V 47 | HO -> P 48 | KO -> C 49 | SF -> H 50 | NO -> N 51 | PS -> C 52 | BP -> K 53 | SC -> C 54 | NP -> C 55 | CH -> V 56 | KV -> B 57 | HK -> V 58 | OP -> V 59 | SP -> V 60 | NC -> V 61 | FF -> B 62 | CC -> V 63 | CS -> F 64 | SB -> C 65 | OS -> C 66 | FN -> O 67 | CV -> P 68 | OH -> H 69 | OO -> P 70 | PO -> F 71 | NS -> H 72 | VB -> K 73 | OV -> K 74 | PH -> H 75 | BH -> V 76 | SS -> B 77 | PK -> F 78 | VK -> O 79 | BN -> V 80 | VF -> O 81 | PF -> H 82 | VS -> K 83 | ON -> V 84 | BF -> F 85 | CN -> F 86 | VO -> B 87 | FS -> K 88 | OB -> B 89 | PN -> H 90 | NF -> O 91 | VN -> P 92 | BV -> S 93 | NV -> V 94 | FB -> V 95 | NB -> P 96 | CB -> B 97 | KK -> S 98 | NN -> F 99 | SN -> B 100 | HB -> P 101 | PV -> S 102 | KN -> S 103 | -------------------------------------------------------------------------------- /Advent of Code/2021/15/input.txt: -------------------------------------------------------------------------------- 1 | 1163751742 2 | 1381373672 3 | 2136511328 4 | 3694931569 5 | 7463417111 6 | 1319128137 7 | 1359912421 8 | 3125421639 9 | 1293138521 10 | 2311944581 11 | -------------------------------------------------------------------------------- /Advent of Code/2021/Project.toml: -------------------------------------------------------------------------------- 1 | name = "AdventOfCode2021" 2 | uuid = "4934216c-a8f9-4242-b09c-c71bf2ae33f3" 3 | authors = ["Henrique Ferrolho "] 4 | version = "0.1.0" 5 | 6 | [deps] 7 | DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" 8 | DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" 9 | InlineTest = "bd334432-b1e7-49c7-a2dc-dd9149e4ebd6" 10 | IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e" 11 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 12 | StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" 13 | Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 14 | 15 | [compat] 16 | InlineTest = "0.2" 17 | IterTools = "1.4" 18 | ReTest = "0.3" 19 | StaticArrays = "1.2" 20 | julia = "1.6" 21 | 22 | [extras] 23 | ReTest = "e0db7c4e-2690-44b9-bad6-7687da720f89" 24 | 25 | [targets] 26 | test = ["ReTest"] 27 | -------------------------------------------------------------------------------- /Advent of Code/2021/src/AdventOfCode2021.jl: -------------------------------------------------------------------------------- 1 | module AdventOfCode2021 2 | 3 | using DataStructures 4 | using DelimitedFiles 5 | using InlineTest 6 | using IterTools 7 | using LinearAlgebra 8 | using StaticArrays 9 | using Statistics 10 | 11 | greet() = println("Hello, Advent of Code 2021!") 12 | 13 | binary_string_to_decimal(x) = parse(Int, x, base=2) 14 | 15 | include("../01/puzzle.jl") 16 | include("../02/puzzle.jl") 17 | include("../03/puzzle.jl") 18 | include("../04/puzzle.jl") 19 | include("../05/puzzle.jl") 20 | include("../06/puzzle.jl") 21 | include("../07/puzzle.jl") 22 | include("../08/puzzle.jl") 23 | include("../09/puzzle.jl") 24 | include("../10/puzzle.jl") 25 | include("../11/puzzle.jl") 26 | include("../12/puzzle.jl") 27 | include("../13/puzzle.jl") 28 | include("../14/puzzle.jl") 29 | include("../15/puzzle.jl") 30 | 31 | end # module 32 | -------------------------------------------------------------------------------- /Advent of Code/2022/01/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day1_parseinput() 2 | filename = joinpath(@__DIR__, "input.txt") 3 | chunks = split(read(filename, String), "\n\n") 4 | parsed_chunks = map(chunks) do chunk 5 | parse.(Int, split(chunk)) 6 | end 7 | return parsed_chunks 8 | end 9 | 10 | day1_part1(input) = sum.(input) |> maximum 11 | day1_part2(input) = sum.(input) |> x -> partialsort!(x, 1:3, rev=true) |> sum 12 | 13 | @testset "day01" begin 14 | day1_input = day1_parseinput() 15 | @test day1_part1(day1_input) == 71506 16 | @test day1_part2(day1_input) == 209603 17 | end 18 | 19 | export day1_parseinput, day1_part1, day1_part2 20 | -------------------------------------------------------------------------------- /Advent of Code/2022/02/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day2_parseinput(filename=joinpath(@__DIR__, "input.txt")) 2 | map(eachline(filename)) do x 3 | a = x[1] - 'A' + 1 4 | b = x[3] - 'X' + 1 5 | (a, b) 6 | end 7 | end 8 | 9 | function day2_part1(input) 10 | sum(input) do (a, b) 11 | # draw, win, lose 12 | if b == a 13 | b + 3 14 | elseif mod1(b - a, 3) == 1 15 | b + 6 16 | else 17 | b 18 | end 19 | end 20 | end 21 | 22 | function day2_part2(input) 23 | sum(input) do (a, c) 24 | # lose, draw, win 25 | if c == 1 26 | mod1(a - 1, 3) 27 | elseif c == 2 28 | a + 3 29 | elseif c == 3 30 | mod1(a + 1, 3) + 6 31 | end 32 | end 33 | end 34 | 35 | @testset "day02" begin 36 | input = day2_parseinput() 37 | @test day2_part1(input) == 12586 38 | @test day2_part2(input) == 13193 39 | end 40 | 41 | export day2_parseinput, day2_part1, day2_part2 42 | -------------------------------------------------------------------------------- /Advent of Code/2022/03/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day3_parseinput(filename=joinpath(@__DIR__, "input.txt")) 2 | readlines(filename) 3 | end 4 | 5 | function day3_char_to_priority(c) 6 | c - (islowercase(c) ? 'a' : 'A' - 26) + 1 7 | end 8 | 9 | function day3_part1(input) 10 | sum(input) do x 11 | N = length(x) 12 | str₁, str₂ = x[1:N÷2], x[N÷2+1:N] 13 | s₁, s₂ = Set(str₁), Set(str₂) 14 | only(s₁ ∩ s₂) |> day3_char_to_priority 15 | end 16 | end 17 | 18 | function day3_part2(input) 19 | sum(Iterators.partition(input, 3)) do x 20 | only(reduce(∩, x)) |> day3_char_to_priority 21 | end 22 | end 23 | 24 | @testset "day03" begin 25 | input = day3_parseinput() 26 | @test day3_part1(input) == 7878 27 | @test day3_part2(input) == 2760 28 | end 29 | 30 | export day3_parseinput, day3_part1, day3_part2 31 | -------------------------------------------------------------------------------- /Advent of Code/2022/04/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day4_parseinput(filename=joinpath(@__DIR__, "input.txt")) 2 | map(eachline(filename)) do line 3 | tokens = split(line, (',', '-')) 4 | aₛ, aₜ, bₛ, bₜ = parse.(Int, tokens) 5 | aₛ:aₜ, bₛ:bₜ 6 | end 7 | end 8 | 9 | function day4_part1(input) 10 | count(input) do (a, b) 11 | a ⊆ b || a ⊇ b 12 | end 13 | end 14 | 15 | function day4_part2(input) 16 | count(input) do (a, b) 17 | a ∩ b |> !isempty 18 | end 19 | end 20 | 21 | @testset "day04" begin 22 | input = day4_parseinput() 23 | @test day4_part1(input) == 605 24 | @test day4_part2(input) == 914 25 | end 26 | 27 | export day4_parseinput, day4_part1, day4_part2 28 | -------------------------------------------------------------------------------- /Advent of Code/2022/05/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day5_parseinput(filename=joinpath(@__DIR__, "input.txt")) 2 | state = Dict( 3 | 1 => ['F', 'G', 'V', 'R', 'J', 'L', 'D'], 4 | 2 => ['S', 'J', 'H', 'V', 'B', 'M', 'P', 'T'], 5 | 3 => ['C', 'P', 'G', 'D', 'F', 'M', 'H', 'V'], 6 | 4 => ['Q', 'G', 'N', 'P', 'D', 'M'], 7 | 5 => ['F', 'N', 'H', 'L', 'J'], 8 | 6 => ['Z', 'T', 'G', 'D', 'Q', 'V', 'F', 'N'], 9 | 7 => ['L', 'B', 'D', 'F'], 10 | 8 => ['N', 'D', 'V', 'S', 'B', 'J', 'M'], 11 | 9 => ['D', 'L', 'G'], 12 | ) 13 | 14 | steps = map(eachline(filename)) do line 15 | split(line) |> x -> parse.(Int, x[[2, 4, 6]]) 16 | end 17 | 18 | state, steps 19 | end 20 | 21 | function day5_aux(state, steps, fn) 22 | for (num, src, dst) in steps 23 | crates = state[src][1:num] |> fn 24 | pushfirst!(state[dst], crates...) 25 | splice!(state[src], 1:num) 26 | end 27 | mapreduce(x -> state[x][begin], string, 1:length(state)) 28 | end 29 | 30 | day5_part1(args...) = day5_aux(args..., reverse!) 31 | day5_part2(args...) = day5_aux(args..., identity) 32 | 33 | @testset "day05" begin 34 | state, steps = day5_parseinput() 35 | @test day5_part1(deepcopy(state), steps) == "QMBMJDFTD" 36 | @test day5_part2(deepcopy(state), steps) == "NBTVTJNFJ" 37 | end 38 | 39 | export day5_parseinput, day5_part1, day5_part2 40 | -------------------------------------------------------------------------------- /Advent of Code/2022/06/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day6_parseinput(filename=joinpath(@__DIR__, "input.txt")) 2 | readline(filename) 3 | end 4 | 5 | function day6_aux(input, N) 6 | findfirst( 7 | i -> allunique(input[i-N+1:i]), 8 | N:lastindex(input) 9 | ) + N - 1 10 | end 11 | 12 | day6_part1(input) = day6_aux(input, 4) 13 | day6_part2(input) = day6_aux(input, 14) 14 | 15 | @testset "day06" begin 16 | input = day6_parseinput() 17 | @test day6_part1(input) == 1175 18 | @test day6_part2(input) == 3217 19 | end 20 | 21 | export day6_parseinput, day6_part1, day6_part2 22 | -------------------------------------------------------------------------------- /Advent of Code/2022/07/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day7_parseinput(filename=joinpath(@__DIR__, "input.txt")) 2 | input = readlines(filename) 3 | 4 | pwd = "/" 5 | 6 | folders = Dict{String,Int}(pwd => 0) 7 | files = Dict{String,Int}() 8 | 9 | for line in input 10 | tokens = split(line) 11 | if tokens[1] == "\$" 12 | if tokens[2] == "cd" 13 | if tokens[3] == ".." 14 | i = findprev(==('/'), pwd, length(pwd) - 1) 15 | pwd = pwd[1:i] 16 | elseif tokens[3] == "/" 17 | pwd = "/" 18 | else 19 | pwd = string(pwd, tokens[3], "/") 20 | folders[pwd] = 0 21 | end 22 | end 23 | else 24 | size, name = tryparse(Int, tokens[1]), tokens[2] 25 | if !isnothing(size) 26 | files[string(pwd, name)] = size 27 | end 28 | end 29 | end 30 | 31 | # calculate the size of each folder 32 | for folder in keys(folders) 33 | folders[folder] = sum(files) do (file, size) 34 | occursin(folder, file) ? size : 0 35 | end 36 | end 37 | 38 | folders 39 | end 40 | 41 | function day7_part1(folders) 42 | sum(v for (k, v) in folders if v ≤ 100000) 43 | end 44 | 45 | function day7_part2(folders) 46 | required = folders["/"] - 40000000 47 | minimum(v for (k, v) in folders if v ≥ required) 48 | end 49 | 50 | @testset "day07" begin 51 | input = day7_parseinput() 52 | @test day7_part1(input) == 919137 53 | @test day7_part2(input) == 2877389 54 | end 55 | 56 | export day7_parseinput, day7_part1, day7_part2 57 | -------------------------------------------------------------------------------- /Advent of Code/2022/10/input.txt: -------------------------------------------------------------------------------- 1 | addx 1 2 | noop 3 | noop 4 | addx 4 5 | addx 5 6 | addx -2 7 | addx 19 8 | addx -12 9 | addx 3 10 | addx -2 11 | addx 4 12 | noop 13 | noop 14 | noop 15 | addx 3 16 | addx -8 17 | addx 15 18 | addx 1 19 | noop 20 | noop 21 | addx 6 22 | addx -1 23 | noop 24 | addx -38 25 | noop 26 | addx 10 27 | addx -5 28 | noop 29 | addx 3 30 | addx 2 31 | addx 7 32 | noop 33 | noop 34 | addx 3 35 | noop 36 | addx 2 37 | addx 3 38 | addx -2 39 | addx 2 40 | addx 7 41 | noop 42 | noop 43 | addx 9 44 | noop 45 | addx -12 46 | noop 47 | addx 11 48 | addx -38 49 | noop 50 | noop 51 | noop 52 | addx 5 53 | addx 5 54 | noop 55 | noop 56 | noop 57 | addx 3 58 | addx -12 59 | addx 14 60 | noop 61 | addx 1 62 | addx 3 63 | addx 1 64 | addx 5 65 | addx 4 66 | addx 1 67 | noop 68 | noop 69 | noop 70 | noop 71 | noop 72 | addx -9 73 | addx 17 74 | addx -39 75 | addx 38 76 | addx -8 77 | addx -26 78 | addx 3 79 | addx 4 80 | addx 16 81 | noop 82 | addx -11 83 | addx 3 84 | noop 85 | addx 2 86 | addx 3 87 | addx -2 88 | addx 2 89 | noop 90 | addx 13 91 | addx -8 92 | noop 93 | addx 7 94 | addx -5 95 | addx 8 96 | addx -40 97 | addx 16 98 | addx -9 99 | noop 100 | addx -7 101 | addx 8 102 | addx 2 103 | addx 7 104 | noop 105 | noop 106 | addx -15 107 | addx 16 108 | addx 2 109 | addx 5 110 | addx 2 111 | addx -20 112 | addx 12 113 | addx 11 114 | addx 8 115 | addx -1 116 | addx 3 117 | noop 118 | addx -39 119 | addx 2 120 | noop 121 | addx 5 122 | noop 123 | noop 124 | noop 125 | addx 4 126 | addx 1 127 | noop 128 | noop 129 | addx 2 130 | addx 5 131 | addx 2 132 | addx 1 133 | addx 4 134 | addx -1 135 | addx 2 136 | noop 137 | addx 2 138 | noop 139 | addx 8 140 | noop 141 | noop 142 | noop 143 | addx -10 144 | noop 145 | noop 146 | -------------------------------------------------------------------------------- /Advent of Code/2022/11/input.txt: -------------------------------------------------------------------------------- 1 | Monkey 0: 2 | Starting items: 54, 61, 97, 63, 74 3 | Operation: x -> x * 7 4 | Test: divisible by 17 5 | If true: throw to monkey 5 6 | If false: throw to monkey 3 7 | 8 | Monkey 1: 9 | Starting items: 61, 70, 97, 64, 99, 83, 52, 87 10 | Operation: x -> x + 8 11 | Test: divisible by 2 12 | If true: throw to monkey 7 13 | If false: throw to monkey 6 14 | 15 | Monkey 2: 16 | Starting items: 60, 67, 80, 65 17 | Operation: x -> x * 13 18 | Test: divisible by 5 19 | If true: throw to monkey 1 20 | If false: throw to monkey 6 21 | 22 | Monkey 3: 23 | Starting items: 61, 70, 76, 69, 82, 56 24 | Operation: x -> x + 7 25 | Test: divisible by 3 26 | If true: throw to monkey 5 27 | If false: throw to monkey 2 28 | 29 | Monkey 4: 30 | Starting items: 79, 98 31 | Operation: x -> x + 2 32 | Test: divisible by 7 33 | If true: throw to monkey 0 34 | If false: throw to monkey 3 35 | 36 | Monkey 5: 37 | Starting items: 72, 79, 55 38 | Operation: x -> x + 1 39 | Test: divisible by 13 40 | If true: throw to monkey 2 41 | If false: throw to monkey 1 42 | 43 | Monkey 6: 44 | Starting items: 63 45 | Operation: x -> x + 4 46 | Test: divisible by 19 47 | If true: throw to monkey 7 48 | If false: throw to monkey 4 49 | 50 | Monkey 7: 51 | Starting items: 72, 51, 93, 63, 80, 86, 81 52 | Operation: x -> x * x 53 | Test: divisible by 11 54 | If true: throw to monkey 0 55 | If false: throw to monkey 4 56 | -------------------------------------------------------------------------------- /Advent of Code/2022/13/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day13_parseinput(filename=joinpath(@__DIR__, "input.txt")) 2 | chunks = split(read(filename, String), "\n\n") 3 | f(x) = split(x) .|> eval ∘ Meta.parse 4 | map(f, chunks) 5 | end 6 | 7 | day13_compare(a::Int, b::Int) = sign(a - b) 8 | day13_compare(a::Int, b::Vector) = day13_compare([a], b) 9 | day13_compare(a::Vector, b::Int) = day13_compare(a, [b]) 10 | 11 | function day13_compare(a::Vector, b::Vector) 12 | for (l, r) in zip(a, b) 13 | result = day13_compare(l, r) 14 | result != 0 && return result 15 | end 16 | day13_compare(length(a), length(b)) 17 | end 18 | 19 | day13_isless(x, y) = day13_compare(x, y) < 0 20 | 21 | function day13_part1(input) 22 | sum(day13_isless(pair...) ? i : 0 23 | for (i, pair) in enumerate(input)) 24 | end 25 | 26 | function day13_part2(input) 27 | divider_packets = [[[2]], [[6]]] 28 | packets = vcat(input..., divider_packets) 29 | sort!(packets, lt=day13_isless) 30 | prod(findfirst(==(p), packets) 31 | for p in divider_packets) 32 | end 33 | 34 | @testset "day13" begin 35 | input = day13_parseinput() 36 | @test day13_part1(input) == 5366 37 | @test day13_part2(input) == 23391 38 | end 39 | 40 | export day13_parseinput, day13_part1, day13_part2 41 | -------------------------------------------------------------------------------- /Advent of Code/2022/25/puzzle.jl: -------------------------------------------------------------------------------- 1 | function day25_parseinput(filename=joinpath(@__DIR__, "input.txt")) 2 | readlines(filename) 3 | end 4 | 5 | function day25_to_snafu(decimal::Int) 6 | decimal == 0 && return "" 7 | a, b = fldmod(decimal, 5) 8 | b == 0 && return day25_to_snafu(a) * '0' 9 | b == 1 && return day25_to_snafu(a) * '1' 10 | b == 2 && return day25_to_snafu(a) * '2' 11 | b == 3 && return day25_to_snafu(a + 1) * '=' 12 | b == 4 && return day25_to_snafu(a + 1) * '-' 13 | end 14 | 15 | function day25_to_decimal(snafu::String) 16 | function snafu_digit_to_decimal(snafu_digit::Char) 17 | snafu_digit == '-' && return -1 18 | snafu_digit == '=' && return -2 19 | snafu_digit == '0' && return 0 20 | snafu_digit == '1' && return 1 21 | snafu_digit == '2' && return 2 22 | end 23 | 24 | sum(snafu_digit_to_decimal(snafu_digit) * 5^i 25 | for (snafu_digit, i) in zip(snafu, length(snafu)-1:-1:0)) 26 | end 27 | 28 | day25(input) = day25_to_decimal.(input) |> sum |> day25_to_snafu 29 | 30 | @testset "day25" begin 31 | input = day25_parseinput() 32 | @test day25(input) == "2=0--0---11--01=-100" 33 | end 34 | 35 | export day25_parseinput, day25 36 | -------------------------------------------------------------------------------- /Advent of Code/2022/Project.toml: -------------------------------------------------------------------------------- 1 | name = "AdventOfCode2022" 2 | uuid = "d500e8ff-d81f-4026-9325-1d611c1de56a" 3 | authors = ["Henrique Ferrolho "] 4 | version = "0.1.0" 5 | 6 | [deps] 7 | DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" 8 | DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" 9 | InlineTest = "bd334432-b1e7-49c7-a2dc-dd9149e4ebd6" 10 | IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e" 11 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 12 | ReTest = "e0db7c4e-2690-44b9-bad6-7687da720f89" 13 | -------------------------------------------------------------------------------- /Advent of Code/2022/README.md: -------------------------------------------------------------------------------- 1 | Start the Julia REPL from within this folder. 2 | 3 | To run all the tests: 4 | ```julia 5 | using AdventOfCode2022, ReTest 6 | AdventOfCode2022.runtests() 7 | ``` 8 | 9 | To run a specific day: 10 | ```julia 11 | input = day1_parseinput() 12 | day1_part1(input) 13 | ``` 14 | 15 | To benchmark a specific day: 16 | ```julia 17 | using BenchmarkTools 18 | @benchmark day1_part1(input) setup=(input = day1_parseinput()) 19 | ``` 20 | -------------------------------------------------------------------------------- /Advent of Code/2022/src/AdventOfCode2022.jl: -------------------------------------------------------------------------------- 1 | module AdventOfCode2022 2 | 3 | using DataStructures 4 | using DelimitedFiles 5 | using InlineTest 6 | using IterTools 7 | using LinearAlgebra 8 | 9 | import LinearAlgebra: CartesianIndex as CI 10 | import LinearAlgebra: CartesianIndices as CIs 11 | 12 | greet() = print("Hello, Advent of Code 2022!") 13 | 14 | include("../01/puzzle.jl") 15 | include("../02/puzzle.jl") 16 | include("../03/puzzle.jl") 17 | include("../04/puzzle.jl") 18 | include("../05/puzzle.jl") 19 | include("../06/puzzle.jl") 20 | include("../07/puzzle.jl") 21 | include("../08/puzzle.jl") 22 | include("../09/puzzle.jl") 23 | include("../10/puzzle.jl") 24 | include("../11/puzzle.jl") 25 | include("../12/puzzle.jl") 26 | include("../13/puzzle.jl") 27 | # include("../14/puzzle.jl") 28 | # include("../15/puzzle.jl") 29 | # include("../16/puzzle.jl") 30 | # include("../17/puzzle.jl") 31 | # include("../18/puzzle.jl") 32 | # include("../19/puzzle.jl") 33 | include("../20/puzzle.jl") 34 | include("../21/puzzle.jl") 35 | include("../22/puzzle.jl") 36 | include("../23/puzzle.jl") 37 | include("../24/puzzle.jl") 38 | include("../25/puzzle.jl") 39 | 40 | end # module AdventOfCode2022 41 | -------------------------------------------------------------------------------- /Advent of Code/README.md: -------------------------------------------------------------------------------- 1 | # Advent of Code 2 | 3 | My solutions to [Advent of Code](https://adventofcode.com/) problems. :santa: :christmas_tree: :gift: 4 | -------------------------------------------------------------------------------- /Leetcode/1. Two Sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class Solution 6 | { 7 | public: 8 | vector twoSum(vector &nums, int target) 9 | { 10 | for (int i = 0; i < size(nums) - 1; i++) 11 | { 12 | for (int j = i + 1; j < size(nums); j++) 13 | { 14 | if (nums[i] + nums[j] == target) 15 | { 16 | return {i, j}; 17 | } 18 | } 19 | } 20 | return {0, 0}; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Leetcode/100. Same Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def traverse(self, n1, n2) -> bool: 9 | if n1 == None and n2 == None: 10 | return True 11 | elif n1 == None or n2 == None: 12 | return False 13 | elif n1.val != n2.val: 14 | return False 15 | else: 16 | return self.traverse(n1.left, n2.left) and self.traverse(n1.right, n2.right) 17 | 18 | def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: 19 | return self.traverse(p, q) 20 | -------------------------------------------------------------------------------- /Leetcode/108. Convert Sorted Array to Binary Search Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: 9 | if len(nums) == 0: 10 | return None 11 | 12 | middle_idx = len(nums) // 2 13 | return TreeNode( 14 | nums[middle_idx], 15 | self.sortedArrayToBST(nums[:middle_idx]), 16 | self.sortedArrayToBST(nums[middle_idx+1:]), 17 | ) 18 | -------------------------------------------------------------------------------- /Leetcode/154. Find Minimum in Rotated Sorted Array II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findMin(self, nums: List[int]) -> int: 3 | return min(nums) 4 | -------------------------------------------------------------------------------- /Leetcode/2. Add Two Numbers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | // Definition for singly-linked list. 6 | struct ListNode 7 | { 8 | int val; 9 | ListNode *next; 10 | ListNode() : val(0), next(nullptr) {} 11 | ListNode(int x) : val(x), next(nullptr) {} 12 | ListNode(int x, ListNode *next) : val(x), next(next) {} 13 | }; 14 | 15 | class Solution 16 | { 17 | public: 18 | ListNode *addTwoNumbers(ListNode *l1, ListNode *l2, int carry = 0) 19 | { 20 | if (!l1 && !l2) 21 | { 22 | return carry == 0 ? nullptr : new ListNode(carry); 23 | } 24 | else if (!l1) 25 | { 26 | return carry == 0 ? l2 : addTwoNumbers(new ListNode(carry), l2); 27 | } 28 | else if (!l2) 29 | { 30 | return carry == 0 ? l1 : addTwoNumbers(new ListNode(carry), l1); 31 | } 32 | else 33 | { 34 | div_t dv = div(l1->val + l2->val + carry, 10); 35 | ListNode *next = addTwoNumbers(l1->next, l2->next, carry = dv.quot); 36 | return new ListNode(dv.rem, next); 37 | } 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /Leetcode/217. Contains Duplicate.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def containsDuplicate(self, nums: List[int]) -> bool: 3 | return len(nums) != len(set(nums)) 4 | -------------------------------------------------------------------------------- /Leetcode/228. Summary Ranges.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def ttos(self, t) -> str: 3 | return f"{t[0]}->{t[1]}" if t[0] != t[1] else f"{t[0]}" 4 | 5 | def summaryRanges(self, nums: List[int]) -> List[str]: 6 | ranges = [] 7 | i = 0 8 | while i < len(nums): 9 | j = i 10 | while j + 1 < len(nums) and nums[j + 1] == nums[j] + 1: 11 | j += 1 12 | ranges.append((nums[i], nums[j])) 13 | i = j + 1 14 | return map(self.ttos, ranges) 15 | -------------------------------------------------------------------------------- /Leetcode/242. Valid Anagram.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isAnagram(self, s: str, t: str) -> bool: 3 | a = {c: s.count(c) for c in set(s)} 4 | b = {c: t.count(c) for c in set(t)} 5 | return a == b 6 | -------------------------------------------------------------------------------- /Leetcode/3. Longest Substring Without Repeating Characters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class Solution 7 | { 8 | public: 9 | int lengthOfLongestSubstring(string s) 10 | { 11 | unordered_set myset; 12 | 13 | int max_so_far = 0; 14 | int start_pos = 0; 15 | 16 | for (size_t i = 0; i < s.size(); ++i) 17 | { 18 | if (myset.count(s[i])) // char is already in set 19 | { 20 | // find previous position of repeated char 21 | int pos = s.find(s[i], start_pos); 22 | 23 | // remove all chars from set until that point 24 | for (size_t j = start_pos; j < pos; j++) 25 | { 26 | myset.erase(s[j]); 27 | } 28 | 29 | // update start position of current candidate 30 | start_pos = pos + 1; 31 | } 32 | 33 | myset.insert(s[i]); 34 | 35 | // save max size given the current substring 36 | max_so_far = max(max_so_far, (int)myset.size()); 37 | } 38 | 39 | return max_so_far; 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /Leetcode/4. Median of Two Sorted Arrays.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float: 3 | M, N = len(nums1), len(nums2) 4 | total = M + N 5 | is_even = total % 2 == 0 6 | 7 | # number of items to be consumed 8 | n = total // 2 9 | if is_even: 10 | n -= 1 11 | 12 | idx1 = 0 13 | idx2 = 0 14 | 15 | while n > 0: 16 | # choose which array to consume from 17 | if idx1 >= M: 18 | idx2 += 1 19 | elif idx2 >= N or nums1[idx1] < nums2[idx2]: 20 | idx1 += 1 21 | else: 22 | idx2 += 1 23 | 24 | n -= 1 # decrease number of items to be consumed 25 | 26 | arr = [] 27 | n = 2 if is_even else 1 28 | for i in range(n): 29 | if idx1 >= M: 30 | arr.append(nums2[idx2]) 31 | idx2 += 1 32 | elif idx2 >= N or nums1[idx1] < nums2[idx2]: 33 | arr.append(nums1[idx1]) 34 | idx1 += 1 35 | else: 36 | arr.append(nums2[idx2]) 37 | idx2 += 1 38 | 39 | return sum(arr) / n 40 | -------------------------------------------------------------------------------- /Leetcode/53. Maximum Subarray.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxSubArray(self, nums: List[int]) -> int: 3 | ans = -inf 4 | total = 0 5 | for num in nums: 6 | total = max(num, total + num) 7 | ans = max(ans, total) 8 | return ans 9 | -------------------------------------------------------------------------------- /Leetcode/6. Zigzag Conversion.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class Solution: 5 | def convert(self, s: str, numRows: int) -> str: 6 | if numRows == 1: 7 | return s 8 | 9 | ZIG = np.array([1, 0]) 10 | ZAG = np.array([-1, 1]) 11 | 12 | charar = np.full((numRows, 1000), " ", dtype=str) 13 | 14 | pos = np.array([0, 0]) 15 | vel = ZIG 16 | 17 | for c in s: 18 | charar[tuple(pos)] = c 19 | if np.array_equal(vel, ZIG) and pos[0] + 1 == numRows or \ 20 | np.array_equal(vel, ZAG) and pos[0] == 0: 21 | vel = ZIG if np.array_equal(vel, ZAG) else ZAG 22 | pos += vel 23 | 24 | print(charar) 25 | 26 | result = "".join(str(c) for row in charar for c in row if c != " ") 27 | 28 | return result 29 | -------------------------------------------------------------------------------- /Leetcode/99. Recover Binary Search Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | a = None 9 | b = None 10 | prev = None 11 | 12 | def traverse(self, node): 13 | if node == None: 14 | return 15 | 16 | self.traverse(node.left) 17 | 18 | if self.prev != None and self.prev.val >= node.val: 19 | if self.a == None: 20 | self.a = self.prev 21 | if self.a != None: 22 | self.b = node 23 | self.prev = node 24 | 25 | self.traverse(node.right) 26 | 27 | def recoverTree(self, root: Optional[TreeNode]) -> None: 28 | self.traverse(root) 29 | self.a.val, self.b.val = self.b.val, self.a.val 30 | -------------------------------------------------------------------------------- /Project Genius/Project.toml: -------------------------------------------------------------------------------- 1 | [deps] 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Coding Challenges 2 | 3 | My very own solutions to various online coding challenges 4 | --------------------------------------------------------------------------------