Apparently a bug in PE 089 but can't for the life of me figure out what goes wrong
This commit is contained in:
32
projecteuler/089/Cargo.lock
generated
Normal file
32
projecteuler/089/Cargo.lock
generated
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "main"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"nom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minimal-lexical"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "7.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"minimal-lexical",
|
||||||
|
]
|
||||||
9
projecteuler/089/Cargo.toml
Normal file
9
projecteuler/089/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "main"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
nom = "7.1.3"
|
||||||
1000
projecteuler/089/roman.txt
Normal file
1000
projecteuler/089/roman.txt
Normal file
File diff suppressed because it is too large
Load Diff
273
projecteuler/089/src/main.rs
Normal file
273
projecteuler/089/src/main.rs
Normal 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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user