From 8a7eab81e0afeef3de4f133970860a880b089d1f Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Mon, 7 Dec 2020 02:36:36 -0800 Subject: [PATCH] Solve a few more puzzles. --- day10.cr | 72 +++++++++++++++++++++++++++++++++++++++++++++++ day11.cr | 42 +++++++++++++++++++++++++++ day7.cr | 6 ++-- day8.cr | 19 +++++++++++++ day9.cr | 7 +++++ intcode_fibers.cr | 47 ++++++++++++++++++++++--------- 6 files changed, 176 insertions(+), 17 deletions(-) create mode 100644 day10.cr create mode 100644 day11.cr create mode 100644 day8.cr create mode 100644 day9.cr diff --git a/day10.cr b/day10.cr new file mode 100644 index 0000000..13641f2 --- /dev/null +++ b/day10.cr @@ -0,0 +1,72 @@ +require "advent" + +struct Tuple(*T) + def reduce_fraction + gcd = (self[0].gcd self[1]).abs + return self if gcd == 0 + {self[0] // gcd, self[1]//gcd} + end +end + +struct Tuple(*T) + def -(other) + {self[0]-other[0], self[1] - other[1]} + end + + def dist + self[0] + self[1] + end +end + +input = input(2019, 10) +asteroids = Set({Int32, Int32}).new +input.lines.each_with_index do |l, y| + l.chars.each_with_index do |c, x| + next unless c == '#' + asteroids << {x, y} + end +end + +p1 = asteroids.max_of do |a| + angles = Set({Int32, Int32}).new + asteroids.each do |b| + next if a == b + angles << (b-a).reduce_fraction + end + angles.size +end + +puts p1 + +p2s = asteroids.max_by do |a| + angles = Set({Int32, Int32}).new + asteroids.each do |b| + next if a == b + angles << (b-a).reduce_fraction + end + angles.size +end + +angle_groups = asteroids.group_by do |a| + (a - p2s).reduce_fraction +end +angle_groups.delete({0,0}) +angle_groups.each do |k, v| + v.sort! do |a| + (a - p2s).dist + end +end + +angles = angle_groups.keys.sort_by do |k| + -Math.atan2(k[0].to_f32, k[1].to_f32) +end +i = 1 +angles.cycle do |angle| + next if angle_groups[angle].empty? + asteroid = angle_groups[angle].delete_at(0) + if i == 200 + puts asteroid[0] * 100 + asteroid[1] + break + end + i += 1 +end diff --git a/day11.cr b/day11.cr new file mode 100644 index 0000000..2ab3f31 --- /dev/null +++ b/day11.cr @@ -0,0 +1,42 @@ +require "advent" +require "./intcode_fibers.cr" + +painted_white = Set({Int64, Int64}).new +color = {} of {Int64,Int64} => Int64 +color[{0_i64, 0_i64}] = 1_i64 +input, output = new_interpreter("", input(2019, 11).split(",").map &.to_i64) +pos = {0_i64, 0_i64} +facing = {0_i64, 1_i64} + +struct Tuple(*T) + def turn_left + {-self[1], self[0]} + end + + def turn_right + turn_left.turn_left.turn_left + end + + def add(other) + {self[0] + other[0], self[1] + other[1]} + end +end + +loop do + c = color[pos]? || 0_i64 + input.send c + break unless nc = output.receive + break unless turn = output.receive + color[pos] = nc + painted_white << pos if nc == 1 + facing = (turn == 0 ? facing.turn_left : facing.turn_right) + pos = pos.add facing +end + +6.times do |y| + y = - y + 45.times do |x| + print (color[{x.to_i64, y.to_i64}]? == 1 ? '#' : ' ') + end + puts +end diff --git a/day7.cr b/day7.cr index e8ed3b4..e8fc144 100644 --- a/day7.cr +++ b/day7.cr @@ -1,18 +1,18 @@ require "./intcode.cr" require "./intcode_fibers.cr" -prog = File.read("day7.txt").chomp.split(",").map(&.to_i32) +prog = File.read("day7.txt").chomp.split(",").map(&.to_i64) def chain_amplifiers(prog, perm, loop = false) chans = perm.map { |f| new_interpreter(f, prog) } chans.zip perm do |amp, freq| - amp[0].send freq + amp[0].send freq.to_i64 end chans[0][0].send 0 i = 0 - history = Array(Int32).new(chans.size, 0) + history = Array(Int64).new(chans.size, 0) loop do j = (i+1) % chans.size break unless received = chans[i][1].receive diff --git a/day8.cr b/day8.cr new file mode 100644 index 0000000..aefc8de --- /dev/null +++ b/day8.cr @@ -0,0 +1,19 @@ +require "advent" + +input = input(2019, 8).chomp +layers = input.chars.each_slice(25*6).to_a +layer = layers.min_by(&.count('0')) +puts(layer.count('2') * layer.count('1')) + +message = layers.reduce do |l1, l2| + l1.zip_with(l2) do |a1, a2| + next (a1 == '2') ? a2 : a1 + end +end + +6.times do |i| + 25.times do |j| + print(message[25*i+j] == '1' ? '#' : ' ') + end + puts +end diff --git a/day9.cr b/day9.cr new file mode 100644 index 0000000..9fa6387 --- /dev/null +++ b/day9.cr @@ -0,0 +1,7 @@ +require "advent" +require "./intcode_fibers.cr" + +input = input(2019, 9).split(",").map &.to_i64 +input, output = new_interpreter("", input) +input.send 2_i64 +puts output.receive diff --git a/intcode_fibers.cr b/intcode_fibers.cr index 18ee2e1..6604ab1 100644 --- a/intcode_fibers.cr +++ b/intcode_fibers.cr @@ -1,40 +1,59 @@ -def new_interpreter(f, prog) - prog = prog.clone - input = Channel(Int32).new - output = Channel(Int32?).new +def new_interpreter(f, p) + prog = {} of Int64 => Int64 + p.each_with_index do |v, i| + prog[i.to_i64] = v.to_i64 + end + + input = Channel(Int64).new + output = Channel(Int64?).new spawn do op = "" - pc = 0 - arg = ->(i : Int32) { op[-(3+i)] == '0' ? prog[prog[pc+1+i]] : prog[pc+1+i] } + pc = 0_i64 + base = 0_i64 + index = ->(i : Int32) { + case op[-(3+i)] + when '0' + prog[pc+1+i] + when '1' + pc+1+i + else + prog[pc+1+i] + base + end + } + get = ->(i : Int32) { prog[index.call(i)]? || 0_i64 } + set = ->(i : Int32, v : Int64) { prog[index.call(i)] = v } loop do op = "0000" + prog[pc].to_s case op when .ends_with? "1" - prog[prog[pc+3]] = arg.call(0) + arg.call(1) + set.call(2, get.call(0) + get.call(1)) pc += 4 when .ends_with? "2" - prog[prog[pc+3]] = arg.call(0) * arg.call(1) + set.call(2, get.call(0) * get.call(1)) pc += 4 when .ends_with? "3" - prog[prog[pc+1]] = input.receive + set.call(0, input.receive) pc += 2 when .ends_with? "4" - output.send(arg.call(0)) + output.send(get.call(0)) pc += 2 when .ends_with? "5" - pc = arg.call(0) != 0 ? arg.call(1) : pc + 3 + pc = get.call(0) != 0 ? get.call(1) : pc + 3 when .ends_with? "6" - pc = arg.call(0) == 0 ? arg.call(1) : pc + 3 + pc = get.call(0) == 0 ? get.call(1) : pc + 3 when .ends_with? "7" - prog[prog[pc+3]] = arg.call(0) < arg.call(1) ? 1 : 0 + set.call(2, get.call(0) < get.call(1) ? 1_i64 : 0_i64) pc += 4 when .ends_with? "8" - prog[prog[pc+3]] = arg.call(0) == arg.call(1) ? 1 : 0 + set.call(2, get.call(0) == get.call(1) ? 1_i64 : 0_i64) pc += 4 when .ends_with? "99" input.receive output.send(nil) break + when .ends_with? "9" + base += get.call(0) + pc += 2 end end end