Added Solution for 2019 day 13

This commit is contained in:
Chris Alge 2023-03-12 20:53:18 +01:00
parent dd0de2a736
commit 72914e6246
6 changed files with 123 additions and 0 deletions

View file

@ -99,6 +99,17 @@ pub mod intcode_processor {
self.input.push_back(input);
}
/// Clears the input and sets it to `input`
pub fn reset_input(&mut self, input: RegVal) {
self.input.clear();
self.input.push_back(input);
}
/// Return the number of items left in the input queue
pub fn get_input_len(&self) -> usize {
self.input.len()
}
/// Get the value from memory address `address`.
///
/// ## Example

View file

@ -0,0 +1,9 @@
[package]
name = "day13_care_package"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
intcode_processor = { path = "../common/intcode_processor" }

View file

@ -0,0 +1,40 @@
As you ponder the solitude of space and the ever-increasing three-hour roundtrip for messages between you and Earth, you notice that the Space Mail Indicator Light is blinking. To help keep you sane, the Elves have sent you a care package.
It's a new game for the ship's [arcade cabinet](https://en.wikipedia.org/wiki/Arcade_cabinet)! Unfortunately, the arcade is *all the way* on the other end of the ship. Surely, it won't be hard to build your own - the care package even comes with schematics.
The arcade cabinet runs [Intcode](9) software like the game the Elves sent (your puzzle input). It has a primitive screen capable of drawing square *tiles* on a grid. The software draws tiles to the screen with output instructions: every three output instructions specify the `x` position (distance from the left), `y` position (distance from the top), and `tile id`. The `tile id` is interpreted as follows:
* `0` is an *empty* tile. No game object appears in this tile.
* `1` is a *wall* tile. Walls are indestructible barriers.
* `2` is a *block* tile. Blocks can be broken by the ball.
* `3` is a *horizontal paddle* tile. The paddle is indestructible.
* `4` is a *ball* tile. The ball moves diagonally and bounces off objects.
For example, a sequence of output values like `1,2,3,6,5,4` would draw a *horizontal paddle* tile (`1` tile from the left and `2` tiles from the top) and a *ball* tile (`6` tiles from the left and `5` tiles from the top).
Start the game. *How many block tiles are on the screen when the game exits?*
Your puzzle answer was `333`.
\--- Part Two ---
----------
The game didn't run because you didn't put in any quarters. Unfortunately, you did not bring any quarters. Memory address `0` represents the number of quarters that have been inserted; set it to `2` to play for free.
The arcade cabinet has a [joystick](https://en.wikipedia.org/wiki/Joystick) that can move left and right. The software reads the position of the joystick with input instructions:
* If the joystick is in the *neutral position*, provide `0`.
* If the joystick is *tilted to the left*, provide `-1`.
* If the joystick is *tilted to the right*, provide `1`.
The arcade cabinet also has a [segment display](https://en.wikipedia.org/wiki/Display_device#Segment_displays) capable of showing a single number that represents the player's current score. When three output instructions specify `X=-1, Y=0`, the third output instruction is not a tile; the value instead specifies the new score to show in the segment display. For example, a sequence of output values like `-1,0,12345` would show `12345` as the player's current score.
Beat the game by breaking all the blocks. *What is your score after the last block is broken?*
Your puzzle answer was `16539`.
Both parts of this puzzle are complete! They provide two gold stars: \*\*
At this point, you should [return to your Advent calendar](/2019) and try another puzzle.
If you still want to see it, you can [get your puzzle input](13/input).

View file

@ -0,0 +1,62 @@
use std::collections::HashMap;
use intcode_processor::intcode_processor::{Cpu, OutputState};
pub fn run(input: &str) -> (usize, isize) {
let mut cpu = Cpu::try_with_memory_from_str(input).unwrap();
let mut cpu_2 = cpu.clone();
let mut screen = HashMap::new();
let mut screen_2 = HashMap::new();
while let OutputState::Output(x) = cpu.run() {
if let OutputState::Output(y) = cpu.run() {
if let OutputState::Output(tile) = cpu.run() {
screen.insert((x, y), tile);
}
}
}
let first = screen.iter().filter(|(_coords, tile)| **tile == 2).count();
cpu_2.set(0, 2);
let second = play(&mut cpu_2, &mut screen_2);
(first, second)
}
fn play(cpu: &mut Cpu, screen: &mut HashMap<(isize, isize), isize>) -> isize {
let mut res = 0;
let mut ball_pos = 0;
let mut pad_pos = 0;
while let OutputState::Output(x) = cpu.run() {
if let OutputState::Output(y) = cpu.run() {
if let OutputState::Output(tile) = cpu.run() {
if x == -1 && y == 0 {
res = tile;
} else {
if tile == 4 {
ball_pos = x;
} else if tile == 3 {
pad_pos = x;
}
screen.insert((x, y), tile);
cpu.reset_input((ball_pos - pad_pos).signum());
}
}
}
}
res
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::read_to_string;
fn read_file(name: &str) -> String {
read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string()
}
#[test]
fn test_challenge() {
let challenge_input = read_file("tests/challenge_input");
assert_eq!(run(&challenge_input), (333, 16539));
}
}

File diff suppressed because one or more lines are too long