feat: 20 - factorial digit sum

This commit is contained in:
newt 2024-10-09 18:10:13 +01:00
parent bdd644ad4a
commit 68e02a020b
6 changed files with 77 additions and 40 deletions

View file

@ -17,7 +17,7 @@ Here is a [link to my profile](https://projecteuler.net/progress=newtykins).
## Challenge Completion
### 23 out of 100 public challenges completed.
### 25 out of 100 public challenges completed.
- [x] 1 - [Multiples of 3 or 5](src/bin/1.rs)
- [x] 2 - [Even Fibonacci numbers](src/bin/2.rs)
@ -38,7 +38,7 @@ Here is a [link to my profile](https://projecteuler.net/progress=newtykins).
- [x] 17 - [Number letter counts](src/bin/17.rs)
- [x] 18 - [Maximum path sum I](src/bin/18.rs)
- [x] 19 - Counting Sundays
- [ ] 20 - Factorial digit sum
- [x] 20 - Factorial digit sum
- [ ] 21 - Amicable numbers
- [x] 22 - [Names scores](src/bin/22.rs)
- [ ] 23 - Non-abundant sums

View file

@ -5,11 +5,11 @@ Problem 16 - Power digit sum
What is the sum of the digits of the number 2 1000 ?
*/
fn power_digit_sum<const POWER: usize>(base: usize) -> usize {
let mut digits = [0u8; POWER];
fn power_digit_sum(base: usize, power: usize) -> usize {
let mut digits = vec![0u8; power];
digits[0] = 1; // 2^0 = 1
for _ in 0..POWER {
for _ in 0..power {
let mut carry = 0;
for digit in digits.iter_mut() {
@ -23,7 +23,7 @@ fn power_digit_sum<const POWER: usize>(base: usize) -> usize {
}
pub fn main() {
let sum = power_digit_sum::<1000>(2);
let sum = power_digit_sum(2, 1000);
println!("The sum of the digits of the number 2^1000 is {}!", sum);
}

34
src/bin/20.rs Normal file
View file

@ -0,0 +1,34 @@
/*
Problem 20 - Factorial Digit Sum
$n!$ means $n \times (n - 1) \times \cdots \times 3 \times 2 \times 1$.
For example, $10! = 10 \times 9 \times \cdots \times 3 \times 2 \times 1 = 3628800$, and the sum of the digits in the number $10!$ is $3 + 6 + 2 + 8 + 8 + 0 + 0 = 27$.
Find the sum of the digits in the number $100!$.
*/
fn multiply(digits: &mut Vec<u8>, multiplier: usize) {
let mut carry = 0usize;
for digit in digits.iter_mut() {
let product = *digit as usize * multiplier + carry;
*digit = (product % 10) as u8;
carry = product / 10;
}
while carry > 0 {
digits.push((carry % 10) as u8);
carry /= 10;
}
}
pub fn main() {
let mut digits = vec![1];
for num in 2..=100 {
multiply(&mut digits, num);
}
let sum: usize = digits.iter().map(|&d| d as usize).sum();
print!("The sum of the digits in the number 100! is {}!", sum);
}

View file

@ -17,40 +17,42 @@ pub async fn execute(number: Option<u8>) -> Result<()> {
file.write(problem.file_body().as_bytes())?;
drop(file);
// open readme
let mut readme_file = OpenOptions::new().read(true).open(README.clone())?;
if problem.number <= 100 {
// open readme
let mut readme_file = OpenOptions::new().read(true).open(README.clone())?;
let readme_content = {
// read
let mut content = BufReader::new(&readme_file)
.lines()
.map(|s| s.unwrap())
.collect::<Vec<String>>()
.join("\n");
let readme_content = {
// read
let mut content = BufReader::new(&readme_file)
.lines()
.map(|s| s.unwrap())
.collect::<Vec<String>>()
.join("\n");
drop(readme_file);
// mark problem as done on readme
content = content.replace(
&format!("\n- [ ] {}", problem.number),
&format!("\n- [x] {}", problem.number),
);
// update completed count
let completion_regex = Regex::new(r"(\d+) out of")?;
let problem_count = fs::read_dir(SOLUTIONS.clone())?.count();
content = completion_regex
.replace(&content, format!("{} out of", problem_count))
.to_string();
content
};
// write the new content to the readme
readme_file = OpenOptions::new().write(true).open(README.clone())?;
readme_file.write(readme_content.as_bytes())?;
drop(readme_file);
// mark problem as done on readme
content = content.replace(
&format!("\n- [ ] {}", problem.number),
&format!("\n- [x] {}", problem.number),
);
// update completed count
let completion_regex = Regex::new(r"(\d+) out of")?;
let problem_count = fs::read_dir(SOLUTIONS.clone())?.count();
content = completion_regex
.replace(&content, format!("{} out of", problem_count))
.to_string();
content
};
// write the new content to the readme
readme_file = OpenOptions::new().write(true).open(README.clone())?;
readme_file.write(readme_content.as_bytes())?;
drop(readme_file);
}
// add the problem to the run command
let mut run_file = OpenOptions::new()

View file

@ -42,6 +42,8 @@ mod thirteen;
mod three;
#[path = "../bin/12.rs"]
mod twelve;
#[path = "../bin/20.rs"]
mod twenty;
#[path = "../bin/27.rs"]
mod twenty_seven;
#[path = "../bin/22.rs"]
@ -87,6 +89,7 @@ pub async fn execute(
27 => twenty_seven::main(),
67 => sixty_seven::main(),
19 => nineteen::main(),
20 => twenty::main(),
_ => {
exists = false;
println!(

View file

@ -21,8 +21,6 @@ impl Problem {
// ensure the number is in bound
if n <= 0 {
Err("Please enter a number greater than 0".to_string())
} else if n > 100 {
Err("Please enter a number less than or equal to 100".to_string())
}
// ensure that the problem has not already got a file associated with it
else {
@ -64,7 +62,7 @@ impl Problem {
let number = number
.unwrap_or_else(|| Self::prompt_number("Please select a problem:", false).unwrap());
let body = reqwest::get(format!("https://projecteuler.net/minimal={number}"))
let body = reqwest::get(format!("https://projecteuler.net/problem={number}"))
.await?
.text()
.await?;