Browse Source

Add the first few solutions.

master
Danila Fedorin 5 months ago
commit
e62a0067e7
  1. 15
      day1.hs
  2. 27
      day2.cr
  3. 43
      day3.cr
  4. 29
      day4.cr
  5. 49
      day5.cr
  6. 49
      day6.cr

15
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

27
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

43
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] }

29
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

49
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])

49
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
Loading…
Cancel
Save