Skip to content

Commit

Permalink
update clippy, more I/O reworks
Browse files Browse the repository at this point in the history
Signed-off-by: Lance-Drane <[email protected]>
  • Loading branch information
Lance-Drane committed Aug 3, 2024
1 parent d7b5547 commit 0750125
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 149 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ workspace = true

[workspace.lints.clippy]
# add pedantic ruleset by default, configure per rule
pedantic = "warn"
pedantic = { level = "warn", priority = -1 }
# allow this one because (..=n) range syntax usually gets compiled into worse assembly
range_plus_one = "allow"
4 changes: 1 addition & 3 deletions src/bin/0_cses_template_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,9 +636,7 @@ pub mod itoap {
///
/// Behaviour is undefined if any of the following conditions are violated:
///
/// - `buf` must point to sufficient
/// [valid](https://doc.rust-lang.org/core/ptr/index.html#safety) bytes of memory to
/// write `value`
/// - `buf` must point to sufficient [valid](https://doc.rust-lang.org/core/ptr/index.html#safety) bytes of memory to write `value`
/// - `buf` must be aligned with `core::mem::align_of::<u8>()` bytes
#[inline]
pub unsafe fn write_to_ptr<V: Integer>(buf: *mut u8, value: V) -> usize {
Expand Down
58 changes: 10 additions & 48 deletions src/bin/intro_grid_paths.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,6 @@
// I/O boilerplate //

pub struct UnsafeScanner<'a> {
// not actually dead code, needed for buf_iter to work
#[allow(dead_code)]
buf_str: Vec<u8>,
buf_iter: std::str::SplitAsciiWhitespace<'a>,
}

impl UnsafeScanner<'_> {
pub fn new<R: std::io::Read>(mut reader: R) -> Self {
let mut buf_str = vec![];
unsafe {
reader.read_to_end(&mut buf_str).unwrap_unchecked();
}
let buf_iter = unsafe {
let slice = std::str::from_utf8_unchecked(&buf_str);
std::mem::transmute::<
std::str::SplitAsciiWhitespace<'_>,
std::str::SplitAsciiWhitespace<'_>,
>(slice.split_ascii_whitespace())
};

Self { buf_str, buf_iter }
}

/// Use "turbofish" syntax `token::<T>()` to select data type of next token.
///
/// # Panics
/// Panics if there's no more tokens or if the token cannot be parsed as T.
pub fn token<T: std::str::FromStr>(&mut self) -> T {
unsafe {
self.buf_iter
.next()
.unwrap_unchecked()
.parse()
.unwrap_unchecked()
}
}
}
use std::io::Read;

// problem //

Expand All @@ -58,9 +21,8 @@ impl UnsafeScanner<'_> {
/// <b>Output</b>
///
/// Print one integer: the total number of paths.
fn solve<W: std::io::Write>(mut scan: UnsafeScanner, out: &mut W) {
let mut path = [0_u8; 48];
path.copy_from_slice(&scan.token::<String>().into_bytes());
fn solve<W: std::io::Write>(scan: &[u8], out: &mut W) {
let (path, _) = scan.split_at(48);

// marking the actual grid with a border saves on having to do additional control flow checks
let mut visited = [
Expand All @@ -76,7 +38,7 @@ fn solve<W: std::io::Write>(mut scan: UnsafeScanner, out: &mut W) {
];

let mut count = 0;
recurse(0, (1, 1), &mut count, &mut visited, &path);
recurse(0, (1, 1), &mut count, &mut visited, path);

writeln!(out, "{count}").unwrap();
}
Expand All @@ -87,7 +49,7 @@ fn recurse(
position: (usize, usize),
count: &mut u32,
visited: &mut [[bool; 9]; 9],
path: &[u8; 48],
path: &[u8],
) {
// base case - check if we're on the ending square
if position == (1, 7) {
Expand Down Expand Up @@ -268,19 +230,19 @@ fn can_proceed_left(position: &(usize, usize), visited: &mut [[bool; 9]; 9]) ->
// entrypoints //

fn main() {
let scan = UnsafeScanner::new(std::io::stdin());
let mut out = std::io::BufWriter::new(std::io::stdout().lock());
solve(scan, &mut out);
let mut buf_str = vec![];
std::io::stdin().lock().read_to_end(&mut buf_str).unwrap();
let mut out = std::io::stdout().lock();
solve(&buf_str, &mut out);
}

#[cfg(test)]
mod test {
use super::*;

fn test(input: &[u8], target: &[u8]) {
let scan = UnsafeScanner::new(input);
let mut out = Vec::with_capacity(target.len());
solve(scan, &mut out);
solve(input, &mut out);

assert_eq!(out, target);
}
Expand Down
62 changes: 13 additions & 49 deletions src/bin/intro_palindrome_reorder.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,6 @@
// I/O boilerplate //

pub struct UnsafeScanner<'a> {
// not actually dead code, needed for buf_iter to work
#[allow(dead_code)]
buf_str: Vec<u8>,
buf_iter: std::str::SplitAsciiWhitespace<'a>,
}

impl UnsafeScanner<'_> {
pub fn new<R: std::io::Read>(mut reader: R) -> Self {
let mut buf_str = vec![];
unsafe {
reader.read_to_end(&mut buf_str).unwrap_unchecked();
}
let buf_iter = unsafe {
let slice = std::str::from_utf8_unchecked(&buf_str);
std::mem::transmute::<
std::str::SplitAsciiWhitespace<'_>,
std::str::SplitAsciiWhitespace<'_>,
>(slice.split_ascii_whitespace())
};

Self { buf_str, buf_iter }
}

/// Use "turbofish" syntax `token::<T>()` to select data type of next token.
///
/// # Panics
/// Panics if there's no more tokens or if the token cannot be parsed as T.
pub fn token<T: std::str::FromStr>(&mut self) -> T {
unsafe {
self.buf_iter
.next()
.unwrap_unchecked()
.parse()
.unwrap_unchecked()
}
}
}
use std::io::Read;

// problem //

Expand All @@ -56,12 +19,14 @@ impl UnsafeScanner<'_> {
/// <ul>
/// <li>1 ≤ n ≤ 10<sup>6</sup></li>
/// </ul>
fn solve<W: std::io::Write>(mut scan: UnsafeScanner, out: &mut W) {
let mut token = scan.token::<String>().into_bytes();
fn solve<W: std::io::Write>(scan: &mut [u8], out: &mut W) {
let (token, _) = scan.split_at_mut(scan.len() - 1);

let mut counter = [0_u32; 26];
for c in &token {
counter[(c - b'A') as usize] += 1;
for c in token.iter() {
unsafe {
*counter.get_unchecked_mut((*c - b'A') as usize) += 1;
}
}

let mut odd_letter = b'\0';
Expand Down Expand Up @@ -91,26 +56,25 @@ fn solve<W: std::io::Write>(mut scan: UnsafeScanner, out: &mut W) {
}
}

out.write_all(&token).unwrap();
out.write_all(&[b'\n']).unwrap();
out.write_all(scan).unwrap();
}

// entrypoints //

fn main() {
let scan = UnsafeScanner::new(std::io::stdin());
let mut out = std::io::BufWriter::with_capacity(32_768, std::io::stdout().lock());
solve(scan, &mut out);
let mut buf_str = vec![];
std::io::stdin().lock().read_to_end(&mut buf_str).unwrap();
let mut out = std::io::stdout().lock();
solve(&mut buf_str, &mut out);
}

#[cfg(test)]
mod test {
use super::*;

fn test(input: &[u8], target: &[u8]) {
let scan = UnsafeScanner::new(input);
let mut out = Vec::with_capacity(target.len());
solve(scan, &mut out);
solve(&mut input.to_owned(), &mut out);

assert_eq!(out, target);
}
Expand Down
48 changes: 0 additions & 48 deletions src/bin/search_josephus_problem_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1146,54 +1146,6 @@ where
}
}

pub struct Cursor<'a, T>
where
T: Ord + Clone,
{
set: &'a IndexSet<T>,
idx: usize,
}

impl<'a, T: Ord + Clone> Cursor<'a, T> {
pub fn move_next(&mut self) {
if self.idx == self.set.len() {
self.idx = 0;
} else {
self.idx += 1;
}
}
pub fn move_index(&mut self, index: usize) {
self.idx = index;
}
pub fn move_prev(&mut self) {
if self.idx == 0 {
self.idx = self.set.len();
} else {
self.idx -= 1;
}
}
pub fn item(&self) -> Option<&'a T> {
return self.set.get_index(self.idx);
}
pub fn peek_next(&self) -> Option<&'a T> {
if self.idx == self.set.len() {
return self.set.first();
}

return self.set.get_index(self.idx + 1);
}
pub fn peek_index(&self, index: usize) -> Option<&'a T> {
return self.set.get_index(index);
}
pub fn peek_prev(&self) -> Option<&'a T> {
if self.idx == 0 {
return None;
}

return self.set.get_index(self.idx - 1);
}
}

// I/O boilerplate //

use std::io::Read;
Expand Down

0 comments on commit 0750125

Please sign in to comment.