Apparently a bug in PE 089 but can't for the life of me figure out what goes wrong

This commit is contained in:
Philippe Zwietering
2023-03-20 17:02:05 +01:00
parent 5bb1e5b31c
commit 091ef1f518
4 changed files with 1314 additions and 0 deletions

View File

@@ -0,0 +1,273 @@
use nom::{
branch::alt,
character::complete::{char, multispace1},
multi::{many1, separated_list1},
IResult, Parser,
};
use std::{time::Instant, vec};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum RomanNum {
I,
V,
X,
L,
C,
D,
M,
Empty,
}
use RomanNum::*;
type RomanNumeral = Vec<RomanNum>;
// This function is not correct at all but I'm not gonna bother fixing it
fn _is_minimal(number: &RomanNumeral) -> bool {
let mut last_num = Empty;
let mut occ = 0;
for num in number.iter() {
if *num == last_num {
occ += 1;
} else {
last_num = *num;
occ = 1;
}
if occ > 3 && (last_num == I || last_num == X || last_num == C) {
return false;
// } else if occ > 1 && (last_num == V || last_num == L || last_num == D) {
// return false;
}
}
true
}
fn reduce(original: &RomanNumeral) -> RomanNumeral {
let mut last_num = Empty;
let mut occ = 0;
let mut result = vec![];
let mut number = original.clone();
number.push(Empty);
for num in number.iter() {
if *num == last_num {
occ += 1;
if occ == 10 {
match last_num {
I => result.push(X),
X => result.push(C),
C => result.push(M),
M => {
for _ in 0..occ {
result.push(M);
}
}
_ => {}
}
occ -= 10;
}
} else {
if occ < 4 {
for _ in 0..occ {
result.push(last_num);
}
} else if occ == 4 {
match last_num {
I => {
result.push(I);
result.push(V);
}
X => {
result.push(X);
result.push(L);
}
C => {
result.push(C);
result.push(D);
}
M => {
for _ in 0..occ {
result.push(M);
}
}
_ => {}
}
} else if occ == 5 {
match last_num {
I => result.push(V),
X => result.push(L),
C => result.push(D),
M => {
for _ in 0..occ {
result.push(M);
}
}
_ => {}
}
} else if occ >= 6 && occ <= 8 {
match last_num {
I => {
result.push(V);
for _ in 0..occ - 5 {
result.push(I);
}
}
X => {
result.push(L);
for _ in 0..occ - 5 {
result.push(X);
}
}
C => {
result.push(D);
for _ in 0..occ - 5 {
result.push(C);
}
}
M => {
for _ in 0..occ {
result.push(M);
}
}
_ => {}
}
} else if occ == 9 {
match last_num {
I => {
result.push(I);
result.push(X);
}
X => {
result.push(X);
result.push(C);
}
C => {
result.push(C);
result.push(M);
}
M => {
for _ in 0..occ {
result.push(M);
}
}
_ => {}
}
}
last_num = *num;
occ = 1;
}
// println!("{:?}", result);
}
result
}
fn reduce_extra(numeral: &RomanNumeral) -> RomanNumeral {
if numeral.len() <= 3 {
return numeral.clone();
}
let mut result = vec![];
let mut window = vec![Empty, numeral[0], numeral[1]];
let mut i = 2;
while i < numeral.len() {
result.push(window[0]);
window[0] = window[1];
window[1] = window[2];
window[2] = numeral[i];
if window[0] == V && window[1] == I && window[2] == V {
result.push(I);
result.push(X);
window[1] = Empty;
window[2] = Empty;
} else if window[0] == L && window[1] == X && window[2] == L {
result.push(X);
result.push(C);
window[1] = Empty;
window[2] = Empty;
} else if window[0] == D && window[1] == C && window[2] == D {
result.push(C);
result.push(M);
window[1] = Empty;
window[2] = Empty;
}
i += 1;
}
result.push(window[0]);
result.push(window[1]);
result.push(window[2]);
result.into_iter().filter(|&n| n != Empty).collect()
}
fn parse_input(input: &str) -> IResult<&str, Vec<RomanNumeral>> {
let (input, result) = separated_list1(
multispace1,
many1(
alt((
char('I'),
char('V'),
char('X'),
char('L'),
char('C'),
char('D'),
char('M'),
))
.map(|c| match c {
'I' => I,
'V' => V,
'X' => X,
'L' => L,
'C' => C,
'D' => D,
'M' => M,
_ => Empty,
}),
),
)(input)?;
Ok((input, result))
}
fn main() {
println!("Hello, this is Patrick!");
let now = Instant::now();
let input_text = include_str!("../roman.txt");
// let res = parse_input(input_text);
// println!("{:?}", res);
let (_, numerals) = parse_input(input_text).unwrap();
let mut result = 0;
for mut numeral in numerals {
let start = numeral.len();
let mut s = start;
loop {
numeral = reduce(&numeral);
numeral = reduce_extra(&numeral);
if s == numeral.len() {
break;
}
s = numeral.len();
}
result += start - numeral.len();
println!("{:?} , {}", numeral, start - numeral.len());
}
println!("The number of characters that can be saved is: {}", result);
println!("Time passed: {:?}", Instant::now() - now);
}