4s to run part 2. But still happy with it.
							parent
							
								
									9ffad3b1b4
								
							
						
					
					
						commit
						8ea740f029
					
				| @ -0,0 +1,254 @@ | ||||
| const std = @import("std"); | ||||
| 
 | ||||
| const Dir = enum(usize) { up, right, down, left }; | ||||
| const Coord = struct { row: usize, col: usize }; | ||||
| const Beam = struct { dir: Dir, coord: Coord }; | ||||
| 
 | ||||
| pub fn main() !void { | ||||
|     var content = @embedFile("data.txt"); | ||||
| 
 | ||||
|     var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||||
|     const allocator = gpa.allocator(); | ||||
| 
 | ||||
|     var grid = std.ArrayList(std.ArrayList(u8)).init(allocator); | ||||
|     defer grid.deinit(); | ||||
| 
 | ||||
|     var lines = std.mem.split(u8, content, "\n"); | ||||
| 
 | ||||
|     while (lines.next()) |line| { | ||||
|         if (line.len < 1) { | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         var lineArrayList = std.ArrayList(u8).init(allocator); | ||||
| 
 | ||||
|         for (line) |char| { | ||||
|             try lineArrayList.append(char); | ||||
|         } | ||||
| 
 | ||||
|         try grid.append(lineArrayList); | ||||
|     } | ||||
| 
 | ||||
|     const energy = try energize(Beam{ .dir = Dir.right, .coord = Coord{ .row = 0, .col = 0 } }, grid); | ||||
| 
 | ||||
|     std.debug.print("Part 1: {d}\n", .{energy}); | ||||
| 
 | ||||
|     const height = grid.items.len; | ||||
|     const width = grid.items[0].items.len; | ||||
| 
 | ||||
|     var maxEnergy: usize = 0; | ||||
| 
 | ||||
|     for (0..height) |row| { | ||||
|         for ([_]usize{ 0, width - 1 }) |col| { | ||||
|             const dir = if (col == 0) Dir.right else Dir.left; | ||||
|             const start = Beam{ .dir = dir, .coord = Coord{ .row = row, .col = col } }; | ||||
|             const e = try energize(start, grid); | ||||
|             if (e > maxEnergy) { | ||||
|                 maxEnergy = e; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for (0..width) |col| { | ||||
|         for ([_]usize{ 0, height - 1 }) |row| { | ||||
|             const dir = if (row == 0) Dir.down else Dir.up; | ||||
|             const start = Beam{ .dir = dir, .coord = Coord{ .row = row, .col = col } }; | ||||
|             const e = try energize(start, grid); | ||||
|             if (e > maxEnergy) { | ||||
|                 maxEnergy = e; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std.debug.print("Part 2: {d}\n", .{maxEnergy}); | ||||
| } | ||||
| 
 | ||||
| fn energize(start: Beam, grid: std.ArrayList(std.ArrayList(u8))) !usize { | ||||
|     var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||||
|     const allocator = gpa.allocator(); | ||||
| 
 | ||||
|     var beams = std.ArrayList(Beam).init(allocator); | ||||
|     defer beams.deinit(); | ||||
| 
 | ||||
|     // add the first beam | ||||
|     try beams.append(start); | ||||
| 
 | ||||
|     var energized = std.AutoHashMap(Coord, void).init(allocator); | ||||
|     defer energized.deinit(); | ||||
| 
 | ||||
|     var beamHistory = std.AutoHashMap(Beam, void).init(allocator); | ||||
|     defer beamHistory.deinit(); | ||||
| 
 | ||||
|     const height = grid.items.len; | ||||
|     const width = grid.items[0].items.len; | ||||
| 
 | ||||
|     while (true) { | ||||
|         // make 2 new lists: beams to add, and beams to remove. | ||||
|         // batch these while iterating, and do it all after | ||||
|         var beamsToAdd = std.ArrayList(Beam).init(allocator); | ||||
|         defer beamsToAdd.deinit(); | ||||
| 
 | ||||
|         var beamsToRemove = std.ArrayList(usize).init(allocator); | ||||
|         defer beamsToRemove.deinit(); | ||||
| 
 | ||||
|         if (beams.items.len == 0) { | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         for ((&beams).items, 0..) |*b, beamNumber| { | ||||
|             if (isOutOfGrid(b, grid)) { | ||||
|                 try beamsToRemove.append(beamNumber); | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             try energized.put(b.coord, {}); | ||||
| 
 | ||||
|             if (beamHistory.contains(b.*)) { | ||||
|                 try beamsToRemove.append(beamNumber); | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             try beamHistory.put(b.*, {}); | ||||
| 
 | ||||
|             const row = b.coord.row; | ||||
|             const col = b.coord.col; | ||||
| 
 | ||||
|             const value = grid.items[row].items[col]; | ||||
| 
 | ||||
|             const goStraight = value == '.' or (value == '|' and (b.dir == .up or b.dir == .down)) or | ||||
|                 (value == '-' and (b.dir == .left or b.dir == .right)); | ||||
| 
 | ||||
|             if (goStraight) { | ||||
|                 switch (b.dir) { | ||||
|                     .up => if (row == 0) { | ||||
|                         b.coord.row = height + 10; // put it out of the grid to get cleaned up | ||||
|                     } else { | ||||
|                         b.coord.row -= 1; | ||||
|                     }, | ||||
|                     .right => b.coord.col += 1, | ||||
|                     .down => b.coord.row += 1, | ||||
|                     .left => if (col == 0) { | ||||
|                         b.coord.col = width + 10; // put it out of the grid to get cleaned up | ||||
|                     } else { | ||||
|                         b.coord.col -= 1; | ||||
|                     }, | ||||
|                 } | ||||
|             } else if (value == '|') { | ||||
|                 if (row == 0) { | ||||
|                     // if we are on the top row, change the beam to go down | ||||
|                     b.dir = Dir.down; | ||||
|                     b.coord.row += 1; | ||||
|                 } else { | ||||
|                     // otherwise, change beam direction to up and move it up one cell | ||||
|                     b.dir = Dir.up; | ||||
|                     b.coord.row -= 1; | ||||
|                     if (row != height - 1) { | ||||
|                         // and if we're not on the _bottom_ row, | ||||
|                         // create a new beam going down, below this cell | ||||
|                         const newBeam = Beam{ .dir = Dir.down, .coord = Coord{ .row = row + 1, .col = col } }; | ||||
|                         try beamsToAdd.append(newBeam); | ||||
|                     } | ||||
|                 } | ||||
|             } else if (value == '-') { | ||||
|                 if (col == 0) { | ||||
|                     // if we are on the first col, change the beam to go right | ||||
|                     b.dir = Dir.right; | ||||
|                     b.coord.col += 1; | ||||
|                 } else { | ||||
|                     // otherwise, change beam direction to left and move it left one cell | ||||
|                     b.dir = Dir.left; | ||||
|                     b.coord.col -= 1; | ||||
|                     if (col != width - 1) { | ||||
|                         // and if we're not on the _last_ column, | ||||
|                         // create a new beam going right, to the right this cell | ||||
|                         const newBeam = Beam{ .dir = Dir.right, .coord = Coord{ .row = row, .col = col + 1 } }; | ||||
|                         try beamsToAdd.append(newBeam); | ||||
|                     } | ||||
|                 } | ||||
|             } else if (value == '/') { | ||||
|                 switch (b.dir) { | ||||
|                     .up => { | ||||
|                         b.dir = Dir.right; | ||||
|                         b.coord.col += 1; | ||||
|                     }, | ||||
|                     .right => if (row == 0) { | ||||
|                         b.coord.row = height + 10; // put it out of the grid to get cleaned up | ||||
|                     } else { | ||||
|                         b.dir = Dir.up; | ||||
|                         b.coord.row -= 1; | ||||
|                     }, | ||||
|                     .down => if (col == 0) { | ||||
|                         b.coord.row = height + 10; // put it out of the grid to get cleaned up | ||||
|                     } else { | ||||
|                         b.dir = Dir.left; | ||||
|                         b.coord.col -= 1; | ||||
|                     }, | ||||
|                     .left => { | ||||
|                         b.dir = Dir.down; | ||||
|                         b.coord.row += 1; | ||||
|                     }, | ||||
|                 } | ||||
|             } else if (value == '\\') { | ||||
|                 switch (b.dir) { | ||||
|                     .up => if (col == 0) { | ||||
|                         b.coord.col = width + 10; // put it out of the grid to get cleaned up | ||||
|                     } else { | ||||
|                         b.dir = Dir.left; | ||||
|                         b.coord.col -= 1; | ||||
|                     }, | ||||
|                     .right => { | ||||
|                         b.dir = Dir.down; | ||||
|                         b.coord.row += 1; | ||||
|                     }, | ||||
|                     .down => { | ||||
|                         b.dir = Dir.right; | ||||
|                         b.coord.col += 1; | ||||
|                     }, | ||||
|                     .left => if (row == 0) { | ||||
|                         b.coord.row = height + 10; // put it out of the grid to get cleaned up | ||||
|                     } else { | ||||
|                         b.dir = Dir.up; | ||||
|                         b.coord.row -= 1; | ||||
|                     }, | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // remove the beams in reverse order | ||||
|         const len = beamsToRemove.items.len; | ||||
|         for (0..len) |j| { | ||||
|             const idx = beamsToRemove.items[len - j - 1]; | ||||
|             _ = beams.orderedRemove(idx); | ||||
|         } | ||||
|         beamsToRemove.clearAndFree(); | ||||
| 
 | ||||
|         // add the new beams | ||||
|         for (beamsToAdd.items) |beam| { | ||||
|             try beams.append(beam); | ||||
|         } | ||||
|         beamsToAdd.clearAndFree(); | ||||
|     } | ||||
| 
 | ||||
|     return energized.count(); | ||||
| } | ||||
| 
 | ||||
| fn isOutOfGrid(beam: *Beam, grid: std.ArrayList(std.ArrayList(u8))) bool { | ||||
|     const row = beam.coord.row; | ||||
|     const col = beam.coord.col; | ||||
|     const height = grid.items.len; | ||||
|     const width = grid.items[0].items.len; | ||||
|     return row < 0 or row >= height or col < 0 or col >= width; | ||||
| } | ||||
| 
 | ||||
| fn printGrid(grid: std.ArrayList(std.ArrayList(u8)), energized: std.AutoHashMap(Coord, void)) void { | ||||
|     for (grid.items, 0..) |line, row| { | ||||
|         for (line.items, 0..) |char, col| { | ||||
|             if (char == '.' and energized.contains(Coord{ .row = row, .col = col })) { | ||||
|                 std.debug.print("#", .{}); | ||||
|             } else { | ||||
|                 std.debug.print("{c}", .{char}); | ||||
|             } | ||||
|         } | ||||
|         std.debug.print("\n", .{}); | ||||
|     } | ||||
| } | ||||
					Loading…
					
					
				
		Reference in New Issue