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