#![doc = include_str!("../README.md")]
use std::cmp::Ordering;
use std::error::Error as StdError;
use std::fmt::{self, Display, Formatter};
use std::time::Duration;
pub mod problems;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum Error {
UnavailableProblem,
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::UnavailableProblem => write!(f, "The requested problem is not available."),
}
}
}
impl StdError for Error {}
pub trait ProjectEuler: Send + Sync {
fn problems<'a>(&'a self) -> Box<dyn Iterator<Item = &'a dyn Problem> + 'a>;
fn problem(&self, id: usize) -> Result<&dyn Problem, Error> {
for iter_problem in self.problems() {
match iter_problem.id().cmp(&id) {
Ordering::Less => {}
Ordering::Equal => return Ok(iter_problem),
Ordering::Greater => break,
}
}
Err(Error::UnavailableProblem)
}
fn solve(&self, id: usize) -> Result<String, Error> {
Ok(self.problem(id)?.solve())
}
fn benchmark(&self, id: usize) -> Result<(String, Duration), Error> {
Ok(self.problem(id)?.benchmark())
}
}
pub trait Problem: Send + Sync + Solution {
fn id(&self) -> usize;
fn title(&self) -> &str;
}
pub trait Solution: Send + Sync {
fn solve(&self) -> String;
fn benchmark(&self) -> (String, Duration) {
let result;
let elapsed;
#[cfg(not(all(
target_arch = "wasm32",
target_vendor = "unknown",
target_os = "unknown"
)))]
{
let instant = std::time::Instant::now();
result = self.solve();
elapsed = instant.elapsed();
}
#[cfg(all(
target_arch = "wasm32",
target_vendor = "unknown",
target_os = "unknown"
))]
{
use wasm_bindgen::prelude::*;
let global_obj = js_sys::global();
let performance = js_sys::Reflect::get(&global_obj, &JsValue::from_str("performance"))
.unwrap()
.dyn_into::<web_sys::Performance>()
.unwrap();
let instant = performance.now();
result = self.solve();
elapsed = Duration::from_secs_f64((performance.now() - instant) / 1000.0);
}
(result, elapsed)
}
}
pub struct PEuler {
problems: Vec<Box<dyn Problem>>,
}
impl PEuler {
pub fn new() -> Self {
let mut new_obj = Self {
problems: vec![
Box::new(problems::Problem0001::new()),
Box::new(problems::Problem0002::new()),
Box::new(problems::Problem0003::new()),
Box::new(problems::Problem0004::new()),
Box::new(problems::Problem0005::new()),
Box::new(problems::Problem0006::new()),
Box::new(problems::Problem0007::new()),
Box::new(problems::Problem0008::new()),
Box::new(problems::Problem0009::new()),
Box::new(problems::Problem0010::new()),
Box::new(problems::Problem0011::new()),
Box::new(problems::Problem0012::new()),
Box::new(problems::Problem0013::new()),
Box::new(problems::Problem0014::new()),
Box::new(problems::Problem0015::new()),
Box::new(problems::Problem0016::new()),
Box::new(problems::Problem0017::new()),
Box::new(problems::Problem0018::new()),
Box::new(problems::Problem0019::new()),
Box::new(problems::Problem0020::new()),
Box::new(problems::Problem0021::new()),
Box::new(problems::Problem0022::new()),
Box::new(problems::Problem0023::new()),
Box::new(problems::Problem0024::new()),
Box::new(problems::Problem0025::new()),
Box::new(problems::Problem0026::new()),
Box::new(problems::Problem0027::new()),
Box::new(problems::Problem0028::new()),
Box::new(problems::Problem0029::new()),
Box::new(problems::Problem0030::new()),
Box::new(problems::Problem0031::new()),
Box::new(problems::Problem0032::new()),
Box::new(problems::Problem0033::new()),
Box::new(problems::Problem0034::new()),
Box::new(problems::Problem0035::new()),
Box::new(problems::Problem0036::new()),
Box::new(problems::Problem0037::new()),
Box::new(problems::Problem0038::new()),
Box::new(problems::Problem0039::new()),
Box::new(problems::Problem0040::new()),
Box::new(problems::Problem0041::new()),
Box::new(problems::Problem0042::new()),
Box::new(problems::Problem0043::new()),
Box::new(problems::Problem0044::new()),
Box::new(problems::Problem0045::new()),
Box::new(problems::Problem0046::new()),
Box::new(problems::Problem0047::new()),
Box::new(problems::Problem0048::new()),
Box::new(problems::Problem0049::new()),
Box::new(problems::Problem0050::new()),
Box::new(problems::Problem0052::new()),
Box::new(problems::Problem0053::new()),
Box::new(problems::Problem0054::new()),
Box::new(problems::Problem0055::new()),
Box::new(problems::Problem0056::new()),
Box::new(problems::Problem0057::new()),
Box::new(problems::Problem0058::new()),
Box::new(problems::Problem0059::new()),
Box::new(problems::Problem0061::new()),
Box::new(problems::Problem0062::new()),
Box::new(problems::Problem0063::new()),
Box::new(problems::Problem0064::new()),
Box::new(problems::Problem0065::new()),
Box::new(problems::Problem0066::new()),
Box::new(problems::Problem0067::new()),
Box::new(problems::Problem0069::new()),
Box::new(problems::Problem0070::new()),
Box::new(problems::Problem0071::new()),
Box::new(problems::Problem0072::new()),
Box::new(problems::Problem0073::new()),
Box::new(problems::Problem0074::new()),
Box::new(problems::Problem0075::new()),
Box::new(problems::Problem0076::new()),
Box::new(problems::Problem0077::new()),
Box::new(problems::Problem0078::new()),
Box::new(problems::Problem0080::new()),
Box::new(problems::Problem0081::new()),
Box::new(problems::Problem0082::new()),
Box::new(problems::Problem0085::new()),
Box::new(problems::Problem0089::new()),
Box::new(problems::Problem0091::new()),
Box::new(problems::Problem0092::new()),
Box::new(problems::Problem0095::new()),
Box::new(problems::Problem0097::new()),
Box::new(problems::Problem0098::new()),
Box::new(problems::Problem0099::new()),
Box::new(problems::Problem0100::new()),
Box::new(problems::Problem0102::new()),
],
};
new_obj
.problems
.sort_unstable_by_key(|problem| problem.id());
new_obj
}
}
impl Default for PEuler {
fn default() -> Self {
Self::new()
}
}
impl ProjectEuler for PEuler {
fn problems<'a>(&'a self) -> Box<dyn Iterator<Item = &'a dyn Problem> + 'a> {
Box::new(self.problems.iter().map(|problem| problem.as_ref()))
}
}