diff --git a/README.rst b/README.rst index 86b24294..45f250d3 100644 --- a/README.rst +++ b/README.rst @@ -88,7 +88,7 @@ Olivia's Project Euler Solutions | | GraalPy 23.1+ |br| | | |CodeQL| |br| | | | Browser [#]_ | | |PythonLint| | +------------+----------------------------+--------+-------------------+ -| Rust | 1.69+ |br| | 34 | |Rust| |br| | +| Rust | 1.69+ |br| | 35 | |Rust| |br| | | | Browser [#]_ | | |Rs-Cov| |br| | | | | | |RustClippy| | +------------+----------------------------+--------+-------------------+ diff --git a/docs/index.rst b/docs/index.rst index 7fd686a3..a07480ed 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -186,7 +186,7 @@ Problems Solved +-----------+------------+------------+------------+------------+------------+------------+------------+ |:prob:`58` | | | | | |:py-d:`0058`| | +-----------+------------+------------+------------+------------+------------+------------+------------+ -|:prob:`59` | | | | | |:py-d:`0059`| | +|:prob:`59` | | | | | |:py-d:`0059`|:rs-d:`0059`| +-----------+------------+------------+------------+------------+------------+------------+------------+ |:prob:`60` | | | | |:js-d:`0060`|:py-d:`0060`| | +-----------+------------+------------+------------+------------+------------+------------+------------+ diff --git a/rust/README.rst b/rust/README.rst index 3fb1e329..a7a12c15 100644 --- a/rust/README.rst +++ b/rust/README.rst @@ -87,6 +87,7 @@ Problems Solved - ☒ `37 <./src/p0037.rs>`__ - ☒ `45 <./src/p0045.rs>`__ - ☒ `53 <./src/p0053.rs>`__ +- ☒ `59 <./src/p0059.rs>`__ - ☒ `69 <./src/p0069.rs>`__ - ☒ `76 <./src/p0076.rs>`__ - ☒ `77 <./src/p0077.rs>`__ diff --git a/rust/src/include/problems.rs b/rust/src/include/problems.rs index 8ebe0d29..fffdea1e 100644 --- a/rust/src/include/problems.rs +++ b/rust/src/include/problems.rs @@ -10,6 +10,7 @@ use crate::p0036::p0036; use crate::p0037::p0037; use crate::p0045::p0045; use crate::p0053::p0053; +use crate::p0059::p0059; use crate::p0069::p0069; use crate::p0076::p0076; use crate::p0077::p0077; @@ -52,6 +53,7 @@ pub fn get_problem<'b>(n: usize) -> Option> { 37 => Some(( &37, p0037, true)), 45 => Some(( &45, p0045, false)), 53 => Some(( &53, p0053, false)), + 59 => Some(( &59, p0059, false)), 69 => Some(( &69, p0069, false)), 76 => Some(( &76, p0076, false)), 77 => Some(( &77, p0077, false)), diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 982146db..a75b0adc 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -15,6 +15,7 @@ pub mod p0036; pub mod p0037; pub mod p0045; pub mod p0053; +pub mod p0059; pub mod p0069; pub mod p0076; pub mod p0077; diff --git a/rust/src/main.rs b/rust/src/main.rs index 7b83149b..276814d3 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -32,6 +32,7 @@ pub mod p0036; pub mod p0037; pub mod p0045; pub mod p0053; +pub mod p0059; pub mod p0069; pub mod p0076; pub mod p0077; @@ -83,6 +84,7 @@ seq!(N in 01..=20 { #[case::problem_37(37)] #[case::problem_45(45)] #[case::problem_53(53)] +#[case::problem_59(59)] #[case::problem_69(69)] #[case::problem_76(76)] #[case::problem_77(77)] diff --git a/rust/src/p0059.rs b/rust/src/p0059.rs new file mode 100644 index 00000000..fa449fc1 --- /dev/null +++ b/rust/src/p0059.rs @@ -0,0 +1,46 @@ +/* +Project Euler Problem 59 + +Problem: + +Each character on a computer is assigned a unique code and the preferred +standard is ASCII (American Standard Code for Information Interchange). For +example, uppercase A = 65, asterisk (*) = 42, and lowercase k = 107. + +A modern encryption method is to take a text file, convert the bytes to ASCII, +then XOR each byte with a given value, taken from a secret key. The advantage +with the XOR function is that using the same encryption key on the cipher text, +restores the plain text; for example, 65 XOR 42 = 107, then 107 XOR 42 = 65. + +For unbreakable encryption, the key is the same length as the plain text +message, and the key is made up of random bytes. The user would keep the +encrypted message and the encryption key in different locations, and without +both "halves", it is impossible to decrypt the message. + +Unfortunately, this method is impractical for most users, so the modified +method is to use a password as a key. If the password is shorter than the +message, which is likely, the key is repeated cyclically throughout the +message. The balance for this method is using a sufficiently long password key +for security, but short enough to be memorable. + +Your task has been made easy, as the encryption key consists of three lower +case characters. Using cipher.txt (right click and 'Save Link/Target As...'), +a file containing the encrypted ASCII codes, and the knowledge that the plain +text must contain common English words, decrypt the message and find the sum of +the ASCII values in the original text. +*/ +use itertools::Itertools; + +use crate::include::utils::{get_data_file,Answer}; + +pub fn p0059() -> Answer { + let keyword = b"beginning"; + let tokens = get_data_file("p0059_cipher.txt").split(',').map(|x| x.parse::().unwrap()).collect::>(); + for key in b"abcdefghijklmnopqrtsuvwxyz".into_iter().permutations(3) { + let plaintext = tokens.iter().enumerate().map(|(i, x)| *x ^ key[i % 3]).collect::>(); + if plaintext.windows(keyword.len()).any(|w| w == keyword) { + return Answer::Int(plaintext.into_iter().sum::()); + } + } + return Answer::Int(-1); +}