Compare commits
2 Commits
180faf92bb
...
master
Author | SHA1 | Date | |
---|---|---|---|
f2506f91ba | |||
46165b1acb |
190
input/year2023/day05.txt
Normal file
190
input/year2023/day05.txt
Normal file
@@ -0,0 +1,190 @@
|
||||
seeds: 2906961955 52237479 1600322402 372221628 2347782594 164705568 541904540 89745770 126821306 192539923 3411274151 496169308 919015581 8667739 654599767 160781040 3945616935 85197451 999146581 344584779
|
||||
|
||||
seed-to-soil map:
|
||||
2328388605 1716277852 240111965
|
||||
3183744888 3056742994 1057221520
|
||||
0 1574488136 141789716
|
||||
886579086 0 430196980
|
||||
141789716 2525350732 49125971
|
||||
881053613 1956389817 5525473
|
||||
3131936012 3013025394 43717600
|
||||
629464378 1322898901 251589235
|
||||
2568500570 1961915290 563435442
|
||||
190915687 2574476703 438548691
|
||||
3175653612 4113964514 8091276
|
||||
1435686684 430196980 892701921
|
||||
1316776066 4122055790 118910618
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 847324382 159395290
|
||||
1690371026 1633839702 81823607
|
||||
1942873068 561308539 283153025
|
||||
702170285 347687930 213620609
|
||||
477747447 1412279682 221560020
|
||||
1284811016 1006719672 253212372
|
||||
2226026093 170678435 177009495
|
||||
3187826244 2792977617 352243190
|
||||
4225283470 3206651416 69683826
|
||||
2970405965 3691658787 56026212
|
||||
1538023388 1259932044 152347638
|
||||
1772194633 0 170678435
|
||||
3540069434 3376298700 315360087
|
||||
159395290 2084683431 318352157
|
||||
915790894 1715663309 369020122
|
||||
2792977617 4117538948 177428348
|
||||
3026432177 3145220807 61430609
|
||||
699307467 844461564 2862818
|
||||
3855429521 3747684999 21637270
|
||||
3877066791 3769322269 348216679
|
||||
3087862786 3276335242 99963458
|
||||
|
||||
fertilizer-to-water map:
|
||||
1957494254 3160765597 68123328
|
||||
3668612865 2055686861 40068724
|
||||
435525860 0 215171709
|
||||
417459051 715121035 18066809
|
||||
3249874551 2634587998 121218972
|
||||
3537356195 3926770979 26944785
|
||||
409490069 215171709 7968982
|
||||
3247878798 2456653359 1995753
|
||||
152557237 570466650 62164110
|
||||
0 223140691 152557237
|
||||
3740494262 3322870672 151571624
|
||||
4127559328 2467180030 146770000
|
||||
2244919185 2003747275 51939586
|
||||
1782523793 2281682898 174970461
|
||||
829840892 2458649112 8530918
|
||||
3415930152 2819793210 9616809
|
||||
3451260386 2162555289 86095809
|
||||
650697569 632630760 82490275
|
||||
1725834205 787129181 30553919
|
||||
2298219434 2095755585 66799704
|
||||
4274329328 2613950030 20637968
|
||||
2025617582 4242693061 52274235
|
||||
3564300980 2248651098 31671137
|
||||
2296858771 2280322235 1360663
|
||||
3162226157 4125227747 85652641
|
||||
1564565599 1911070479 92676796
|
||||
3892065886 3691277537 235493442
|
||||
3371093523 1848297376 44836629
|
||||
1187663862 1437436130 376901737
|
||||
1689179378 2755806970 36654827
|
||||
2077891817 1238471779 167027368
|
||||
2365019138 2792461797 27331413
|
||||
2678412296 3953715764 63025182
|
||||
2741437478 817683100 420788679
|
||||
2461577055 3474442296 216835241
|
||||
787129181 3228888925 21340999
|
||||
3595972117 3250229924 72640748
|
||||
838371810 2829410019 331355578
|
||||
3425546961 4085967450 25713425
|
||||
1657242395 1405499147 31936983
|
||||
3708681589 4210880388 31812673
|
||||
1756388124 4111680875 13546872
|
||||
1169727388 1893134005 17936474
|
||||
2392350551 4016740946 69226504
|
||||
808470180 1826926664 21370712
|
||||
218943670 379920251 190546399
|
||||
214721347 375697928 4222323
|
||||
1769934996 1814337867 12588797
|
||||
|
||||
water-to-light map:
|
||||
3411019791 3038265544 83843899
|
||||
1902872961 1862724448 39203216
|
||||
3968365807 2753393749 138464731
|
||||
1729762115 1614300400 173110846
|
||||
3494863690 3122109443 473502117
|
||||
423365393 445887946 9248183
|
||||
2869853730 3595611560 11542547
|
||||
910597576 2054510840 169422772
|
||||
609563085 2589844190 163549559
|
||||
2522382340 1299215911 3599854
|
||||
2525982194 609563085 139503131
|
||||
131438599 455136129 141314541
|
||||
4106830538 3607154107 188136758
|
||||
2106420951 2290083024 299761166
|
||||
2406182117 966254850 82053377
|
||||
1157660094 1302815765 172746664
|
||||
97774358 248386611 33664241
|
||||
432613576 282050852 163837094
|
||||
2835557666 1794281538 34296064
|
||||
1953837775 2043524684 10986156
|
||||
1964823931 1901927664 141597020
|
||||
2881396277 749066216 217188634
|
||||
3404149499 1787411246 6870292
|
||||
1330406758 3795290865 240494284
|
||||
773112644 4035785149 137484932
|
||||
3282452284 4173270081 121697215
|
||||
2665485325 3001382926 36882618
|
||||
272753140 97774358 150612253
|
||||
0 38271406 59502952
|
||||
3098584911 1115348538 183867373
|
||||
1570901042 2938014447 31884700
|
||||
1942076177 1602538802 11761598
|
||||
2488235494 1828577602 34146846
|
||||
1080020348 2969899147 31483779
|
||||
1602785742 1475562429 126976373
|
||||
1111504127 2891858480 46155967
|
||||
2768517355 1048308227 67040311
|
||||
59502952 0 38271406
|
||||
2702367943 2223933612 66149412
|
||||
|
||||
light-to-temperature map:
|
||||
2325040309 318068442 41526915
|
||||
3863810956 4139509244 32531846
|
||||
3695021342 4093645836 45863408
|
||||
3176344157 3053768010 518677185
|
||||
2214303174 207331307 110737135
|
||||
1166404663 0 207331307
|
||||
3896342802 3761428671 206212717
|
||||
216675148 359595357 47363132
|
||||
4102555519 3967641388 126004448
|
||||
264038280 406958489 888098871
|
||||
4228559967 3572445195 66407329
|
||||
1152137151 1295057360 14267512
|
||||
3053768010 3638852524 122576147
|
||||
1373735970 1526000020 840567204
|
||||
0 1309324872 216675148
|
||||
3740884750 4172041090 122926206
|
||||
|
||||
temperature-to-humidity map:
|
||||
0 1391213880 85308204
|
||||
3458067104 3613119976 31521054
|
||||
1325453299 1240145095 151068785
|
||||
4139914424 3458067104 155052872
|
||||
1271510819 1186202615 53942480
|
||||
85308204 0 1186202615
|
||||
3489588158 3644641030 650326266
|
||||
|
||||
humidity-to-location map:
|
||||
167312469 2495357077 210182350
|
||||
1429747769 3808500825 68802537
|
||||
2550869359 1829966489 80945905
|
||||
1243007130 3610450429 186740639
|
||||
1735537822 990200552 68491638
|
||||
2426758858 2125855270 111895863
|
||||
1637338839 2027656287 98198983
|
||||
3109292740 3306673452 735862
|
||||
3647611593 2386885260 96257179
|
||||
3910495658 3919394548 32743716
|
||||
3860612665 3289982755 16690697
|
||||
3743868772 1910912394 116743893
|
||||
1498550306 2705539427 138788533
|
||||
0 1662654020 167312469
|
||||
2631815264 512723076 477477476
|
||||
836912419 1370893553 291760467
|
||||
2271993218 3307409314 154765640
|
||||
4136363029 3910495658 8898890
|
||||
377494819 3797191068 11309757
|
||||
1804029460 1058692190 209661300
|
||||
836150842 3517760656 761577
|
||||
3110028602 3518522233 91928196
|
||||
2538654721 2483142439 12214638
|
||||
687016715 2237751133 149134127
|
||||
3201956798 2844327960 445654795
|
||||
1128672886 1268353490 102540063
|
||||
2057482281 0 214510937
|
||||
388804576 214510937 298212139
|
||||
1231212949 3505966475 11794181
|
||||
2013690760 3462174954 43791521
|
||||
3943239374 3952138264 193123655
|
2
input/year2023/day06.txt
Normal file
2
input/year2023/day06.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Time: 51 92 68 90
|
||||
Distance: 222 2031 1126 1225
|
@@ -24,4 +24,6 @@ pub mod year2023 {
|
||||
pub mod day02;
|
||||
pub mod day03;
|
||||
pub mod day04;
|
||||
pub mod day05;
|
||||
pub mod day06;
|
||||
}
|
||||
|
@@ -12,8 +12,8 @@ struct Solution {
|
||||
macro_rules! solution {
|
||||
($year:tt, $day:tt) => {
|
||||
Solution {
|
||||
year: (&stringify!($year)).parse_u32(),
|
||||
day: (&stringify!($day)).parse_u32(),
|
||||
year: (&stringify!($year)).parse_unsigned::<u32>(),
|
||||
day: (&stringify!($day)).parse_unsigned::<u32>(),
|
||||
input: include_str!(concat![
|
||||
"../input/",
|
||||
stringify!($year),
|
||||
@@ -38,7 +38,7 @@ macro_rules! solution {
|
||||
fn main() {
|
||||
let (year, day) = match std::env::args().nth(1) {
|
||||
Some(arg) => {
|
||||
let mut split = arg.split("::").map(|s| s.parse_u32());
|
||||
let mut split = arg.split("::").map(|s| s.parse_unsigned());
|
||||
(split.next(), split.next())
|
||||
}
|
||||
None => (None, None),
|
||||
@@ -99,5 +99,7 @@ fn year2023() -> Vec<Solution> {
|
||||
solution!(year2023, day02),
|
||||
solution!(year2023, day03),
|
||||
solution!(year2023, day04),
|
||||
solution!(year2023, day05),
|
||||
solution!(year2023, day06),
|
||||
]
|
||||
}
|
||||
|
@@ -1,74 +1,133 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::str::Bytes;
|
||||
|
||||
pub struct U32s<'a> {
|
||||
pub trait IsSigned {}
|
||||
|
||||
impl IsSigned for i8 {}
|
||||
impl IsSigned for i16 {}
|
||||
impl IsSigned for i32 {}
|
||||
impl IsSigned for i64 {}
|
||||
impl IsSigned for i128 {}
|
||||
impl IsSigned for isize {}
|
||||
|
||||
pub trait IsUnsigned {}
|
||||
|
||||
impl IsUnsigned for u8 {}
|
||||
impl IsUnsigned for u16 {}
|
||||
impl IsUnsigned for u32 {}
|
||||
impl IsUnsigned for u64 {}
|
||||
impl IsUnsigned for u128 {}
|
||||
impl IsUnsigned for usize {}
|
||||
|
||||
pub struct Signed<'a, T = i64>
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<i32> + TryFrom<u8> + IsSigned,
|
||||
{
|
||||
bytes: Bytes<'a>,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for U32s<'a> {
|
||||
type Item = u32;
|
||||
impl<'a, T> Iterator for Signed<'a, T>
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<i32> + TryFrom<u8> + IsSigned,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
try_parse_u32(&mut self.bytes)
|
||||
try_parse_signed::<T>(&mut self.bytes)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct I32s<'a> {
|
||||
pub struct Unsigned<'a, T = u64>
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<u8> + IsUnsigned,
|
||||
{
|
||||
bytes: Bytes<'a>,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for I32s<'a> {
|
||||
type Item = i32;
|
||||
impl<'a, T> Iterator for Unsigned<'a, T>
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<u8> + IsUnsigned,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
try_parse_i32(&mut self.bytes)
|
||||
try_parse_unsigned::<T>(&mut self.bytes)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ParseExt {
|
||||
fn parse_u32(&self) -> u32;
|
||||
fn parse_signed<T>(&self) -> T
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<i32> + TryFrom<u8> + IsSigned;
|
||||
|
||||
fn u32s(&self) -> U32s<'_>;
|
||||
fn parse_unsigned<T>(&self) -> T
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<u8> + IsUnsigned;
|
||||
|
||||
fn parse_i32(&self) -> i32;
|
||||
fn signed<T>(&self) -> Signed<'_, T>
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<i32> + TryFrom<u8> + IsSigned;
|
||||
|
||||
fn i32s(&self) -> I32s<'_>;
|
||||
fn unsigned<T>(&self) -> Unsigned<'_, T>
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<u8> + IsUnsigned;
|
||||
}
|
||||
|
||||
impl ParseExt for &str {
|
||||
fn parse_u32(&self) -> u32 {
|
||||
match try_parse_u32(&mut self.bytes()) {
|
||||
Some(num) => num,
|
||||
None => panic!("unable to parse u32: {self}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn u32s(&self) -> U32s<'_> {
|
||||
U32s {
|
||||
fn signed<T>(&self) -> Signed<'_, T>
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<i32> + TryFrom<u8> + IsSigned,
|
||||
{
|
||||
Signed {
|
||||
bytes: self.bytes(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_i32(&self) -> i32 {
|
||||
match try_parse_i32(&mut self.bytes()) {
|
||||
fn parse_signed<T>(&self) -> T
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<i32> + TryFrom<u8> + IsSigned,
|
||||
{
|
||||
match try_parse_signed(&mut self.bytes()) {
|
||||
Some(num) => num,
|
||||
None => panic!("unable to parse i32: {self}"),
|
||||
None => panic!("unable to parse signed: {self}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn i32s(&self) -> I32s<'_> {
|
||||
I32s {
|
||||
fn unsigned<T>(&self) -> Unsigned<'_, T>
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<u8> + IsUnsigned,
|
||||
{
|
||||
Unsigned {
|
||||
bytes: self.bytes(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_unsigned<T>(&self) -> T
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<u8> + IsUnsigned,
|
||||
{
|
||||
match try_parse_unsigned(&mut self.bytes()) {
|
||||
Some(num) => num,
|
||||
None => panic!("unable to parse signed: {self}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_parse_u32(bytes: &mut Bytes<'_>) -> Option<u32> {
|
||||
use std::ops::{Add, Mul};
|
||||
fn try_parse_unsigned<T>(bytes: &mut Bytes<'_>) -> Option<T>
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<u8> + IsUnsigned,
|
||||
{
|
||||
let mut n = loop {
|
||||
let byte = bytes.next()?;
|
||||
let digit = byte.wrapping_sub(b'0');
|
||||
|
||||
if digit < 10 {
|
||||
break digit as u32;
|
||||
break T::try_from(digit).unwrap_or_else(|_| unreachable!());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -79,29 +138,33 @@ fn try_parse_u32(bytes: &mut Bytes<'_>) -> Option<u32> {
|
||||
let digit = byte.wrapping_sub(b'0');
|
||||
|
||||
if digit < 10 {
|
||||
n = 10 * n + digit as u32;
|
||||
n = T::try_from(10).unwrap_or_else(|_| unreachable!()) * n
|
||||
+ T::try_from(digit).unwrap_or_else(|_| unreachable!());
|
||||
} else {
|
||||
break Some(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_parse_i32(bytes: &mut Bytes<'_>) -> Option<i32> {
|
||||
let mut fac = 1;
|
||||
fn try_parse_signed<T>(bytes: &mut Bytes<'_>) -> Option<T>
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + TryFrom<i32> + TryFrom<u8> + IsSigned,
|
||||
{
|
||||
let mut fac = T::try_from(1i32).unwrap_or_else(|_| unreachable!());
|
||||
let mut n = loop {
|
||||
let byte = bytes.next()?;
|
||||
if byte == b'-' {
|
||||
let byte = bytes.next()?;
|
||||
let digit = byte.wrapping_sub(b'0');
|
||||
if digit < 10 {
|
||||
fac = -1;
|
||||
break digit as i32;
|
||||
fac = T::try_from(-1i32).unwrap_or_else(|_| unreachable!());
|
||||
break T::try_from(digit).unwrap_or_else(|_| unreachable!());
|
||||
}
|
||||
}
|
||||
let digit = byte.wrapping_sub(b'0');
|
||||
|
||||
if digit < 10 {
|
||||
break digit as i32;
|
||||
break T::try_from(digit).unwrap_or_else(|_| unreachable!());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -112,7 +175,8 @@ fn try_parse_i32(bytes: &mut Bytes<'_>) -> Option<i32> {
|
||||
let digit = byte.wrapping_sub(b'0');
|
||||
|
||||
if digit < 10 {
|
||||
n = 10 * n + digit as i32;
|
||||
n = T::try_from(10).unwrap_or_else(|_| unreachable!()) * n
|
||||
+ T::try_from(digit).unwrap_or_else(|_| unreachable!());
|
||||
} else {
|
||||
break Some(n * fac);
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ use crate::util::{index::*, parse::ParseExt};
|
||||
|
||||
fn parse(input: &str) -> impl Iterator<Item = (u8, u32)> + '_ {
|
||||
let dirs = input.bytes().filter(u8::is_ascii_uppercase);
|
||||
let steps: Vec<_> = input.u32s().collect();
|
||||
let steps: Vec<_> = input.unsigned().collect();
|
||||
|
||||
dirs.zip(steps)
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ pub fn part1(input: &str) -> impl std::fmt::Display {
|
||||
input
|
||||
.lines()
|
||||
.map(|s| {
|
||||
s.u32s()
|
||||
s.unsigned()
|
||||
// This is faster than `collect().try_into().expect("")`
|
||||
// presumably because of the allocation of the Vec
|
||||
// and the additional check for the Option for each line
|
||||
@@ -33,9 +33,9 @@ pub fn part2(input: &str) -> impl std::fmt::Display {
|
||||
let mut valid = 0;
|
||||
|
||||
while let Some((l1, l2, l3)) = get3(&mut lines) {
|
||||
let l1: Vec<u32> = l1.u32s().collect();
|
||||
let l2: Vec<u32> = l2.u32s().collect();
|
||||
let l3: Vec<u32> = l3.u32s().collect();
|
||||
let l1: Vec<u32> = l1.unsigned().collect();
|
||||
let l2: Vec<u32> = l2.unsigned().collect();
|
||||
let l3: Vec<u32> = l3.unsigned().collect();
|
||||
for i in 0..2 {
|
||||
if valid_triangle(&[l1[i], l2[i], l3[i]]) {
|
||||
valid += 1;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
use crate::util::parse::ParseExt;
|
||||
|
||||
fn calories(input: &str) -> impl Iterator<Item = u32> + '_ {
|
||||
input.split("\n\n").map(|set| set.u32s().sum())
|
||||
input.split("\n\n").map(|set| set.unsigned::<u32>().sum())
|
||||
}
|
||||
|
||||
pub fn part1(input: &str) -> impl std::fmt::Display {
|
||||
|
@@ -4,7 +4,7 @@ fn solve(input: &str, filter: fn(u32, u32, u32, u32) -> bool) -> usize {
|
||||
input
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
let mut nums = line.u32s();
|
||||
let mut nums = line.unsigned::<u32>();
|
||||
|
||||
if (filter)(nums.next()?, nums.next()?, nums.next()?, nums.next()?) {
|
||||
Some(())
|
||||
|
@@ -2,7 +2,7 @@ use crate::util::parse::ParseExt;
|
||||
|
||||
fn parse(input: &str) -> Option<(Vec<Vec<char>>, impl Iterator<Item = [u32; 3]> + '_)> {
|
||||
let (board, moveset) = input.split_once("\n\n")?;
|
||||
let size = board.lines().last()?.u32s().count();
|
||||
let size = board.lines().last()?.unsigned::<u32>().count();
|
||||
let mut crates: Vec<Vec<char>> = vec![vec![]; size + 1];
|
||||
|
||||
board.lines().for_each(|line| {
|
||||
@@ -22,7 +22,7 @@ fn parse(input: &str) -> Option<(Vec<Vec<char>>, impl Iterator<Item = [u32; 3]>
|
||||
}
|
||||
|
||||
let moves = moveset.lines().filter_map(|line| {
|
||||
let mut nums = line.u32s();
|
||||
let mut nums = line.unsigned();
|
||||
Some([nums.next()?, nums.next()?, nums.next()?])
|
||||
});
|
||||
|
||||
|
@@ -18,7 +18,7 @@ pub fn part1(input: &str) -> impl std::fmt::Display {
|
||||
|
||||
for b in draw.split(", ") {
|
||||
let (num, col) = b.split_once(' ')?;
|
||||
let num = num.parse_u32();
|
||||
let num = num.parse_unsigned::<u32>();
|
||||
match col {
|
||||
"red" => red += num,
|
||||
"green" => green += num,
|
||||
@@ -47,7 +47,7 @@ pub fn part2(input: &str) -> impl std::fmt::Display {
|
||||
for draw in cubes.split("; ") {
|
||||
for b in draw.split(", ") {
|
||||
let (num, col) = b.split_once(' ')?;
|
||||
let num = num.parse_u32();
|
||||
let num = num.parse_unsigned::<u32>();
|
||||
|
||||
match col {
|
||||
"red" => {
|
||||
|
@@ -6,8 +6,8 @@ pub fn part1(input: &str) -> impl std::fmt::Display {
|
||||
.map(|line| {
|
||||
let (_, rest) = line.split_once(':').unwrap();
|
||||
let (winning, numbers) = rest.split_once('|').unwrap();
|
||||
let winning = winning.u32s().collect::<Vec<_>>();
|
||||
let numbers = numbers.u32s().filter(|n| winning.contains(n)).count() as u32;
|
||||
let winning = winning.unsigned::<u32>().collect::<Vec<_>>();
|
||||
let numbers = numbers.unsigned::<u32>().filter(|n| winning.contains(n)).count() as u32;
|
||||
(numbers > 0).then(|| 2u32.pow(numbers - 1)).unwrap_or(0)
|
||||
})
|
||||
.sum::<u32>()
|
||||
@@ -24,8 +24,8 @@ pub fn part2(input: &str) -> impl std::fmt::Display {
|
||||
.map(|(i, line)| {
|
||||
let (_, rest) = line.split_once(':').unwrap();
|
||||
let (winning, numbers) = rest.split_once('|').unwrap();
|
||||
let winning = winning.u32s().collect::<Vec<_>>();
|
||||
let numbers = numbers.u32s().filter(|n| winning.contains(n)).count();
|
||||
let winning = winning.unsigned::<u32>().collect::<Vec<_>>();
|
||||
let numbers = numbers.unsigned::<u32>().filter(|n| winning.contains(n)).count();
|
||||
let mul = mults[i];
|
||||
mults
|
||||
.iter_mut()
|
||||
|
151
src/year2023/day05.rs
Normal file
151
src/year2023/day05.rs
Normal file
@@ -0,0 +1,151 @@
|
||||
use crate::util::parse::ParseExt;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Map {
|
||||
tuples: Vec<(usize, usize, usize)>,
|
||||
}
|
||||
|
||||
impl Map {
|
||||
// We divide the seed range up into smaller seed ranges:
|
||||
// 1) seed range before map range
|
||||
// 2) seed range after map range
|
||||
// 3) seed range in map range
|
||||
// for the seed range inside the map range we map it and it to the result array
|
||||
// the before and after seed ranges will be saved for the next map where. apply again
|
||||
// rinse and repeat until the ranges are empty
|
||||
fn calc_range(&self, mut ranges: Vec<(usize, usize)>) -> Vec<(usize, usize)> {
|
||||
let mut mapped = vec![];
|
||||
for (dest, source, l) in &self.tuples {
|
||||
let mut todo = vec![];
|
||||
|
||||
while let Some((range_start, range_end)) = ranges.pop() {
|
||||
let before_range = (range_start, range_end.min(*source));
|
||||
if before_range.1 > before_range.0 {
|
||||
todo.push(before_range);
|
||||
}
|
||||
let after_range = ((*source + l).max(range_start), range_end);
|
||||
if after_range.1 > after_range.0 {
|
||||
todo.push(after_range);
|
||||
}
|
||||
let between_range = (range_start.max(*source), (*source + *l).min(range_end));
|
||||
if between_range.1 > between_range.0 {
|
||||
mapped.push((
|
||||
between_range.0 - source + dest,
|
||||
between_range.1 - source + dest,
|
||||
));
|
||||
}
|
||||
}
|
||||
ranges = todo;
|
||||
}
|
||||
mapped.extend(ranges);
|
||||
mapped
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(input: &str) -> (Vec<usize>, Vec<Map>) {
|
||||
let mut chunks = input.split("\n\n");
|
||||
let seeds = chunks
|
||||
.next()
|
||||
.unwrap()
|
||||
.unsigned::<usize>()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let maps = chunks
|
||||
.map(|chunk| Map {
|
||||
tuples: chunk
|
||||
.lines()
|
||||
.enumerate()
|
||||
.filter_map(|(idx, line)| {
|
||||
if idx == 0 {
|
||||
return None;
|
||||
}
|
||||
let mut nums = line.unsigned::<usize>();
|
||||
Some((nums.next()?, nums.next()?, nums.next()?))
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
(seeds, maps)
|
||||
}
|
||||
|
||||
pub fn part1(input: &str) -> impl std::fmt::Display {
|
||||
let (mut seeds, maps) = parse(input);
|
||||
|
||||
for seed in seeds.iter_mut() {
|
||||
for map in &maps {
|
||||
for (dest, source, l) in &map.tuples {
|
||||
// if seed is within range map it in-place else leave it
|
||||
if *seed >= *source && *seed < *source + *l {
|
||||
*seed = *seed + *dest - *source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
seeds.sort();
|
||||
seeds[0]
|
||||
}
|
||||
|
||||
pub fn part2(input: &str) -> impl std::fmt::Display {
|
||||
let (seeds, maps) = parse(input);
|
||||
let seeds = seeds.chunks(2).map(|v| (v[0], v[1]));
|
||||
|
||||
let mut res = seeds
|
||||
.map(|(start, end)| {
|
||||
let mut ranges = maps
|
||||
.iter()
|
||||
.fold(vec![(start, start + end)], |acc, map| map.calc_range(acc));
|
||||
ranges.sort();
|
||||
// We want the lowest, so take lower end of range
|
||||
ranges[0].0
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
res.sort();
|
||||
res[0]
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
static TEST_INPUT: &str = "seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 15 37
|
||||
37 52 2
|
||||
39 0 15
|
||||
|
||||
fertilizer-to-water map:
|
||||
49 53 8
|
||||
0 11 42
|
||||
42 0 7
|
||||
57 7 4
|
||||
|
||||
water-to-light map:
|
||||
88 18 7
|
||||
18 25 70
|
||||
|
||||
light-to-temperature map:
|
||||
45 77 23
|
||||
81 45 19
|
||||
68 64 13
|
||||
|
||||
temperature-to-humidity map:
|
||||
0 69 1
|
||||
1 0 69
|
||||
|
||||
humidity-to-location map:
|
||||
60 56 37
|
||||
56 93 4";
|
||||
|
||||
#[test]
|
||||
fn test_part1() {
|
||||
assert_eq!("35", part1(TEST_INPUT).to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2() {
|
||||
assert_eq!("46", part2(TEST_INPUT).to_string())
|
||||
}
|
49
src/year2023/day06.rs
Normal file
49
src/year2023/day06.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use crate::util::parse::ParseExt;
|
||||
|
||||
pub fn part1(input: &str) -> impl std::fmt::Display {
|
||||
let mut lines = input.lines();
|
||||
let times = lines.next().unwrap();
|
||||
let dists = lines.next().unwrap();
|
||||
|
||||
times
|
||||
.signed::<i32>()
|
||||
.zip(dists.signed())
|
||||
.map(|(lim, dist)| {
|
||||
(0..dist)
|
||||
.filter_map(|d| (d * (lim - d) > dist).then_some(1))
|
||||
.sum::<u32>()
|
||||
})
|
||||
.product::<u32>()
|
||||
}
|
||||
|
||||
pub fn part2(input: &str) -> impl std::fmt::Display {
|
||||
let mut lines = input.lines();
|
||||
let time = lines
|
||||
.next()
|
||||
.unwrap()
|
||||
.chars()
|
||||
.filter(|a| a.is_ascii_digit())
|
||||
.collect::<String>().as_str()
|
||||
.parse_signed::<i128>();
|
||||
let dist = lines
|
||||
.next()
|
||||
.unwrap()
|
||||
.chars()
|
||||
.filter(|a| a.is_ascii_digit())
|
||||
.collect::<String>().as_str()
|
||||
.parse_signed::<i128>();
|
||||
|
||||
(0..time)
|
||||
.filter_map(|d| (d * (time - d) > dist).then_some(1))
|
||||
.sum::<i128>()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part1() {
|
||||
assert_eq!("", part1("").to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2() {
|
||||
assert_eq!("", part2("").to_string())
|
||||
}
|
Reference in New Issue
Block a user