This commit is contained in:
Dory 2024-03-22 20:46:10 -07:00
parent 43ec9c7d2f
commit e39887f0c2
2 changed files with 105 additions and 24 deletions

View File

@ -1,4 +1,5 @@
use std::env; use std::env;
use std::cmp::Ordering;
use std::fs::File; use std::fs::File;
use std::io::{BufReader, BufRead}; use std::io::{BufReader, BufRead};
@ -17,40 +18,43 @@ fn parse_num(s: &[u8]) -> (u64, usize) {
} }
// Assuming no malformed input // Assuming no malformed input
fn is_in_order(left: &[u8], right: &[u8]) -> bool { fn compare(left: &[u8], right: &[u8]) -> Ordering {
//println!(">> {:?}, {:?} -- {:?}", str::from_utf8(left), str::from_utf8(right));
if left.len() == 0 { if left.len() == 0 {
return true; return Ordering::Less;
} }
if right.len() == 0 { if right.len() == 0 {
return false; return Ordering::Greater;
} }
let (l, r) = (left[0], right[0]); let (l, r) = (left[0], right[0]);
if l == b',' && r == b',' { if l == b',' && r == b',' {
is_in_order(&left[1..], &right[1..]) compare(&left[1..], &right[1..])
} else if l == b'[' && r == b'[' { } else if l == b'[' && r == b'[' {
is_in_order(&left[1..], &right[1..]) compare(&left[1..], &right[1..])
} else if l == b']' && r == b']' { } else if l == b']' && r == b']' {
is_in_order(&left[1..], &right[1..]) compare(&left[1..], &right[1..])
} else if l == b']' { } else if l == b']' {
true Ordering::Less
} else if r == b']' { } else if r == b']' {
false Ordering::Greater
} else if l == b'[' { } else if l == b'[' {
let (num, len) = parse_num(right); let (num, len) = parse_num(right);
is_in_order(&left, &[b"[", num.to_string().as_bytes(), b"]", &right[len..]].concat()) compare(
&left,
&[b"[", num.to_string().as_bytes(), b"]", &right[len..]].concat())
} else if r == b'[' { } else if r == b'[' {
let (num, len) = parse_num(left); let (num, len) = parse_num(left);
is_in_order(&[b"[", num.to_string().as_bytes(), b"]", &left[len..]].concat(), &right) compare(
&[b"[", num.to_string().as_bytes(), b"]", &left[len..]].concat(),
&right)
} else { } else {
let (lnum, llen) = parse_num(left); let (lnum, llen) = parse_num(left);
let (rnum, rlen) = parse_num(right); let (rnum, rlen) = parse_num(right);
if lnum < rnum { if lnum < rnum {
true Ordering::Less
} else if lnum > rnum { } else if lnum > rnum {
false Ordering::Greater
} else { } else {
is_in_order(&left[llen..], &right[rlen..]) compare(&left[llen..], &right[rlen..])
} }
} }
@ -58,17 +62,20 @@ fn is_in_order(left: &[u8], right: &[u8]) -> bool {
fn main() { fn main() {
let file = File::open(&env::args().nth(1).expect("input")).expect("io err"); let file = File::open(&env::args().nth(1).expect("input")).expect("io err");
let lines: Vec<String> = BufReader::new(file).lines().flatten().collect(); let mut lines: Vec<_> = BufReader::new(file).lines().flatten()
// TODO: array_chunks() for lazy iter? .filter(|line| line != "").collect();
let blocks: Vec<_> = lines.chunks(3).collect(); lines.push(String::from("[[2]]"));
lines.push(String::from("[[6]]"));
lines.sort_unstable_by(|s1, s2| compare(s1.as_bytes(), s2.as_bytes()));
let mut sum = 0; let (mut six, mut two): (usize, usize) = (0, 0);
for (i, block) in blocks.iter().enumerate() { for (i, line) in lines.iter().enumerate() {
// TODO: return error here instead of assert? if line == "[[6]]" {
assert!((block.len() == 3 && block[2] == "") || block.len() == 2); six = i + 1;
if is_in_order(block[0].as_bytes(), block[1].as_bytes()) { }
sum += i + 1; if line == "[[2]]" {
two = i + 1;
} }
} }
println!("Answer: {:?}", sum); println!("{:?}", six*two);
} }

74
day13/src/main1.rs Normal file
View File

@ -0,0 +1,74 @@
use std::env;
use std::fs::File;
use std::io::{BufReader, BufRead};
fn parse_num(s: &[u8]) -> (u64, usize) {
let mut num: u64 = 0;
let mut len = 0;
for i in 0..s.len() {
if s[i].is_ascii_digit() {
num = num*10 + (s[i] as u64 - '0' as u64);
len += 1;
} else {
break;
}
}
(num, len)
}
// Assuming no malformed input
fn is_in_order(left: &[u8], right: &[u8]) -> bool {
//println!(">> {:?}, {:?} -- {:?}", str::from_utf8(left), str::from_utf8(right));
if left.len() == 0 {
return true;
}
if right.len() == 0 {
return false;
}
let (l, r) = (left[0], right[0]);
if l == b',' && r == b',' {
is_in_order(&left[1..], &right[1..])
} else if l == b'[' && r == b'[' {
is_in_order(&left[1..], &right[1..])
} else if l == b']' && r == b']' {
is_in_order(&left[1..], &right[1..])
} else if l == b']' {
true
} else if r == b']' {
false
} else if l == b'[' {
let (num, len) = parse_num(right);
is_in_order(&left, &[b"[", num.to_string().as_bytes(), b"]", &right[len..]].concat())
} else if r == b'[' {
let (num, len) = parse_num(left);
is_in_order(&[b"[", num.to_string().as_bytes(), b"]", &left[len..]].concat(), &right)
} else {
let (lnum, llen) = parse_num(left);
let (rnum, rlen) = parse_num(right);
if lnum < rnum {
true
} else if lnum > rnum {
false
} else {
is_in_order(&left[llen..], &right[rlen..])
}
}
}
fn main() {
let file = File::open(&env::args().nth(1).expect("input")).expect("io err");
let lines: Vec<String> = BufReader::new(file).lines().flatten().collect();
// TODO: array_chunks() for lazy iter?
let blocks: Vec<_> = lines.chunks(3).collect();
let mut sum = 0;
for (i, block) in blocks.iter().enumerate() {
// TODO: return error here instead of assert?
assert!((block.len() == 3 && block[2] == "") || block.len() == 2);
if is_in_order(block[0].as_bytes(), block[1].as_bytes()) {
sum += i + 1;
}
}
println!("Answer: {:?}", sum);
}