Skip to content

Commit

Permalink
dec10 (#19)
Browse files Browse the repository at this point in the history
legit _finally_! got a little bit of help, though.
  • Loading branch information
srecnig committed Dec 19, 2023
1 parent 8bcec3c commit b3e7083
Show file tree
Hide file tree
Showing 12 changed files with 517 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Minitest::TestTask.create
task default: %i[lint test]

task :run do
ruby 'lib/dec-16/main.rb'
ruby 'lib/dec-10/main.rb'
end

RuboCop::RakeTask.new(:lint) do |task|
Expand Down
140 changes: 140 additions & 0 deletions lib/dec-10/input.txt

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions lib/dec-10/input1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
..F7.
.FJ|.
SJ.L7
|F--J
LJ...
9 changes: 9 additions & 0 deletions lib/dec-10/input2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
..........
.S------7.
.|F----7|.
.||OOOO||.
.||OOOO||.
.|L-7F-J|.
.|II||II|.
.L--JL--J.
..........
9 changes: 9 additions & 0 deletions lib/dec-10/input3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
...........
.S-------7.
.|F-----7|.
.||.....||.
.||.....||.
.|L-7.F-J|.
.|..|.|..|.
.L--J.L--J.
...........
10 changes: 10 additions & 0 deletions lib/dec-10/input4.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.F----7F7F7F7F-7....
.|F--7||||||||FJ....
.||.FJ||||||||L7....
FJL7L7LJLJ||LJ.L-7..
L--J.L7...LJS7F-7L7.
....F-J..F7FJ|L7L7L7
....L7.F7||L7|.L7L7|
.....|FJLJ|FJ|F7|.LJ
....FJL-7.||.||||...
....L---J.LJ.LJLJ...
10 changes: 10 additions & 0 deletions lib/dec-10/input5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FF7FSF7F7F7F7F7F---7
L|LJ||||||||||||F--J
FL-7LJLJ||||||LJL-77
F--JF--7||LJLJIF7FJ-
L---JF-JLJIIIIFJLJJ7
|F|F-JF---7IIIL7L|7|
|FFJF7L7F-JF7IIL---7
7-L-JL7||F7|L7F-7F7|
L.L7LFJ|||||FJL7||LJ
L7JLJL-JLJLJL--JLJ.L
19 changes: 9 additions & 10 deletions lib/dec-10/main.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
# frozen_string_literal: true

require_relative 'something'
require_relative 'pipe_maze'

def main1(filepath)
something = File.readlines(File.join(File.dirname(__FILE__), filepath), chomp: true)
p something
lines = File.readlines(File.join(File.dirname(__FILE__), filepath), chomp: true)
pipe_map = PipeMaze::PipeMap.new(lines)
pipe_map.follow_start!
pipe_map.calculate_inside!
pipe_map.print_inside
p pipe_map.path.length / 2
p pipe_map.inside_points.length
end

def main2(filepath)
something = File.readlines(File.join(File.dirname(__FILE__), filepath), chomp: true)
p something
end

main1('input1.txt')
# main2('input1.txt')
main1('input.txt')
187 changes: 187 additions & 0 deletions lib/dec-10/pipe_maze.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# frozen_string_literal: true

module PipeMaze
Coordinate = Struct.new(:x, :y)

class PipeMap
attr_reader :start, :path

def initialize(lines)
# read and create all the lines
column_count = lines[0].length
row_count = lines.length
@zero = Coordinate.new(0, 0)
@max = Coordinate.new(column_count - 1, row_count - 1)
max_coordinates = [@zero, @max]

@points = Array.new(row_count) { Array.new(column_count) }
lines.each_with_index do |line, y_index|
line.each_char.with_index do |char, x_index|
new_point = Point.new(
char, Coordinate.new(x_index, y_index), max_coordinates
)
@points[y_index][x_index] = new_point
@start = new_point if new_point.start?
end
end
end

def [](coordinate)
@points[coordinate.y][coordinate.x]
end

def follow_start!
potentially_connected_points = @start.connects_to.map { |c| self[c] }
connected_points = potentially_connected_points.select { |p| p.connects?(@start) }
@path = explore_route(start_point: connected_points[0], end_point: @start)
@path.each do |point|
point.in_path = true
point.outside = false
end

# set start to the proper logical_char
case connected_points.map(&:coordinate)
when [@start.north, @start.south]
@start.logical_char = '|'
when [@start.east, @start.west]
@start.logical_char = '-'
when [@start.north, @start.east]
@start.logical_char = 'L'
when [@start.north, @start.west]
@start.logical_char = 'J'
when [@start.south, @start.west]
@start.logical_char = '7'
when [@start.east, @start.south]
@start.logical_char = 'F'
end
end

def explore_route(start_point:, end_point:)
steps = []
last_point = end_point
current_point = start_point
loop do
steps << current_point
next_coordinate = current_point.connects_to.reject { |c| c == last_point.coordinate }.first
# if nil, there's no next coordinate, we're in a dead end.
return if next_coordinate.nil?
# if we're at the actual end
break if next_coordinate == end_point.coordinate

last_point = current_point
current_point = self[next_coordinate]
end
steps << end_point
steps
end

def calculate_inside!
@points.each do |row|
edges = row.select(&:edge?)
normalized_edges = edges.each.with_index.with_object([]) do |(edge, i), arr|
next_edge = edges[i + 1]

next if (edge.char == 'L' && next_edge && next_edge.char == '7') ||
(edge.char == 'F' && next_edge && next_edge.char == 'J')

arr << edge
end

row.each.with_index do |point, _i|
next if point.in_path

edge_count = normalized_edges.select { |e| e.coordinate.x > point.coordinate.x }.length
point.outside = edge_count.even?
end
end
end

def inside_points
@points.flatten.select { |p| !p.outside && !p.in_path }
end

def print_inside
p ''
@points.each do |line|
output = line.map do |p|
if p.in_path
p.char
elsif p.outside.nil?
'N'
elsif p.outside
'O'
else
'I'
end
end
puts output.join
end
end
end

class Point
attr_reader :char, :coordinate
attr_accessor :in_path, :logical_char, :outside

def initialize(char, coordinate, max_coordinates)
@char = char
@logical_char = char
@coordinate = coordinate
@in_path = false
@outside = nil
@zero = max_coordinates[0]
@max = max_coordinates[1]
end

def north
Coordinate.new(@coordinate.x, @coordinate.y - 1)
end

def east
Coordinate.new(@coordinate.x + 1, @coordinate.y)
end

def south
Coordinate.new(@coordinate.x, @coordinate.y + 1)
end

def west
Coordinate.new(@coordinate.x - 1, @coordinate.y)
end

def connects_to
connecting = []
case @logical_char
when '|'
connecting = [north, south]
when '-'
connecting = [east, west]
when 'L'
connecting = [north, east]
when 'J'
connecting = [north, west]
when '7'
connecting = [south, west]
when 'F'
connecting = [east, south]
when 'S'
connecting = [north, east, south, west]
when '.'
[]
end
connecting.filter { |n| n.x >= @zero.x && n.y >= @zero.y && n.x <= @max.x && n.y <= @max.y }
end

def edge?
@in_path && ['|', 'L', 'J', '7', 'F'].include?(@logical_char)
end

def connects?(point)
connects_to.include?(point.coordinate)
end

def start?
@char == 'S'
end
end
end
4 changes: 0 additions & 4 deletions lib/dec-10/something.rb

This file was deleted.

Loading

0 comments on commit b3e7083

Please sign in to comment.