problem 1

This commit is contained in:
AF 2024-03-22 22:19:30 +00:00
parent d3c4e41a12
commit a7fafcff22
3 changed files with 191 additions and 3 deletions

35
Cargo.lock generated
View File

@ -519,6 +519,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
[[package]]
name = "itoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.153" version = "0.2.153"
@ -581,6 +587,28 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "mini-internal"
version = "0.1.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f09fa787e06d071d09c2964b065eb7cb1b842a7af5382fc4c9142089f8383f08"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "miniserde"
version = "0.1.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e19a2e17a11c24d44c84d7e1b61477e20cd503d024e4b0eb3e97eb9a4d24fa87"
dependencies = [
"itoa",
"mini-internal",
"ryu",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.2" version = "0.7.2"
@ -685,6 +713,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"futures", "futures",
"miette", "miette",
"miniserde",
"smol", "smol",
] ]
@ -730,6 +759,12 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "ryu"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.1" version = "1.4.1"

View File

@ -6,4 +6,5 @@ edition = "2021"
[dependencies] [dependencies]
futures = "0.3.30" futures = "0.3.30"
miette = { version = "5", features = ["fancy"] } miette = { version = "5", features = ["fancy"] }
miniserde = "0.1.38"
smol = "1.3.0" smol = "1.3.0"

View File

@ -1,9 +1,161 @@
use futures::{AsyncReadExt, StreamExt}; use futures::{
future::ready, io::BufReader, AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, StreamExt,
TryStreamExt,
};
use miette::IntoDiagnostic; use miette::IntoDiagnostic;
use miniserde::{json::Number, Deserialize, Serialize};
fn pow(a: u64, d: u64, n: u64) -> u64 {
let n: u128 = n.into();
let mut d: u128 = d.into();
let mut x: u128 = 1;
let mut q: u128 = a.into();
while d != 0 {
if d & 1 == 1 {
x *= q;
x %= n;
}
q *= q;
q %= n;
d >>= 1;
}
x as _
}
fn square(x: u64, n: u64) -> u64 {
let n: u128 = n.into();
let mut x: u128 = x.into();
x *= x;
x %= n;
x as _
}
fn is_prime(n: u64) -> bool {
const LOG_2_TO_E: [u64; 65] = [
0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12, 12, 13, 14, 14, 15, 16, 16, 17, 18,
19, 19, 20, 21, 21, 22, 23, 23, 24, 25, 25, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34,
34, 35, 36, 37, 37, 38, 39, 39, 40, 41, 41, 42, 43, 43, 44, 45,
];
match n {
0 => false,
1 => false,
2 => true,
3.. => {
let n1 = n - 1;
let s = n1.trailing_zeros();
let d = n1 >> s;
let log_e_approx = LOG_2_TO_E[(n.ilog2() + 1) as usize];
for a in 2..=(n - 2).min(2 * log_e_approx * log_e_approx) {
let mut x = pow(a, d, n);
for _ in 0..s {
let y = square(x, n);
if y == 1 && x != 1 && x != n1 {
return false;
}
x = y;
}
if x != 1 {
return false;
}
}
true
}
}
}
#[test]
fn primes() {
assert!(!is_prime(0));
assert!(!is_prime(1));
assert!(is_prime(2));
assert!(is_prime(3));
assert!(!is_prime(4));
assert!(is_prime(5));
assert!(!is_prime(6));
assert!(is_prime(7));
assert!(!is_prime(8));
assert!(!is_prime(9));
assert!(!is_prime(10));
assert!(is_prime(11));
assert!(!is_prime(12));
assert!(is_prime(13));
assert!(!is_prime(14));
assert!(!is_prime(15));
assert!(!is_prime(16));
assert!(is_prime(17));
assert!(!is_prime(18));
assert!(is_prime(19));
assert!(!is_prime(20));
assert!(!is_prime(21));
assert!(!is_prime(22));
assert!(is_prime(23));
assert!(!is_prime(57));
assert!(is_prime(97));
assert!(is_prime(101));
assert!(is_prime(179));
assert!(!is_prime(216));
assert!(!is_prime(426));
assert!(is_prime(997));
assert!(is_prime(65537));
}
#[derive(Debug, Serialize, Deserialize)]
enum Method {
#[serde(rename = "isPrime")]
IsPrime,
}
#[derive(Debug, Deserialize)]
struct Request {
method: Method,
number: Number,
}
#[derive(Debug, Serialize)]
struct Response {
method: Method,
prime: bool,
}
fn json_prime(number: Number) -> bool {
match number {
Number::U64(n) => is_prime(n),
_ => false,
}
}
fn try_process(input: String) -> miniserde::Result<String> {
let Request {
method: Method::IsPrime,
number,
} = miniserde::json::from_str(&input)?;
let response = Response {
method: Method::IsPrime,
prime: json_prime(number),
};
Ok(miniserde::json::to_string(&response))
}
fn process(input: String) -> String {
try_process(input).unwrap_or_default()
}
async fn handle(stream: smol::io::Result<smol::net::TcpStream>) -> smol::io::Result<()> { async fn handle(stream: smol::io::Result<smol::net::TcpStream>) -> smol::io::Result<()> {
let (reader, mut writer) = stream?.split(); let (reader, writer) = stream?.split();
futures::io::copy(reader, &mut writer).await.map(|_| {}) let mut alive = true;
BufReader::new(reader)
.lines()
.map_ok(process)
.take_while(|item| {
ready(match item {
Ok(s) if s.is_empty() => std::mem::take(&mut alive),
_ => alive,
})
})
.map_ok(|s| s + "\n")
.forward(writer.into_sink::<String>())
.await
} }
fn main() -> miette::Result<()> { fn main() -> miette::Result<()> {