Skip to content

Instantly share code, notes, and snippets.

@miguelraz
Created May 31, 2021 22:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miguelraz/d0341e9fee8c728baa99fd6fe86c1be1 to your computer and use it in GitHub Desktop.
Save miguelraz/d0341e9fee8c728baa99fd6fe86c1be1 to your computer and use it in GitHub Desktop.
# -*- mode: snippet -*-
# name: template
# uuid:
# key: TEMP
# condition: t
# --
//! Generic utility for reading data from standard input, based on [voxl's
//! stdin wrapper](http://codeforces.com/contest/702/submission/19589375).
use std::io;
use std::str;
#[allow(unused_imports)]
use std::collections::*;
/// Reads white-space separated tokens one at a time.
pub struct Scanner<R> {
reader: R,
buffer: Vec<String>,
}
impl<R: io::BufRead> Scanner<R> {
pub fn new(reader: R) -> Self {
Self {
reader,
buffer: vec![],
}
}
/// Use "turbofish" syntax token::<T>() to select data type of next token.
///
/// # Panics
///
/// Panics if there's an I/O error or if the token cannot be parsed as T.
pub fn token<T: str::FromStr>(&mut self) -> T {
loop {
if let Some(token) = self.buffer.pop() {
return token.parse().ok().expect("Failed parse");
}
let mut input = String::new();
self.reader.read_line(&mut input).expect("Failed read");
self.buffer = input.split_whitespace().rev().map(String::from).collect();
}
}
}
/// Same API as Scanner but nearly twice as fast, using horribly unsafe dark arts
/// **REQUIRES** Rust 1.34 or higher
pub struct UnsafeScanner<R> {
reader: R,
buf_str: Vec<u8>,
buf_iter: str::SplitAsciiWhitespace<'static>,
}
impl<R: io::BufRead> UnsafeScanner<R> {
pub fn new(reader: R) -> Self {
Self {
reader,
buf_str: vec![],
buf_iter: "".split_ascii_whitespace(),
}
}
/// This function should be marked unsafe, but noone has time for that in a
/// programming contest. Use at your own risk!
pub fn token<T: str::FromStr>(&mut self) -> T {
loop {
if let Some(token) = self.buf_iter.next() {
return token.parse().ok().expect("Failed parse");
}
self.buf_str.clear();
self.reader
.read_until(b'\n', &mut self.buf_str)
.expect("Failed read");
self.buf_iter = unsafe {
let slice = str::from_utf8_unchecked(&self.buf_str);
std::mem::transmute(slice.split_ascii_whitespace())
}
}
}
}
pub fn scanner_from_file(filename: &str) -> Scanner<io::BufReader<std::fs::File>> {
let file = std::fs::File::open(filename).expect("Input file not found");
Scanner::new(io::BufReader::new(file))
}
pub fn writer_to_file(filename: &str) -> io::BufWriter<std::fs::File> {
let file = std::fs::File::create(filename).expect("Output file not found");
io::BufWriter::new(file)
}
fn main() {
let stdin = io::stdin();
let stdout = io::stdout();
let reader = Scanner::new(stdin.lock());
let writer = io::BufWriter::new(stdout.lock());
solve(reader, writer);
}
#[allow(unused_must_use)]
fn solve<B: io::BufRead, W: io::Write>(mut scan: Scanner<B>, mut w: W) {
// Read a string
//let str = scan.token::<String>();
// Convert to a bitstring
//let v: Vec<bool> = s.chars().map(|ch| ch == ‘1’).collect();
// Read an Int
//let n = scan.token::<i64>();
${1}
//let mut a = Vec::with_capacity(n);
//let mut b = Vec::with_capacity(n);
//for _ in 0..n {
//a.push(scan.token::<i64>());
//b.push(scan.token::<i64>());
//}
//let mut order: Vec<_> = (0..n).collect();
//order.sort_by_key(|&i| b[i] - a[i]);
//let ans: i64 = order.into_iter()
//.enumerate()
//.map(|(i, x)| a[x] * i as i64 + b[x] * (n - 1 - i) as i64)
//.sum();
writeln!(w, "{}", ans);
}
@categulario
Copy link

Eso se ve increíblemente complicado y ofuscado. Mira te enseño el que yo uso:

use std::fmt;
use std::str::FromStr;
use std::io;

fn main() {
}

fn read_line() -> String {
    let mut pre_n = String::new();
    io::stdin().read_line(&mut pre_n).unwrap();
    pre_n
}

fn read<T: FromStr>() -> T
    where <T as FromStr>::Err: fmt::Debug
{
    read_line().trim().parse().unwrap()
}

fn read_vec<T: FromStr>() -> Vec<T>
    where <T as FromStr>::Err: fmt::Debug
{
    read_line().trim().split(" ").map(|x| x.trim().parse().unwrap()).collect()
}

Ya en el main solamente me preocupo por leer números de la entrada (que vengan uno por línea) usando

let num: u64 = read();

o si vienen varios números en la misma línea:

let nums: Vec<u64> = read_vec();

y listo.

@miguelraz
Copy link
Author

@categulario nais!

Lo voy a tomar en cuenta. Lo bonito del template que puse es que es un snippet: solo pongo TEMP<TAB> y se autocompleta todo - de ahi solo borro las lineas que aplican y casi de inmediato ya capturo mi entrada completamente.

La razón (hasta donde entiendo) que el código es más complicado es que se supone que hay problemas que te van a dar timeout si hay demasiados datos por entrada y siempre estás flusheando el Buffer - se supone que este código evita ese cuello de botella, pero la verdad mientras funcione no me preocupa mucho.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment