Skip to content

Instantly share code, notes, and snippets.

@kdkasad
Last active April 9, 2025 21:03
Show Gist options
  • Save kdkasad/78a3bcbf0022a6a830edc7575ad1789e to your computer and use it in GitHub Desktop.
Save kdkasad/78a3bcbf0022a6a830edc7575ad1789e to your computer and use it in GitHub Desktop.
Rust competitive programming template
//!
//! # Rust competitive programming template
//!
//! Copyright (C) 2025 Kian Kasad (@kdkasad).
//! Testing via I/O dependency injection inspired by Eric Park (@ericswpark).
//!
//! You are free to use this template. If you redistribute it or a derivative work, the above
//! copyright notice and credits as well as this permission notice must be kept intact.
//!
//! Requires the following crates as dev-dependencies:
//! - `indoc`
//! - `pretty_assertions`
//!
/// Solves the problem.
fn solve<R, W>(input: &mut R, output: &mut W)
where
R: std::io::BufRead,
W: std::io::Write,
{
todo!()
}
/// Reads a single line containing `N` integers separated by ASCII whitespace from the input
/// stream.
///
/// # Panics
///
/// Panics if
/// - reading from the stream fails,
/// - the line contains less than `N` whitespace-separated parts, or
/// - parsing any part into a `usize` fails.
///
/// In debug mode, this function also panics if the line contains more than `N` parts.
#[allow(dead_code)]
fn read_parts<T, const N: usize, R>(input: &mut R) -> [T; N]
where
R: std::io::BufRead,
T: std::str::FromStr<Err: std::fmt::Debug> + Default + Copy,
{
let mut arr = [T::default(); N];
let mut line = String::new();
input.read_line(&mut line).unwrap();
let mut parts = line
.split_ascii_whitespace()
.map(|s| s.parse::<T>().unwrap());
for (i, cell) in arr.iter_mut().enumerate() {
*cell = parts
.next()
.unwrap_or_else(|| panic!("Expected {N} numbers but got {i}"));
}
debug_assert!(parts.next().is_none(), "Line contains more than {N} parts");
arr
}
/// Specialized form of [`read_parts()`] to allow for a nicer interface to read a line of a known
/// amount of space-separated `usize`s.
#[allow(dead_code)]
fn read_usizes<const N: usize, R>(input: &mut R) -> [usize; N]
where
R: std::io::BufRead,
{
read_parts(input)
}
pub fn main() {
solve(&mut std::io::stdin().lock(), &mut std::io::stdout().lock());
}
#[cfg(test)]
mod tests {
use indoc::indoc;
use pretty_assertions::assert_str_eq;
macro_rules! sample {
{ $testname:ident, $input:literal, $output:literal } => {
#[test]
fn $testname() {
let mut input = std::io::Cursor::new(
indoc! { $input }
);
let expected_output = indoc! { $output };
let mut output = Vec::new();
super::solve(&mut input, &mut output);
assert_str_eq!(expected_output, std::str::from_utf8(&output).unwrap());
}
};
}
sample! {
sample1,
"",
""
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment