init; basic quiz functionality
This commit is contained in:
@@ -0,0 +1 @@
|
||||
/target
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "fast-math"
|
||||
version = "0.1.0"
|
||||
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "fast-math"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
use std::io::{self, BufRead, Write};
|
||||
use std::time::{Duration, Instant, SystemTime};
|
||||
|
||||
struct Rng {
|
||||
state: u64,
|
||||
}
|
||||
|
||||
impl Rng {
|
||||
fn new() -> Self {
|
||||
let seed = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.subsec_nanos() as u64;
|
||||
Self { state: seed ^ 0x9e3779b97f4a7c15 }
|
||||
}
|
||||
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
self.state = self.state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
|
||||
self.state
|
||||
}
|
||||
|
||||
fn range(&mut self, min: i32, max: i32) -> i32 {
|
||||
let range = (max - min + 1) as u64;
|
||||
(self.next_u64() % range) as i32 + min
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Op {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
}
|
||||
|
||||
impl Op {
|
||||
fn symbol(self) -> char {
|
||||
match self {
|
||||
Op::Add => '+',
|
||||
Op::Sub => '-',
|
||||
Op::Mul => 'x',
|
||||
Op::Div => '/',
|
||||
}
|
||||
}
|
||||
|
||||
fn apply(self, a: i32, b: i32) -> i32 {
|
||||
match self {
|
||||
Op::Add => a + b,
|
||||
Op::Sub => a - b,
|
||||
Op::Mul => a * b,
|
||||
Op::Div => a / b,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Question {
|
||||
a: i32,
|
||||
b: i32,
|
||||
op: Op,
|
||||
answer: i32,
|
||||
}
|
||||
|
||||
impl Question {
|
||||
fn generate(rng: &mut Rng) -> Self {
|
||||
let op = match rng.range(0, 3) {
|
||||
0 => Op::Add,
|
||||
1 => Op::Sub,
|
||||
2 => Op::Mul,
|
||||
_ => Op::Div,
|
||||
};
|
||||
|
||||
let (a, b) = match op {
|
||||
Op::Add => (rng.range(1, 99), rng.range(1, 99)),
|
||||
Op::Sub => {
|
||||
let x = rng.range(1, 99);
|
||||
let y = rng.range(1, x);
|
||||
(x, y)
|
||||
}
|
||||
Op::Mul => (rng.range(2, 12), rng.range(2, 12)),
|
||||
Op::Div => {
|
||||
let b = rng.range(2, 12);
|
||||
let quotient = rng.range(2, 12);
|
||||
(b * quotient, b)
|
||||
}
|
||||
};
|
||||
|
||||
let answer = op.apply(a, b);
|
||||
Question { a, b, op, answer }
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
format!("{} {} {} = ", self.a, self.op.symbol(), self.b)
|
||||
}
|
||||
}
|
||||
|
||||
struct QuestionStats {
|
||||
a: i32,
|
||||
b: i32,
|
||||
op: Op,
|
||||
answer: i32,
|
||||
time_taken: Duration,
|
||||
mistakes: u32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const ROUNDS: usize = 10;
|
||||
|
||||
println!("\n=== Fast Math ===");
|
||||
println!("Complete {ROUNDS} questions to finish a round.\n");
|
||||
|
||||
let stdin = io::stdin();
|
||||
let mut stdin = stdin.lock();
|
||||
let mut rng = Rng::new();
|
||||
let mut stats: Vec<QuestionStats> = Vec::with_capacity(ROUNDS);
|
||||
|
||||
for i in 0..ROUNDS {
|
||||
let q = Question::generate(&mut rng);
|
||||
println!("Question {}/{}:", i + 1, ROUNDS);
|
||||
|
||||
let mut mistakes = 0u32;
|
||||
let start = Instant::now();
|
||||
|
||||
loop {
|
||||
print!(" {}", q.prompt());
|
||||
io::stdout().flush().unwrap();
|
||||
|
||||
let mut line = String::new();
|
||||
stdin.read_line(&mut line).unwrap();
|
||||
|
||||
match line.trim().parse::<i32>() {
|
||||
Ok(n) if n == q.answer => {
|
||||
println!(" Correct!\n");
|
||||
break;
|
||||
}
|
||||
Ok(_) => {
|
||||
mistakes += 1;
|
||||
println!(" Wrong, try again.");
|
||||
}
|
||||
Err(_) => {
|
||||
println!(" Please enter a valid integer.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stats.push(QuestionStats {
|
||||
a: q.a,
|
||||
b: q.b,
|
||||
op: q.op,
|
||||
answer: q.answer,
|
||||
time_taken: start.elapsed(),
|
||||
mistakes,
|
||||
});
|
||||
}
|
||||
|
||||
print_summary(&stats);
|
||||
}
|
||||
|
||||
fn print_summary(stats: &[QuestionStats]) {
|
||||
let total_time: Duration = stats.iter().map(|s| s.time_taken).sum();
|
||||
let total_mistakes: u32 = stats.iter().map(|s| s.mistakes).sum();
|
||||
let perfect = stats.iter().filter(|s| s.mistakes == 0).count();
|
||||
|
||||
println!("=== Round Complete ===\n");
|
||||
println!("{:<5} {:<12} {:<8} {:>10} {:>8}", "#", "Question", "Answer", "Time (s)", "Mistakes");
|
||||
println!("{}", "-".repeat(50));
|
||||
|
||||
for (i, s) in stats.iter().enumerate() {
|
||||
let q = format!("{} {} {}", s.a, s.op.symbol(), s.b);
|
||||
println!(
|
||||
"{:<5} {:<12} {:<8} {:>10.2} {:>8}",
|
||||
i + 1,
|
||||
q,
|
||||
s.answer,
|
||||
s.time_taken.as_secs_f64(),
|
||||
s.mistakes,
|
||||
);
|
||||
}
|
||||
|
||||
println!("{}", "-".repeat(50));
|
||||
println!(
|
||||
"{:<5} {:<12} {:<8} {:>10.2} {:>8}",
|
||||
"Tot", "", "", total_time.as_secs_f64(), total_mistakes
|
||||
);
|
||||
println!("\nPerfect (no mistakes): {}/{}", perfect, stats.len());
|
||||
}
|
||||
Reference in New Issue
Block a user