leetcode solutions mostly in Rust some C++ and TypeScript here and there

todos

#[inline] fn
const fn

scripts

clang-format -i solution.cpp
g++ -pedantic -Wall -Wextra solution.cpp
rustfmt
clippy-driver
deno fmt
deno lint

notes

  • ltr rtl lsb msb
  • don't forget hashmap and hahsset also do have with_capctiy use them
  • use assert it makes so easy to read, don't know why i didn't used, but ok only assert! leetcode runs only normal asserts not debug_assert! even if semetic meaning of those asserts is rather close to debug assertions
  • input output
    fn from_str(s: &str) -> Result<FileLines, Self::Err> {
        let v: Vec<JsonSpan> = json::from_str(s).map_err(FileLinesError::Json)?;
        let mut m = HashMap::new();
        for js in v {
            let (s, r) = JsonSpan::into_tuple(js)?;
            m.entry(s).or_insert_with(Vec::new).push(r);
  • T random type F function, S string I iterator in term of types
  • x and xs are both fine usage in rust
  • i will use m then n it seems like by default this is what we use as notation, and n when its the only value, a bit surprising since its not alphabetical
  • rust have nice ne and eq operator in same vibes as cmp don't forget to use them
  • candidate and predicate nice placeholders word to pace into functions when it's obvious what we operate on
  • r1 r2 w for pointer might be really explicit for read write of course
  • i fully embraced the confusion between m and n to denote the lenght n and m being in alphabetical order but m and n still can be found quit often
  • also check ruststd to see how their call things as refs
  • for rust don't forget usize i32 conversion i often make this mistake, as _
  • a lot of even easy rust problemes could be optimized by rewrriting the singature more idiomatic way AsRef, &mut [i32] instead of &mut Vec<32>
  • in c++ i will go with preincrement as default and postincrement then needed
  • i will use x for iteration name across all challenges
    vec![1,2,3].map(|x| println!("{x}"))
  • for the names when comparing i will stick with l and r as shorthand for left hand side and right hand side, even if in rust std it's rather lhs and rhs
  • implicit Vec::into_iter is not called on &mut Vec<i32> so be carefull
  • tokio and rust docs seems to use by default the name of value of the hashmap as naming convention like worker_threads: HashMap<usize, thread::JoinHandle<()>>, for example, or actually by key here let mut player_stats = HashMap::new(); in rust doc, with an s at the end both though
  • as bytes actually give &[u8] while bytes give iterator! on String i mean
  • if you really need to exhaust the iterator, consider .for_each(drop) instead didnt' knew this one
  • i try to avoid break, i do like loop tho but prefer return make it more explicit the solutions with breaks just feels clumsy to me you have to jump the flow everywhere to get the meaning
  • from tokio repository, hashmap naming examples
    tasks_by_key: HashMap<Key<K>, AbortHandle, S>,
    hashes_by_task: HashMap<Id, u64, S>,
  • shadowing tricks
fn take(i: u8) {}

fn main() {
    let mut i = 1;
    let i = i; // non mutable now
    let number: u32 = 1;
    let number = number as _; // u8 now
    take(number);
}
  • Option ergonomics
assert_eq!(Some(1i32), Some(1i32));
assert!(Some(i32::MIN) > None::<i32>);
assert!(None::<i32> < Some(i32::MIN));
  • gdb cheat sheet

https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf

cargo build
gdb target/debug/playground
rust-gdb ...
break src/main.rs:1
layout src
continue
step        # step into
next        # next line
finish      # step out of the fn
info locals
info args
print
print *node # if `node` is a pointer and we want value
print &node
watch       # like display but print on change only
display     # prints on every `n`
backtrace full
whatis      # print type
`Ctrl` + `L` # force rerender