Solve a few more puzzles.

This commit is contained in:
Danila Fedorin 2020-12-07 02:36:36 -08:00
parent 161ee6e244
commit 8a7eab81e0
6 changed files with 176 additions and 17 deletions

72
day10.cr Normal file
View File

@ -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

42
day11.cr Normal file
View File

@ -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

View File

@ -1,18 +1,18 @@
require "./intcode.cr" require "./intcode.cr"
require "./intcode_fibers.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) def chain_amplifiers(prog, perm, loop = false)
chans = perm.map { |f| new_interpreter(f, prog) } chans = perm.map { |f| new_interpreter(f, prog) }
chans.zip perm do |amp, freq| chans.zip perm do |amp, freq|
amp[0].send freq amp[0].send freq.to_i64
end end
chans[0][0].send 0 chans[0][0].send 0
i = 0 i = 0
history = Array(Int32).new(chans.size, 0) history = Array(Int64).new(chans.size, 0)
loop do loop do
j = (i+1) % chans.size j = (i+1) % chans.size
break unless received = chans[i][1].receive break unless received = chans[i][1].receive

19
day8.cr Normal file
View File

@ -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

7
day9.cr Normal file
View File

@ -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

View File

@ -1,40 +1,59 @@
def new_interpreter(f, prog) def new_interpreter(f, p)
prog = prog.clone prog = {} of Int64 => Int64
input = Channel(Int32).new p.each_with_index do |v, i|
output = Channel(Int32?).new prog[i.to_i64] = v.to_i64
end
input = Channel(Int64).new
output = Channel(Int64?).new
spawn do spawn do
op = "" op = ""
pc = 0 pc = 0_i64
arg = ->(i : Int32) { op[-(3+i)] == '0' ? prog[prog[pc+1+i]] : prog[pc+1+i] } 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 loop do
op = "0000" + prog[pc].to_s op = "0000" + prog[pc].to_s
case op case op
when .ends_with? "1" 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 pc += 4
when .ends_with? "2" 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 pc += 4
when .ends_with? "3" when .ends_with? "3"
prog[prog[pc+1]] = input.receive set.call(0, input.receive)
pc += 2 pc += 2
when .ends_with? "4" when .ends_with? "4"
output.send(arg.call(0)) output.send(get.call(0))
pc += 2 pc += 2
when .ends_with? "5" 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" 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" 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 pc += 4
when .ends_with? "8" 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 pc += 4
when .ends_with? "99" when .ends_with? "99"
input.receive input.receive
output.send(nil) output.send(nil)
break break
when .ends_with? "9"
base += get.call(0)
pc += 2
end end
end end
end end