Mercurial > repos > other > adventofcode2023
view day18.rb @ 36:7197f31970ff
Day 25 part 1 instructions and partial solution
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Thu, 18 Apr 2024 19:56:23 +0100 |
parents | 6b58ddfaed38 |
children |
line wrap: on
line source
#! /usr/bin/env ruby if ARGV.length < 1 or ARGV.length > 2 abort("Incorrect arguments - needs input file and optional 'b' for part 2") elsif not File.exist? (ARGV[0]) abort("File #{ARGV[0]} did not exist") end file = ARGV[0] instructions = File.open(file, "r").each_line(chomp: true).map(&:split) Coord = Struct.new(:x,:y, :values) trench = [Coord.new(0,0, [])] if ARGV.length == 1 def decode(instruction) [instruction[0], instruction[1]] end else def decode(instruction) # Offset of 2 because of brackets and hash dir_char = case instruction[2][7] when "0" then "R" when "1" then "D" when "2" then "L" when "3" then "U" end num_steps = instruction[2][2,5].to_i(16) [dir_char, num_steps] end end instructions.reduce(trench[0]) do |pos, instruction| dir_char, num_steps = decode(instruction) # Map to cardinal directions so that we can use the day 10 border crossing algorithm # for finding "inside" nodes case dir_char when "R" x_change = 1 y_change = 0 prev_dir = :east next_dir = :west when "L" x_change = -1 y_change = 0 prev_dir = :west next_dir = :east when "U" x_change = 0 y_change = -1 prev_dir = :north next_dir = :south when "D" x_change = 0 y_change = 1 prev_dir = :south next_dir = :north end num_steps.to_i.times do |i| pos.values << prev_dir pos = Coord.new(pos.x + x_change, pos.y + y_change, [next_dir]) trench << pos end pos end x_min, x_max = trench.map(&:x).minmax y_min, y_max = trench.map(&:y).minmax puts x_min, y_min if ARGV.length > 1 puts "We can't brute force this. Answers online suggest shoelace formula and Pick's theorem" puts "So we'll call it quits and skip this" return end dig_map = Hash.new trench.each do |pos| new_x = pos.x - x_min new_y = pos.y - y_min coords = [new_x, new_y] if dig_map.key? (coords) dig_map[coords] += pos.values else dig_map[coords] = pos.values end dig_map[coords].sort! end State = Struct.new(:crossed_lines, :inside_count, :last_switch) in_out_transition = [:north, :south] state = State.new(0,0,nil) cells_inside = (y_max - y_min + 1).times do |y| state.last_switch = nil (x_max - x_min + 1).times do |x| cell = dig_map[[x,y]] if cell #puts "#{x},#{y} - #{cell}" # Same algorithm as Day 10 EXCEPT we count the trench/border as well state.inside_count += 1 if cell == in_out_transition state.crossed_lines += 1 elsif cell != [:east, :west] this_switch = (cell & in_out_transition) if state.last_switch.nil? state.last_switch = this_switch else if this_switch != state.last_switch state.crossed_lines += 1 end state.last_switch = nil end end elsif state.crossed_lines % 2.0 != 0 #puts "#{x},#{y} - inside" state.inside_count += 1 else #puts "#{x},#{y} - crossed #{state.crossed_lines} lines" end state end state end puts state.inside_count