Cod sursa(job #2728350)

Utilizator wickedmanCristian Strat wickedman Data 23 martie 2021 09:21:23
Problema Zeap Scor 20
Compilator rs Status done
Runda Arhiva de probleme Marime 3.73 kb
use std::collections::BTreeSet;
use std::fs::File;
use std::io::prelude::*;
use std::io::{self, BufRead, BufWriter};
use std::path::Path;

#[derive(Debug)]
enum Command {
    Insert(i32),
    Delete(i32),
    Lookup(i32),
    QueryMaxDiff,
    QueryMinDiff,
}

trait Solution {
    fn execute(&mut self, cmd: Command) -> Option<i32>;
}

struct SlowSolution {
    a: BTreeSet<i32>,
}

impl SlowSolution {
    fn new() -> Self {
        Self { a: BTreeSet::new() }
    }
}

impl Solution for SlowSolution {
    fn execute(&mut self, cmd: Command) -> Option<i32> {
        use Command::*;
        match cmd {
            Insert(x) => {
                self.a.insert(x);
                None
            }
            Delete(x) => match self.a.remove(&x) {
                true => None,
                false => Some(-1),
            },
            Lookup(x) => match self.a.contains(&x) {
                true => Some(1),
                false => Some(0),
            },
            QueryMaxDiff => match (self.a.iter().next(), self.a.iter().next_back()) {
                (Some(a), Some(b)) if a != b => Some(b - a),
                _ => Some(-1),
            },
            QueryMinDiff => {
                let mut best: Option<i32> = None;
                let mut last: Option<i32> = None;
                for crt in self.a.iter() {
                    if let Some(last) = last.as_mut() {
                        if let Some(best) = best.as_mut() {
                            if *best > *crt - *last {
                                *best = *crt - *last;
                            }
                        } else {
                            best = Some(*crt - *last);
                        }
                        *last = *crt;
                    } else {
                        last = Some(*crt);
                    }
                }
                Some(best.unwrap_or(-1))
            }
        }
    }
}

fn run<S: Solution>(s: &mut S, in_: &mut Input, out: &mut Output) {
    for x in in_ {
        println!(">>> {:?}", x);
        if let Some(y) = s.execute(x) {
            out.put(y);
        }
    }
    out.done();
}

fn main() {
    let mut input = Input::from_path("zeap.in");
    let mut output = Output::from_path("zeap.out");
    let mut sol = SlowSolution::new();
    run(&mut sol, &mut input, &mut output);
}

struct Output {
    out: io::BufWriter<File>,
}

impl Output {
    fn from_path<P>(filename: P) -> Self
    where
        P: AsRef<Path>,
    {
        let file = File::create(filename).expect("failed to open output");
        Self {
            out: BufWriter::new(file),
        }
    }

    fn put(&mut self, x: i32) {
        write!(self.out, "{}\n", x);
    }

    fn done(&mut self) {
        self.out.flush().expect("failed to close output")
    }
}

struct Input {
    lines: io::Lines<io::BufReader<File>>,
}

impl Input {
    fn from_path<P>(filename: P) -> Self
    where
        P: AsRef<Path>,
    {
        let file = File::open(filename).expect("failed to open input");
        Self {
            lines: io::BufReader::new(file).lines(),
        }
    }
}

impl Iterator for Input {
    type Item = Command;

    fn next(&mut self) -> Option<Command> {
        let line = self.lines.next()?.ok()?;
        let args: Vec<_> = line.split(" ").collect();
        let op = args[0];
        let op_arg = args.get(1).map(|x_str| x_str.parse::<i32>().ok());
        match (op, op_arg) {
            ("I", Some(Some(x))) => Some(Command::Insert(x)),
            ("S", Some(Some(x))) => Some(Command::Delete(x)),
            ("C", Some(Some(x))) => Some(Command::Lookup(x)),
            ("MAX", None) => Some(Command::QueryMaxDiff),
            ("MIN", None) => Some(Command::QueryMinDiff),
            _ => panic!("couldn't parse input {:?}", line),
        }
    }
}