diff --git a/common.cr b/common.cr index e76094e..02f985e 100644 --- a/common.cr +++ b/common.cr @@ -1,5 +1,5 @@ module Enumerable(T) - def count_each(others) + def count_each count_map = {} of T => Int32 each do |other| count_map[other] = (count_map[other]? || 0) + 1 diff --git a/day13.cr b/day13.cr new file mode 100644 index 0000000..0e9af4d --- /dev/null +++ b/day13.cr @@ -0,0 +1,120 @@ +require "./common.cr" + +lines = File.read("day13_input").split "\n" +lines.pop + +map = lines.map &.chars +carts = [] of Tuple(Int32, Int32, Char, Char) + +map.each_with_index do |line, y| + line.each_with_index do |char, x| + carts << {x, y, char, 'l'} if char == '>' || char == '<' || char == '^' || char == 'v' + end +end + +def next_turn(char) + return 'r' if char == 's' + return 'l' if char == 'r' + return 's' +end + +def turn_dir(char, turn) + if turn == 'l' + return '<' if char == '^' + return 'v' if char == '<' + return '>' if char == 'v' + return '^' if char == '>' + end + if turn == 'r' + return '>' if char == '^' + return '^' if char == '<' + return '<' if char == 'v' + return 'v' if char == '>' + end + return char +end + +def offset(char) + case char + when '^' + {0, -1} + when 'v' + {0, 1} + when '<' + {-1, 0} + when '>' + {1, 0} + else + {0, 0} + end +end + +def turn(cart, turnchar) + if turnchar == '/' + return '>' if cart == '^' + return 'v' if cart == '<' + return '^' if cart == '>' + return '<' + elsif turnchar == '\\' + return 'v' if cart == '>' + return '<' if cart == '^' + return '^' if cart == '<' + return '>' + end + return cart +end + +def simulate(map, carts) + crashed = [] of Int32 + crashed_pos = [] of Tuple(Int32, Int32) + + carts.sort_by! do |cart| + x, y, c, t = cart + y * 280 + x + end + + carts.each_with_index do |cart, index| + next if crashed.includes? index + x, y, c, t = cart + + # TRUSTED + dx, dy = offset(c) + x += dx + y += dy + if map[y][x] == '+' + c = turn_dir(c, t) + t = next_turn(t) + else + c = turn(c, map[y][x]) + end + # UNTRUSTED + + carts.each_with_index do |c2, i2| + next if crashed.includes? i2 + next if (c2[0] != x) || (c2[1] != y) + + puts carts + crashed << index + crashed << i2 + crashed_pos << {x, y} + end + + carts[index] = {x, y, c, t} + end + + crashed.sort!.reverse!.uniq!.each do |index| + carts.delete_at index + end + + unless crashed_pos.empty? + puts crashed_pos + end + + return carts.size <= 1 +end + +count = 0 +while !simulate(map, carts) + count += 1 +end +puts carts[0]?