Compare commits

...

12 Commits

Author SHA1 Message Date
65499624e7 rem map 2025-12-08 03:44:28 +00:00
3dbbab6fbe no need to current point value 2025-12-08 03:36:07 +00:00
3db1c4c372 delegate each_with_index 2025-12-08 03:32:55 +00:00
22afdfb126 remove extra comments 2025-12-08 03:19:25 +00:00
3811f7b26f add day_07 2025-12-08 03:16:37 +00:00
cce0b68275 already a symbol 2025-12-06 22:33:54 +00:00
dda849abd3 use num2 2025-12-06 22:32:51 +00:00
296866f017 add day_06 2025-12-06 22:27:04 +00:00
0a3b029aba add day_05 2025-12-05 06:40:39 +00:00
432d14e248 use deletaged methods
use single instance of Grid
2025-12-05 02:02:28 +00:00
c8c523dd66 use deletaged methods 2025-12-05 02:02:13 +00:00
f9e99d1d2c make {Grid}.data private
define delegated methods
2025-12-05 02:01:22 +00:00
11 changed files with 357 additions and 22 deletions

View File

@@ -13,8 +13,8 @@ class Main
@sum = 0
grid = Grid.new(data)
(0...grid.rows.size).each do |row_index|
(0...grid.columns.size).each do |column_index|
(0...grid.size).each do |row_index|
(0...grid[row_index].size).each do |column_index|
cell = grid.cell_at(row_index, column_index)
next unless cell.value == "@"

View File

@@ -15,15 +15,15 @@ class Main
grid = Grid.new(data)
loop do
grid_updated = false
(0...grid.rows.size).each do |row_index|
(0...grid.columns.size).each do |column_index|
(0...grid.size).each do |row_index|
(0...grid[row_index].size).each do |column_index|
cell = grid.cell_at(row_index, column_index)
next unless cell.value == "@"
if cell.neighbours.count do |neighbour|
neighbour.value == "@"
end < 4
data[row_index][column_index] = "x"
grid[row_index][column_index].value = "x"
@sum += 1
grid_updated = true
end
@@ -31,7 +31,6 @@ class Main
end
break unless grid_updated
grid = Grid.new(data)
end
puts @sum

View File

@@ -1,10 +1,14 @@
require "forwardable"
require_relative "cell"
class Grid
attr_reader :rows, :columns
attr_reader :columns
extend Forwardable
def_delegators :@data, :size, :[]
def initialize(input)
@rows = []
@data = []
(0...input.size).each do |row_index|
row = []
(0...input[row_index].size).each do |column_index|
@@ -12,27 +16,26 @@ class Grid
cell.value = input[row_index][column_index]
row << cell
end
@rows << row
@data << row
end
@columns = @rows.transpose
# Link neighbours
(0...@rows.size).each do |row_index|
(0...@columns.size).each do |column_index|
cell = @rows[row_index][column_index]
cell.n = @rows[row_index - 1][column_index] if row_index - 1 >= 0
cell.ne = @rows[row_index - 1][column_index + 1] if row_index - 1 >= 0 && column_index + 1 < @columns.size
cell.e = @rows[row_index][column_index + 1] if column_index + 1 < @columns.size
cell.se = @rows[row_index + 1][column_index + 1] if row_index + 1 < @rows.size && column_index + 1 < @columns.size
cell.s = @rows[row_index + 1][column_index] if row_index + 1 < @rows.size
cell.sw = @rows[row_index + 1][column_index - 1] if row_index + 1 < @rows.size && column_index - 1 >= 0
cell.w = @rows[row_index][column_index - 1] if column_index - 1 >= 0
cell.nw = @rows[row_index - 1][column_index - 1] if row_index - 1 >= 0 && column_index - 1 >= 0
(0...@data.size).each do |row_index|
(0...@data[row_index].size).each do |column_index|
cell = @data[row_index][column_index]
cell.n = @data[row_index - 1][column_index] if row_index - 1 >= 0
cell.ne = @data[row_index - 1][column_index + 1] if row_index - 1 >= 0 && column_index + 1 < @data[row_index - 1].size
cell.e = @data[row_index][column_index + 1] if column_index + 1 < @data[row_index].size
cell.se = @data[row_index + 1][column_index + 1] if row_index + 1 < @data.size && column_index + 1 < @data[row_index + 1].size
cell.s = @data[row_index + 1][column_index] if row_index + 1 < @data.size
cell.sw = @data[row_index + 1][column_index - 1] if row_index + 1 < @data.size && column_index - 1 >= 0
cell.w = @data[row_index][column_index - 1] if column_index - 1 >= 0
cell.nw = @data[row_index - 1][column_index - 1] if row_index - 1 >= 0 && column_index - 1 >= 0
end
end
end
def cell_at(row, column)
@rows[row][column]
@data[row][column]
end
end

28
day_05/1.rb Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
class Main
def run
ranges = []
ingredient_ids = Hash.new(0)
$stdin.each_line do |line|
arr = line.chomp.split("-").map(&:to_i)
if arr.size == 2
ranges << (arr[0]..arr[1])
elsif arr.size == 1
ingredient_ids[arr[0]] += 1
end
end
@sum = 0
ingredient_ids.each do |id, count|
if ranges.any? { |r| r.include?(id) }
@sum += count
end
end
puts @sum
end
end
Main.new.run

47
day_05/2.rb Executable file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
class Main
def run
ranges = []
$stdin.each_line do |line|
arr = line.chomp.split("-").map(&:to_i)
if arr.size == 2
ranges << (arr[0]..arr[1])
end
end
# Sort ranges by starting point
# This prevents having to check all previous ranges for every new range
ranges.sort_by!(&:begin)
valid_id_ranges = []
ranges.each do |r|
valid_id_ranges.each do |vr|
if (
# r starts inside vr
r.begin >= vr.begin && r.begin <= vr.end) ||
# r ends inside vr
(r.end >= vr.begin && r.end <= vr.end) ||
# vr starts inside r
(vr.begin >= r.begin && vr.begin <= r.end) ||
# vr ends inside r
(vr.end >= r.begin && vr.end <= r.end)
# Merge ranges
r = ([r.begin, vr.begin].min..[r.end, vr.end].max)
valid_id_ranges.delete(vr)
end
end
valid_id_ranges << r
end
@total = 0
valid_id_ranges.each do |r|
@total += (r.end - r.begin + 1)
end
puts @total
end
end
Main.new.run

53
day_06/1.rb Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
class Main
def run
problems = Hash.new(0)
$stdin.each_line do |line|
arr = line.chomp.split.map do |part|
if /^\d+$/.match?(part)
part.to_i
else
part.to_sym
end
end.compact
arr.each_with_index do |part, idx|
problems[idx] = [] unless problems.key?(idx)
problems[idx] << part
end
end
@sum = 0
problems.each do |_, parts|
@sum += recurse(parts[..-2], parts.last)
end
puts @sum
end
def recurse(nums, op)
return nums.first if nums.size == 1
num1, num2 = nums.shift(2)
case op
when :+
nums.unshift(num1 + num2)
when :-
nums.unshift(num1 - num2)
when :*
nums.unshift(num1 * num2)
when :/
if num2 == 0
raise "Division by zero"
end
nums.unshift(num1 / num2)
end
recurse(nums, op)
end
end
Main.new.run

68
day_06/2.rb Executable file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require "stringio"
class Main
def run
num_map = []
$stdin.each_line do |line|
num_map << line.chomp.chars
end
problems = Hash.new(0)
count = 0
problems[count] = Hash.new(0)
num_map.transpose.each do |chars|
if chars.uniq == [" "]
count += 1
problems[count] = Hash.new(0)
next
end
num_str = StringIO.new
chars.each do |ch|
if ch.match?(/\d/)
num_str.write(ch)
else
problems[count][:op] = [] unless problems[count].key?(:op)
problems[count][:op] << ch.to_sym unless ch == " "
end
end
problems[count][:nums] = [] unless problems[count].key?(:nums)
problems[count][:nums] << num_str.string.to_i unless num_str.string.empty?
end
@sum = 0
problems.each do |_, data|
@sum += recurse(data[:nums], data[:op].first)
end
puts @sum
end
def recurse(nums, op)
return nums.first if nums.size == 1
num1, num2 = nums.shift(2)
case op
when :+
nums.unshift(num1 + num2)
when :-
nums.unshift(num1 - num2)
when :*
nums.unshift(num1 * num2)
when :/
if num2 == 0
raise "Division by zero"
end
nums.unshift(num1 / num2)
end
recurse(nums, op)
end
end
Main.new.run

42
day_07/1.rb Executable file
View File

@@ -0,0 +1,42 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require_relative "graph"
class Main
def run
input = $stdin.readlines(chomp: true)
graph = Graph.new(input)
total = dfs(graph.start, graph, 0, Set.new)
puts total
end
def dfs(next_point, graph, total, visited)
if next_point.y > graph.height || visited.include?(next_point)
return total
end
if graph.at(next_point) == "^"
step_west = Point.new(next_point.x - 1, next_point.y)
step_east = Point.new(next_point.x + 1, next_point.y)
if graph.at(step_west) == "." ||
graph.at(step_east) == "."
total += 1
end
# step west then dfs south
total = dfs(step_west, graph, total, visited)
# step east then dfs south
total = dfs(step_east, graph, total, visited)
return total
elsif graph.at(next_point) == "."
visited.add(next_point)
end
dfs(Point.new(next_point.x, next_point.y + 1), graph, total, visited) # south
end
end
Main.new.run

39
day_07/2.rb Executable file
View File

@@ -0,0 +1,39 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require_relative "graph"
class Main
def run
input = $stdin.readlines(chomp: true)
graph = Graph.new(input)
counts = Hash.new(0)
counts[graph.start.x] = 1
process_graph(graph, counts)
puts counts.values.sum
end
def process_graph(graph, counts)
graph.each_with_index do |line, y|
line.each_with_index do |char, x|
next unless char == "^"
distribute_counts(x, y, counts)
end
end
end
# When we encounter a "^", we split the count to the west and east positions
# and reset the current position count to 0.
def distribute_counts(x, y, counts)
peek_west = Point.new(x - 1, y)
peek_east = Point.new(x + 1, y)
counts[peek_west.x] += counts[x]
counts[peek_east.x] += counts[x]
counts[x] = 0
end
end
Main.new.run

32
day_07/graph.rb Normal file
View File

@@ -0,0 +1,32 @@
require "forwardable"
require_relative "point"
class Graph
attr_reader :start, :height, :width
extend Forwardable
def_delegators :@data, :[], :each_with_index
def initialize(input)
@data = input.each_with_index.map do |line, y|
if y.zero?
@start = Point.new(line.index("S"), y)
end
line.chars
end
@width = @data[0].size - 1
@height = @data.size - 1
end
def to_s
@data.map { |row| row.join("") }.join("\n")
end
def at(point)
@data[point.y][point.x]
end
def out_of_bounds?(point)
point.x < 0 || point.x > @width || point.y < 0 || point.y > @height
end
end

24
day_07/point.rb Normal file
View File

@@ -0,0 +1,24 @@
class Point
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
def to_s
"(#{x}, #{y})"
end
def ==(other)
x == other.x && y == other.y
end
def hash
[x, y].hash
end
def eql?(other)
self == other
end
end