Mercurial > repos > other > adventofcode2023
changeset 22:ad73a2ff3d06
Implement Day 15 part 1 and all of Day 16
Hash implementation was trivial, but I skipped the rest for now.
Day 16 part 1 approach works unchanged for part 2! Just needed
to run repeatedly with different inputs.
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sat, 16 Dec 2023 14:42:06 +0000 |
parents | 46fb65f2cb94 |
children | f34254b67082 |
files | day15.rb day15.txt day16.rb day16.txt day16b.rb |
diffstat | 5 files changed, 248 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/day15.rb Sat Dec 16 14:42:06 2023 +0000 @@ -0,0 +1,11 @@ +#! /usr/bin/env ruby + +if ARGV.length != 1 + abort("Incorrect arguments - needs input file") +elsif not File.exist? (ARGV[0]) + abort("File #{ARGV[0]} did not exist") +end + +file = ARGV[0] + +puts File.open(file, "r").each_line(chomp: true).first.split(",").map {|str| str.each_char.map(&:ord).reduce(0) {|sum, c| puts ((sum + c) * 17) % 256; ((sum + c) * 17) % 256 }}.reduce(:+)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/day15.txt Sat Dec 16 14:42:06 2023 +0000 @@ -0,0 +1,27 @@ +--- Day 15: Lens Library --- + +Implement a custom hashing algorithm: + Determine the ASCII code for the current character of the string. + Increase the current value by the ASCII code you just determined. + Set the current value to itself multiplied by 17. + Set the current value to the remainder of dividing itself by 256. + +Values are comma-separated. For example: + +rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7 + +Gives 11 individual steps; the result of running the HASH algorithm on each of the steps is as follows: + + rn=1 becomes 30. + cm- becomes 253. + qp=3 becomes 97. + cm=2 becomes 47. + qp- becomes 14. + pc=4 becomes 180. + ot=9 becomes 9. + ab=5 becomes 197. + pc- becomes 48. + pc=6 becomes 214. + ot=7 becomes 231. + +Then sum the hashes. \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/day16.rb Sat Dec 16 14:42:06 2023 +0000 @@ -0,0 +1,77 @@ +#! /usr/bin/env ruby + +require "set" + +if ARGV.length != 1 + abort("Incorrect arguments - needs input file") +elsif not File.exist? (ARGV[0]) + abort("File #{ARGV[0]} did not exist") +end + +file = ARGV[0] + +Laser = Struct.new(:x, :y, :direction) + +mirror_map = { + "." => { + right: [:right], + up: [:up], + left: [:left], + down: [:down] + }, + "/" => { + right: [:up], + up: [:right], + down: [:left], + left: [:down] + }, + "\\" => { + right: [:down], + down: [:right], + up: [:left], + left: [:up] + }, + "-" => { + right: [:right], + left: [:left], + down: [:left, :right], + up: [:left, :right] + }, + "|" => { + right: [:up, :down], + left: [:up, :down], + down: [:down], + up: [:up] + } +} + +def next_positions(puzzle, mirror_map, laser) + x_prime, y_prime = case laser.direction + when :right then [laser.x + 1, laser.y] + when :down then [laser.x, laser.y + 1] + when :left then [laser.x - 1, laser.y] + when :up then [laser.x, laser.y - 1] + end + if x_prime < 0 or x_prime >= puzzle[0].length or y_prime < 0 or y_prime >= puzzle.length + [] + else + new_space = puzzle[y_prime][x_prime] + # puts "#{laser.direction} to #{x_prime}, #{y_prime} (#{new_space})" + mirror_map[new_space][laser.direction].map {|dir| Laser.new(x_prime, y_prime, dir)} + end +end + +puzzle = File.open(file, "r").each_line(chomp: true).map {|line| line.each_char.to_a} +lasers = next_positions(puzzle, mirror_map, Laser.new(-1, 0, :right)) +energised = Array.new(puzzle.length) {Array.new(puzzle[0].length)} +energised [0][0] = 1 +previous_lasers = Set.new + +while lasers != [] +# puts "#{lasers}" + lasers = lasers.flat_map do |laser| + next_positions(puzzle, mirror_map, laser).filter {|new_laser| !previous_lasers.include? new_laser}.each {|new_laser| energised[new_laser.y][new_laser.x] = 1; previous_lasers << new_laser} + end +end + +puts energised.flatten.map(&:to_i).reduce(:+)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/day16.txt Sat Dec 16 14:42:06 2023 +0000 @@ -0,0 +1,49 @@ +--- Day 16: The Floor Will Be Lava --- + +A laser/mirror problem - "/" and "\" are mirrors that reflect 90°. +"-" and "|" are splitters - transparent in the same orientation, +but TWO beams go at 90° if hit against the flat edge. +"." is empty space. + +The laser starts in the top-right. + +For an example map: + +.|...\.... +|.-.\..... +.....|-... +........|. +.......... +.........\ +..../.\\.. +.-.-/..|.. +.|....-|.\ +..//.|.... + +The laser goes: + +>|<<<\.... +|v-.\^.... +.v...|->>> +.v...v^.|. +.v...v^... +.v...v^..\ +.v../2\\.. +<->-/vv|.. +.|<<<2-|.\ +.v//.|.v.. + +Every space that the laser goes through is "energised", which gives: + +######.... +.#...#.... +.#...##### +.#...##... +.#...##... +.#...##... +.#..####.. +########.. +.#######.. +.#...#.#.. + +The count of energised spaces is 46. \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/day16b.rb Sat Dec 16 14:42:06 2023 +0000 @@ -0,0 +1,84 @@ +#! /usr/bin/env ruby + +require "set" + +if ARGV.length != 1 + abort("Incorrect arguments - needs input file") +elsif not File.exist? (ARGV[0]) + abort("File #{ARGV[0]} did not exist") +end + +file = ARGV[0] + +Laser = Struct.new(:x, :y, :direction) + +mirror_map = { + "." => { + right: [:right], + up: [:up], + left: [:left], + down: [:down] + }, + "/" => { + right: [:up], + up: [:right], + down: [:left], + left: [:down] + }, + "\\" => { + right: [:down], + down: [:right], + up: [:left], + left: [:up] + }, + "-" => { + right: [:right], + left: [:left], + down: [:left, :right], + up: [:left, :right] + }, + "|" => { + right: [:up, :down], + left: [:up, :down], + down: [:down], + up: [:up] + } +} + +def next_positions(puzzle, mirror_map, laser) + x_prime, y_prime = case laser.direction + when :right then [laser.x + 1, laser.y] + when :down then [laser.x, laser.y + 1] + when :left then [laser.x - 1, laser.y] + when :up then [laser.x, laser.y - 1] + end + if x_prime < 0 or x_prime >= puzzle[0].length or y_prime < 0 or y_prime >= puzzle.length + [] + else + new_space = puzzle[y_prime][x_prime] + # puts "#{laser.direction} to #{x_prime}, #{y_prime} (#{new_space})" + mirror_map[new_space][laser.direction].map {|dir| Laser.new(x_prime, y_prime, dir)} + end +end + +puzzle = File.open(file, "r").each_line(chomp: true).map {|line| line.each_char.to_a} +puzzle_width = puzzle[0].length +puzzle_height = puzzle.length +start_points = ((0..puzzle_height).map{|y| [Laser.new(-1, y, :right), Laser.new(puzzle_width, y, :left)]} + (0..puzzle_width).map{|x| [Laser.new(x, -1, :down), Laser.new(x, puzzle_height, :up)]}).flatten + +max_energised = start_points.reduce(0) do |highest, start_point| + energised = Array.new(puzzle.length) {Array.new(puzzle[0].length)} + previous_lasers = Set.new + lasers = [start_point] + + while lasers != [] + # puts "#{lasers}" + lasers = lasers.flat_map do |laser| + next_positions(puzzle, mirror_map, laser).filter {|new_laser| !previous_lasers.include? new_laser}.each {|new_laser| energised[new_laser.y][new_laser.x] = 1; previous_lasers << new_laser} + end + end + + energised_count = energised.flatten.map(&:to_i).reduce(:+) + [highest, energised_count].max +end +puts max_energised \ No newline at end of file