From a2cafe726caf512519b8728f9325d5af695318da Mon Sep 17 00:00:00 2001 From: Ishan Jain Date: Fri, 17 Dec 2021 12:25:46 +0530 Subject: [PATCH] Added Day 17 Part 1 --- inputs/input.txt | 2 +- inputs/sample.txt | 2 +- src/main.rs | 227 ++++++++++++---------------------------------- 3 files changed, 58 insertions(+), 173 deletions(-) diff --git a/inputs/input.txt b/inputs/input.txt index bbdc39b..e6711eb 100644 --- a/inputs/input.txt +++ b/inputs/input.txt @@ -1 +1 @@ -820D4A801EE00720190CA005201682A00498014C04BBB01186C040A200EC66006900C44802BA280104021B30070A4016980044C800B84B5F13BFF007081800FE97FDF830401BF4A6E239A009CCE22E53DC9429C170013A8C01E87D102399803F1120B4632004261045183F303E4017DE002F3292CB04DE86E6E7E54100366A5490698023400ABCC59E262CFD31DDD1E8C0228D938872A472E471FC80082950220096E55EF0012882529182D180293139E3AC9A00A080391563B4121007223C4A8B3279B2AA80450DE4B72A9248864EAB1802940095CDE0FA4DAA5E76C4E30EBE18021401B88002170BA0A43000043E27462829318F83B00593225F10267FAEDD2E56B0323005E55EE6830C013B00464592458E52D1DF3F97720110258DAC0161007A084228B0200DC568FB14D40129F33968891005FBC00E7CAEDD25B12E692A7409003B392EA3497716ED2CFF39FC42B8E593CC015B00525754B7DFA67699296DD018802839E35956397449D66997F2013C3803760004262C4288B40008747E8E114672564E5002256F6CC3D7726006125A6593A671A48043DC00A4A6A5B9EAC1F352DCF560A9385BEED29A8311802B37BE635F54F004A5C1A5C1C40279FDD7B7BC4126ED8A4A368994B530833D7A439AA1E9009D4200C4178FF0880010E8431F62C880370F63E44B9D1E200ADAC01091029FC7CB26BD25710052384097004677679159C02D9C9465C7B92CFACD91227F7CD678D12C2A402C24BF37E9DE15A36E8026200F4668AF170401A8BD05A242009692BFC708A4BDCFCC8A4AC3931EAEBB3D314C35900477A0094F36CF354EE0CCC01B985A932D993D87E2017CE5AB6A84C96C265FA750BA4E6A52521C300467033401595D8BCC2818029C00AA4A4FBE6F8CB31CAE7D1CDDAE2E9006FD600AC9ED666A6293FAFF699FC168001FE9DC5BE3B2A6B3EED060 +target area: x=124..174, y=-123..-86 diff --git a/inputs/sample.txt b/inputs/sample.txt index 0a1278e..a07e02d 100644 --- a/inputs/sample.txt +++ b/inputs/sample.txt @@ -1 +1 @@ -A0016C880162017C3686B18A3D4780 +target area: x=20..30, y=-10..-5 diff --git a/src/main.rs b/src/main.rs index 154eee9..4b70d2c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,200 +1,84 @@ #![feature(test)] + +use std::ops::RangeInclusive; extern crate test; -use bitvec::{order::Msb0, view::BitView}; - -type BitSlice<'a> = &'a bitvec::slice::BitSlice; - const INPUTS: [&'static str; 2] = [ include_str!("../inputs/sample.txt"), include_str!("../inputs/input.txt"), ]; -#[derive(Debug)] -struct PacketHeader { - version: u8, - type_id: u8, +fn parse(input: &'static str) -> (RangeInclusive, RangeInclusive) { + let input = input.trim(); + let input = input.trim_start_matches("target area: "); + + let (x, y) = input.split_once(", ").unwrap(); + + let x = x.trim_start_matches("x="); + let y = y.trim_start_matches("y="); + + let (sx, ex) = x + .split_once("..") + .map(|(a, b)| (a.parse::().unwrap(), b.parse::().unwrap())) + .unwrap(); + let (sy, ey) = y + .split_once("..") + .map(|(a, b)| (a.parse::().unwrap(), b.parse::().unwrap())) + .unwrap(); + + (sx..=ex, sy..=ey) } -#[derive(Debug)] -struct Packet { - header: PacketHeader, - size: u64, - literal: Option, - sub_packets: Vec, -} +fn check( + mut vx: i32, + mut vy: i32, + (tx, ty): (RangeInclusive, RangeInclusive), +) -> Option { + let mut sx = 0; + let mut sy = 0; + let mut y_max = 0; -impl Packet { - fn new(input: &'static str) -> Self { - let out = hex::decode(input).unwrap(); - - let mut bvec: BitSlice = BitView::view_bits(out.as_slice()); - - Self::parse(&mut bvec) - } - - fn read_literal(ip: &mut BitSlice) -> (u64, u64) { - let mut out = 0; - let mut read = 0; - - loop { - let (word, remaining) = ip.split_at(5); - *ip = remaining; - read += 5; - - out = out << 4 | read_as_u8(&word[1..]) as u64; - - if !*word.first().unwrap() { - break; - } + loop { + if vx == 0 && sy < *ty.start() { + return None; } - (out, read) - } + if tx.contains(&sx) && ty.contains(&sy) { + return Some(y_max); + } - fn read_header(ip: &mut BitSlice) -> (u8, u8) { - (take_u8(ip, 3), take_u8(ip, 3)) - } + sx += vx; + sy += vy; - fn parse(input: &mut BitSlice) -> Packet { - let (version, type_id) = Self::read_header(input); + y_max = y_max.max(sy); - let mut out = Packet { - size: 6, - literal: None, - header: PacketHeader { version, type_id }, - sub_packets: vec![], + vy -= 1; + vx -= if vx > 0 { + 1 + } else if vx < 0 { + -1 + } else { + 0 }; - - match type_id { - // Literal - 4 => { - let (literal, read) = Self::read_literal(input); - - out.size += read; - out.literal = Some(literal); - } - - // Operation - _ => { - let length_type_id = take_u8(input, 1); - out.size += 1; - - match length_type_id { - 0 => { - let mut trailing_packet_size = take_u64(input, 15); - out.size += 15; - - while trailing_packet_size > 0 { - let packet = Self::parse(input); - - trailing_packet_size -= packet.size; - out.size += packet.size; - out.sub_packets.push(packet); - } - } - - 1 => { - let trailing_packet_count = take_u64(input, 11); - out.size += 11; - - for _ in 0..trailing_packet_count { - let packet = Self::parse(input); - out.size += packet.size; - out.sub_packets.push(packet); - } - } - _ => unreachable!(), - } - } - }; - out } +} - fn value(&self) -> u64 { - match self.header.type_id { - 0 => self.sub_packets.iter().fold(0, |a, x| a + x.value()), - 1 => self.sub_packets.iter().fold(1, |a, x| a * x.value()), - 2 => self.sub_packets.iter().map(|x| x.value()).min().unwrap(), - 3 => self.sub_packets.iter().map(|x| x.value()).max().unwrap(), - 4 => self.literal.unwrap(), - 5 => { - let value1 = self.sub_packets[0].value(); - let value2 = self.sub_packets[1].value(); - - if value1 > value2 { - 1 - } else { - 0 - } +fn solution((xr, yr): (RangeInclusive, RangeInclusive)) -> i32 { + let mut y_max = 0; + for x in 0..250 { + for y in -250..=250 { + if let Some(lymax) = check(x, y, (xr.clone(), yr.clone())) { + y_max = y_max.max(lymax); } - 6 => { - let value1 = self.sub_packets[0].value(); - let value2 = self.sub_packets[1].value(); - - if value1 < value2 { - 1 - } else { - 0 - } - } - 7 => { - let value1 = self.sub_packets[0].value(); - let value2 = self.sub_packets[1].value(); - - if value1 == value2 { - 1 - } else { - 0 - } - } - _ => unreachable!(), } } -} -fn take_u8(ip: &mut BitSlice, offset: usize) -> u8 { - let (num, left) = ip.split_at(offset); - *ip = left; - - read_as_u8(num) -} - -fn take_u64(ip: &mut BitSlice, offset: usize) -> u64 { - let (num, left) = ip.split_at(offset); - *ip = left; - - read_as_u64(num) -} - -fn read_as_u64(ip: BitSlice) -> u64 { - let mut out = 0; - - for bit in ip { - out = out << 1 | if *bit { 1 } else { 0 }; - } - - out -} - -fn read_as_u8(ip: BitSlice) -> u8 { - let mut out = 0; - - for bit in ip { - out = out << 1 | if *bit { 1 } else { 0 }; - } - - out -} - -fn solution(input: &'static str) -> u64 { - let packet = Packet::new(input.trim()); - - packet.value() + y_max } fn main() { for input in INPUTS { + let input = parse(input); let result = solution(input); println!("Result = {}", result); } @@ -202,8 +86,9 @@ fn main() { #[bench] fn solution_bench(b: &mut test::Bencher) { + let input = parse(INPUTS[1]); b.iter(|| { - let result = solution(INPUTS[1]); + let result = solution(input.clone()); test::black_box(result); }) }