// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // https://adventofcode.com/2024/day/15 library "day15_common"; import Core library "io"; import library "io_utils"; // TODO: Use a choice type. class Square { adapt char; impl as Core.Copy { fn Op[self: Self]() -> Self { return (self as char).(Core.Copy.Op)() as Self; } } impl as Core.EqWith(Square) { fn Equal[self: Self](other: Self) -> bool { // TODO: Use a `char` comparison when it's supported. return (self as u8) == (other as u8); } fn NotEqual[self: Self](other: Self) -> bool { // TODO: Use a `char` comparison when it's supported. return (self as u8) != (other as u8); } } fn Make(c: CharOrEOF) -> Square { // TODO: Use `match`. if (c == '#') { return ('#' as char) as Square; } if (c == 'O') { return ('O' as char) as Square; } if (c == '.') { return ('.' as char) as Square; } if (c == '@') { return ('@' as char) as Square; } return ('!' as char) as Square; } } let Wall: Square = ('#' as char) as Square; let Box: Square = ('O' as char) as Square; let Empty: Square = ('.' as char) as Square; let Robot: Square = ('@' as char) as Square; class Grid { impl as Core.UnformedInit {} fn Read() -> Grid { returned var me: Grid; var y: i32 = 0; while (y < 50) { var x: i32 = 0; while (x < 50) { me.data[x][y] = Square.Make(ReadChar()); if (me.data[x][y] == Robot) { me.robot = (x, y); } ++x; } SkipNewline(); ++y; } return var; } fn Move[ref self: Self](d: (i32, i32)) { var distance: i32 = 1; while (self.data[self.robot.0 + distance * d.0][self.robot.1 + distance * d.1] == Box) { ++distance; } if (self.data[self.robot.0 + distance * d.0][self.robot.1 + distance * d.1] == Empty) { self.data[self.robot.0][self.robot.1] = Empty; self.data[self.robot.0 + distance * d.0][self.robot.1 + distance * d.1] = Box; self.data[self.robot.0 + d.0][self.robot.1 + d.1] = Robot; self.robot.0 += d.0; self.robot.1 += d.1; } } fn Print[self: Self]() { var y: i32 = 0; while (y < 50) { var x: i32 = 0; while (x < 50) { Core.PrintChar(self.data[x][y] as char); ++x; } Core.PrintChar('\n'); ++y; } Core.PrintChar('\n'); } fn Signature[self: Self]() -> i32 { var s: i32 = 0; var y: i32 = 0; while (y < 50) { var x: i32 = 0; while (x < 50) { if (self.data[x][y] == Box) { s += y * 100 + x; } ++x; } ++y; } return s; } var data: array(array(Square, 50), 50); var robot: (i32, i32); } fn ReadAndExecuteActions(ref g: Grid) { while (true) { var m: CharOrEOF = ReadChar(); // To watch the progress, uncomment the following: // g.Print(); // Core.PrintChar(((m as i32) as u8) as char); // Core.PrintChar('\n'); // TODO: Use `match` once it's available. if (m == '^') { g.Move((0, -1)); } else if (m == '<') { g.Move((-1, 0)); } else if (m == '>') { g.Move((1, 0)); } else if (m == 'v') { g.Move((0, 1)); } else if (m == CharOrEOF.EOF()) { return; } } }