improve performance of challenge 03 by precomputing giant steps
This commit is contained in:
BIN
res/03_baby_steps.bin
Normal file
BIN
res/03_baby_steps.bin
Normal file
Binary file not shown.
BIN
res/03_giant_steps.bin
Normal file
BIN
res/03_giant_steps.bin
Normal file
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
use lib::submit_with_name;
|
||||
|
||||
fn main() {
|
||||
let name = "((ο)=>((o)=>o(((o(((ο*o([!+[]+!+";
|
||||
let name = "Яана";
|
||||
|
||||
let (n, x) = lib::challenges::c1_welcome::solve();
|
||||
println!("n = {:?}\nx = {:?}\n{:?}\n", n, x, submit_with_name(name, n, x));
|
||||
|
@@ -11,9 +11,8 @@ lazy_static!(
|
||||
|
||||
pub fn solve(name: &str) -> (u64, Integer) {
|
||||
let mut x = sha256(name);
|
||||
println!("sha256 = {x}");
|
||||
x += 4;
|
||||
for _ in tqdm::tqdm(0..10_000) {
|
||||
for _ in 0..10_000 {
|
||||
for _ in 0..100 {
|
||||
x.pow_mod_mut(&E, &M).unwrap();
|
||||
}
|
||||
|
@@ -1,22 +1,86 @@
|
||||
use lazy_static::lazy_static;
|
||||
use rug::Integer;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{stdout, Write};
|
||||
use tqdm::tqdm;
|
||||
|
||||
const P: u64 = 12345679943u64;
|
||||
|
||||
lazy_static!(
|
||||
static ref BABY_STEPS: Vec<u64> = std::fs::read("res/03_baby_steps.bin").unwrap()
|
||||
.chunks_exact(8)
|
||||
.map(|chunk| u64::from_be_bytes(chunk.try_into().unwrap()))
|
||||
.collect();
|
||||
|
||||
static ref GIANT_STEPS: HashMap<u64, usize> = std::fs::read("res/03_giant_steps.bin").unwrap()
|
||||
.chunks_exact(8)
|
||||
.map(|chunk| u64::from_be_bytes(chunk.try_into().unwrap()))
|
||||
.enumerate()
|
||||
.map(|(idx, step)| (step, idx))
|
||||
.collect();
|
||||
);
|
||||
|
||||
pub fn solve(n: u64, x: Integer) -> (u64, Integer) {
|
||||
let x = x.modulo(&Integer::from(P - 1)).to_u64().unwrap();
|
||||
|
||||
let mut n = n;
|
||||
let mut x = x.clone();
|
||||
for _ in tqdm(0..10_000) {
|
||||
for _ in 0..10_000 {
|
||||
n += 1;
|
||||
x = log(42, 1 + (x + n) % (P - 1), P).unwrap();
|
||||
x = log42_mod_p(1 + (x + n) % (P - 1)).unwrap();
|
||||
}
|
||||
|
||||
(n, Integer::from(x))
|
||||
}
|
||||
|
||||
fn log42_mod_p(b: u64) -> Option<u64> {
|
||||
if b % P == 1 {
|
||||
return Some(0);
|
||||
}
|
||||
|
||||
let inv = pow(b, P - 2, P) as u128;
|
||||
let s = GIANT_STEPS.len();
|
||||
for j in 1..=BABY_STEPS.len() {
|
||||
let baby_step = BABY_STEPS[j - 1] as u128;
|
||||
let search = ((baby_step * inv) % P as u128) as u64;
|
||||
if let Some(i) = GIANT_STEPS.get(&search) {
|
||||
return Some((j * s - i) as u64);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn precompute() {
|
||||
let g = 42u64;
|
||||
let m = P;
|
||||
let s = 5341666;
|
||||
precompute_giant_steps(g, m, s);
|
||||
precompute_baby_steps(g, m, s);
|
||||
}
|
||||
|
||||
fn precompute_giant_steps(g: u64, m: u64, s: u64) {
|
||||
let g = g as u128;
|
||||
let m = m as u128;
|
||||
let mut a = 1u128;
|
||||
for _ in tqdm(0..s) {
|
||||
stdout().write_all(&(a as u64).to_be_bytes()).unwrap();
|
||||
a *= g;
|
||||
a %= m;
|
||||
}
|
||||
}
|
||||
|
||||
fn precompute_baby_steps(g: u64, m: u64, s: u64) {
|
||||
let gs = pow(g, s, m) as u128;
|
||||
let m= m as u128;
|
||||
let mut a = gs;
|
||||
for _ in tqdm(1..=(m as u64 / s + 1)) {
|
||||
stdout().write_all(&(a as u64).to_be_bytes()).unwrap();
|
||||
a *= gs;
|
||||
a %= m;
|
||||
}
|
||||
}
|
||||
|
||||
fn log(g: u64, b: u64, m: u64) -> Option<u64> {
|
||||
let g: u128 = g as u128;
|
||||
let b: u128 = b as u128;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
#![allow(dead_code)]
|
||||
use anyhow::{anyhow, Result};
|
||||
use json::JsonValue;
|
||||
use std::fmt::Display;
|
||||
|
Reference in New Issue
Block a user