diff --git a/2021/day24_arithmetic_logic_unit/Cargo.toml b/2021/day24_arithmetic_logic_unit/Cargo.toml new file mode 100644 index 0000000..8a9a2dc --- /dev/null +++ b/2021/day24_arithmetic_logic_unit/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day24_arithmetic_logic_unit" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2021/day24_arithmetic_logic_unit/challenge.txt b/2021/day24_arithmetic_logic_unit/challenge.txt new file mode 100644 index 0000000..b1727cd --- /dev/null +++ b/2021/day24_arithmetic_logic_unit/challenge.txt @@ -0,0 +1,84 @@ +[Magic smoke](https://en.wikipedia.org/wiki/Magic_smoke) starts leaking from the submarine's [arithmetic logic unit](https://en.wikipedia.org/wiki/Arithmetic_logic_unit) (ALU). Without the ability to perform basic arithmetic and logic functions, the submarine can't produce cool patterns with its Christmas lights! + +It also can't navigate. Or run the oxygen system. + +Don't worry, though - you *probably* have enough oxygen left to give you enough time to build a new ALU. + +The ALU is a four-dimensional processing unit: it has integer variables `w`, `x`, `y`, and `z`. These variables all start with the value `0`. The ALU also supports *six instructions*: + +* `inp a` - Read an input value and write it to variable `a`. +* `add a b` - Add the value of `a` to the value of `b`, then store the result in variable `a`. +* `mul a b` - Multiply the value of `a` by the value of `b`, then store the result in variable `a`. +* `div a b` - Divide the value of `a` by the value of `b`, truncate the result to an integer, then store the result in variable `a`. (Here, "truncate" means to round the value toward zero.) +* `mod a b` - Divide the value of `a` by the value of `b`, then store the *remainder* in variable `a`. (This is also called the [modulo](https://en.wikipedia.org/wiki/Modulo_operation) operation.) +* `eql a b` - If the value of `a` and `b` are equal, then store the value `1` in variable `a`. Otherwise, store the value `0` in variable `a`. + +In all of these instructions, `a` and `b` are placeholders; `a` will always be the variable where the result of the operation is stored (one of `w`, `x`, `y`, or `z`), while `b` can be either a variable or a number. Numbers can be positive or negative, but will always be integers. + +The ALU has no *jump* instructions; in an ALU program, every instruction is run exactly once in order from top to bottom. The program halts after the last instruction has finished executing. + +(Program authors should be especially cautious; attempting to execute `div` with `b=0` or attempting to execute `mod` with `a<0` or `b<=0` will cause the program to crash and might even damage the ALU. These operations are never intended in any serious ALU program.) + +For example, here is an ALU program which takes an input number, negates it, and stores it in `x`: + +``` +inp x +mul x -1 + +``` + +Here is an ALU program which takes two input numbers, then sets `z` to `1` if the second input number is three times larger than the first input number, or sets `z` to `0` otherwise: + +``` +inp z +inp x +mul z 3 +eql z x + +``` + +Here is an ALU program which takes a non-negative integer as input, converts it into binary, and stores the lowest (1's) bit in `z`, the second-lowest (2's) bit in `y`, the third-lowest (4's) bit in `x`, and the fourth-lowest (8's) bit in `w`: + +``` +inp w +add z w +mod z 2 +div w 2 +add y w +mod y 2 +div w 2 +add x w +mod x 2 +div w 2 +mod w 2 + +``` + +Once you have built a replacement ALU, you can install it in the submarine, which will immediately resume what it was doing when the ALU failed: validating the submarine's *model number*. To do this, the ALU will run the MOdel Number Automatic Detector program (MONAD, your puzzle input). + +Submarine model numbers are always *fourteen-digit numbers* consisting only of digits `1` through `9`. The digit `0` *cannot* appear in a model number. + +When MONAD checks a hypothetical fourteen-digit model number, it uses fourteen separate `inp` instructions, each expecting a *single digit* of the model number in order of most to least significant. (So, to check the model number `13579246899999`, you would give `1` to the first `inp` instruction, `3` to the second `inp` instruction, `5` to the third `inp` instruction, and so on.) This means that when operating MONAD, each input instruction should only ever be given an integer value of at least `1` and at most `9`. + +Then, after MONAD has finished running all of its instructions, it will indicate that the model number was *valid* by leaving a `0` in variable `z`. However, if the model number was *invalid*, it will leave some other non-zero value in `z`. + +MONAD imposes additional, mysterious restrictions on model numbers, and legend says the last copy of the MONAD documentation was eaten by a [tanuki](https://en.wikipedia.org/wiki/Japanese_raccoon_dog). You'll need to *figure out what MONAD does* some other way. + +To enable as many submarine features as possible, find the largest valid fourteen-digit model number that contains no `0` digits. *What is the largest model number accepted by MONAD?* + +Your puzzle answer was `29991993698469`. + +\--- Part Two --- +---------- + +As the submarine starts booting up things like the [Retro Encabulator](https://www.youtube.com/watch?v=RXJKdh1KZ0w), you realize that maybe you don't need all these submarine features after all. + +*What is the smallest model number accepted by MONAD?* + +Your puzzle answer was `14691271141118`. + +Both parts of this puzzle are complete! They provide two gold stars: \*\* + +At this point, you should [return to your Advent calendar](/2021) and try another puzzle. + +If you still want to see it, you can [get your puzzle input](24/input). \ No newline at end of file diff --git a/2021/day24_arithmetic_logic_unit/src/lib.rs b/2021/day24_arithmetic_logic_unit/src/lib.rs new file mode 100644 index 0000000..d9627cd --- /dev/null +++ b/2021/day24_arithmetic_logic_unit/src/lib.rs @@ -0,0 +1,130 @@ +pub fn run() -> (usize, usize) { + let first = next_valid_input(1_000_000, false); + let second = next_valid_input(111_110, true); + (first, second) +} + +fn next_valid_input(previous: usize, ascending: bool) -> usize { + let mut curr = if ascending { + previous+1 + } else { + previous-1 + }; + let mut digits: Vec; + loop { + digits = Vec::new(); + let mut rest = curr; + while rest > 0 { + let digit = rest % 10; + if digit == 0 { + if ascending { + curr += 10_usize.pow(digits.len() as u32); + } else { + curr -= 10_usize.pow(digits.len() as u32); + } + digits = Vec::new(); + rest = curr; + } else { + digits.push(digit as isize); + rest /= 10; + } + } +// [0]=[13]-7 +// [1]=[12]+3 +// [2]=[11]+5 +// [3]=9 +// [4]=1 +// [5]=[10]+1 +// [6]=[7]+6 +// [8]=[9]-3 +// +// free: 13, 12, 11, 10, 9, 7 +// [13] = 0 +// [12] = 1 +// [11] = 2 +// [10] = 3 +// [9] = 4 +// [8] = 5 +// [7] = 6 + + let seven = digits.pop().unwrap(); + let next = digits[4] - 3; + if (1..10).contains(&next) { + digits.push(next); + } else { + if ascending { + curr += 1; + } else { + curr -= 1; + } + continue; + } + digits.push(seven); + let next = digits[6] + 6; + if (1..10).contains(&next) { + digits.push(next); + } else { + if ascending { + curr += 1; + } else { + curr -= 1; + } + continue; + } + let next = digits[3] + 1; + if (1..10).contains(&next) { + digits.push(next); + } else { + if ascending { + curr += 1; + } else { + curr -= 1; + } + continue; + } + digits.push(1); + digits.push(9); + let next = digits[2] + 5; + if (1..10).contains(&next) { + digits.push(next); + } else { + if ascending { + curr += 1; + } else { + curr -= 1; + } + continue; + } + let next = digits[1] + 3; + if (1..10).contains(&next) { + digits.push(next); + } else { + if ascending { + curr += 1; + } else { + curr -= 1; + } + continue; + } + let next = digits[0] - 7; + if (1..10).contains(&next) { + digits.push(next); + break; + } else if ascending { + curr += 1; + } else { + curr -= 1; + } + } + digits.iter().rev().fold(0, |acc, cur| 10*acc+ *cur as usize) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_challenge() { + assert_eq!(run(), (29991993698469, 14691271141118)); + } +} diff --git a/2021/day24_arithmetic_logic_unit/tests/challenge_input b/2021/day24_arithmetic_logic_unit/tests/challenge_input new file mode 100644 index 0000000..ea986df --- /dev/null +++ b/2021/day24_arithmetic_logic_unit/tests/challenge_input @@ -0,0 +1,252 @@ +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 15 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 9 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 11 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 1 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 10 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 11 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 12 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 3 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -11 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 10 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 11 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 5 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 14 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 0 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -6 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 7 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 1 +add x 10 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 9 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -6 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 15 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -6 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 4 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -16 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 10 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -4 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 4 +mul y x +add z y +inp w +mul x 0 +add x z +mod x 26 +div z 26 +add x -2 +eql x w +eql x 0 +mul y 0 +add y 25 +mul y x +add y 1 +mul z y +mul y 0 +add y w +add y 9 +mul y x +add z y