From e62a0067e7b71ebfa91639a9eb0ff7dca123b344 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Mon, 30 Nov 2020 22:16:06 -0800 Subject: [PATCH] Add the first few solutions. --- day1.hs | 15 +++++++++++++++ day2.cr | 27 +++++++++++++++++++++++++++ day3.cr | 43 +++++++++++++++++++++++++++++++++++++++++++ day4.cr | 29 +++++++++++++++++++++++++++++ day5.cr | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ day6.cr | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 212 insertions(+) create mode 100644 day1.hs create mode 100644 day2.cr create mode 100644 day3.cr create mode 100644 day4.cr create mode 100644 day5.cr create mode 100644 day6.cr diff --git a/day1.hs b/day1.hs new file mode 100644 index 0000000..0169ea3 --- /dev/null +++ b/day1.hs @@ -0,0 +1,15 @@ +cost :: Int -> Int +cost x = (x `div` 3) - 2 + +fuel :: Int -> [Int] +fuel x + | cost x <= 0 = [] + | otherwise = cost x : fuel (cost x) + +totalCost :: Int -> Int +totalCost = sum . fuel + +main :: IO () +main = do + ls <- map read <$> lines <$> readFile "day1.txt" + print $ sum $ map totalCost ls diff --git a/day2.cr b/day2.cr new file mode 100644 index 0000000..5a5515a --- /dev/null +++ b/day2.cr @@ -0,0 +1,27 @@ +lines = File.read("day2.txt").lines.map(&.split(",").map(&.to_i32)).flatten +def run(lines, noun, verb) + lines[1] = noun + lines[2] = verb + pos = 0 + loop do + case lines[pos] + when 1 + lines[lines[pos+3]] = lines[lines[pos+1]] + lines[lines[pos+2]] + pos += 4 + when 2 + lines[lines[pos+3]] = lines[lines[pos+1]] * lines[lines[pos+2]] + pos += 4 + when 99 + break + end + end + lines[0] +end +100.times do |noun| + 100.times do |verb| + if run(lines.dup, noun, verb) == 19690720 + puts 100*noun + verb + break + end + end +end diff --git a/day3.cr b/day3.cr new file mode 100644 index 0000000..1f0b8aa --- /dev/null +++ b/day3.cr @@ -0,0 +1,43 @@ +def parse(s) + s.split(",").map { |ss| { ss[0], ss[1..].to_i32 } } +end + +def run_line(l) + poses = Set({Int32,Int32}).new + step_map = {} of {Int32,Int32} => Int32 + x, y, steps = 0, 0, 0 + l.each do |cmd| + dir, len = cmd + dx, dy = 0, 0 + case dir + when 'U' + dy = 1 + when 'D' + dy = -1 + when 'L' + dx = -1 + when 'R' + dx = 1 + end + len.times do |i| + x += dx + y += dy + steps += 1 + poses << {x,y} + step_map[{x,y}] ||= steps + end + end + return {poses, step_map} +end + +lines = File.read("day3.txt").lines.map(&.chomp) +# wire1 = parse("R8,U5,L5,D3") +# wire2 = parse("U7,R6,D4,L4") +# puts run_line(wire1) +# puts run_line(wire2) +wire1 = parse(lines[0]) +wire2 = parse(lines[1]) +poses1, steps1 = run_line(wire1) +poses2, steps2 = run_line(wire2) +puts (poses1 & poses2).min_of { |p| p[0] + p[1] } +puts (poses1 & poses2).min_of { |p| steps1[p] + steps2[p] } diff --git a/day4.cr b/day4.cr new file mode 100644 index 0000000..09b54ff --- /dev/null +++ b/day4.cr @@ -0,0 +1,29 @@ +input = File.read("day4.txt").chomp.split("-").map(&.to_i32) +total = 0 +(input[1] - input[0]).times do |i| + invalid = false + i = (input[0] + i).to_s + i.chars.each_cons_pair do |c1,c2| + invalid = c2 < c1 + break if invalid + end + next if invalid + + # next unless i =~ /.*(.)\1.*/ + past_char = nil + past_count = 0 + pasts = [] of Int32 + i.each_char do |c| + if c == past_char + past_count += 1 + else + pasts << past_count + past_count = 0 + end + past_char = c + end + pasts << past_count + + total += 1 if pasts.any? &.==(1) +end +puts total diff --git a/day5.cr b/day5.cr new file mode 100644 index 0000000..7ec0c43 --- /dev/null +++ b/day5.cr @@ -0,0 +1,49 @@ +lines = File.read("day5.txt").chomp.split(",").map(&.to_i32) +def run(lines, input) + output = [] of Int32 + pos = 0 + get = ->(x : Char, p : Int32) { + x == '0' ? lines[lines[pos+p]] : lines[pos+p] + } + loop do + str = "000" + lines[pos].to_s + case str + when .ends_with?("1") + lines[lines[pos+3]] = get.call(str[-3], 1) + get.call(str[-4], 2) + pos += 4 + when .ends_with?("2") + lines[lines[pos+3]] = get.call(str[-3], 1) * get.call(str[-4], 2) + pos += 4 + when .ends_with?("3") + lines[lines[pos+1]] = input.pop + pos += 2 + when .ends_with?("4") + output << get.call(str[-3], 1) + pos += 2 + when .ends_with?("5") + if get.call(str[-3], 1) != 0 + pos = get.call(str[-4], 2) + else + pos += 3 + end + when .ends_with?("6") + if get.call(str[-3], 1) == 0 + pos = get.call(str[-4], 2) + else + pos += 3 + end + when .ends_with?("7") + lines[lines[pos+3]] = (get.call(str[-3], 1) < get.call(str[-4], 2)) ? 1 : 0 + pos += 4 + when .ends_with?("8") + lines[lines[pos+3]] = (get.call(str[-3], 1) == get.call(str[-4], 2)) ? 1 : 0 + pos += 4 + when .ends_with?("99") + break + else + raise "aahhh #{str}" + end + end + {output, lines} +end +puts run(lines, [5]) diff --git a/day6.cr b/day6.cr new file mode 100644 index 0000000..b43a12e --- /dev/null +++ b/day6.cr @@ -0,0 +1,49 @@ +orbits = File.read("day6.txt").lines.map(&.chomp) +indirect = {} of String => Set(String) +direct = {} of String => Set(String) +edges_from = {} of String => Set(String) +orbits.each do |orbit| + big, small = orbit.split(")") + direct[big] ||= Set(String).new + direct[big] << small + (edges_from[big] ||= Set(String).new) << small + (edges_from[small] ||= Set(String).new) << big +end + +def compute_indirect(direct, indirect, for, current) + indirect[for] ||= Set(String).new + indirect[for] << current unless current == for + return unless direct.has_key? current + direct[current].each do |n| + compute_indirect(direct, indirect, for, n) + end +end + +direct.each_key do |k| + compute_indirect(direct, indirect, k, k) +end + +total_direct = direct.values.map(&.size).sum +total_indirect = indirect.values.map(&.size).sum +puts total_indirect + +start = "YOU" +dest = "SAN" +visited = Set(String).new +distances = { start => 0 } +queue = Set { start } +length = 0 +loop do + next_node = queue.min_by { |e| distances.fetch(e, 1000000) } + queue.delete next_node + + break if next_node == dest + next if visited.includes? next_node + visited << next_node + + edges_from[next_node].each do |neighbor| + distances[neighbor] ||= distances[next_node] + 1 + queue << neighbor + end +end +puts distances[dest]-2