Skip to content

cdwfs/advent2020

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

My Advent of Code 2020 solutions, implemented in Rust and built using VS Code.

TIL

A list of the puzzles, and what new language/tool features I learned each day:

  • Basic Rust + VSCode integration
  • Basic Rust Git configuration (.gitignore, .gitattributes)
  • Reading text files line-by-line with BufReader
  • Parsing strings as integers with my_str.parse()
  • Vec for growable lists
  • All-at-once text file parsing using fs::read_to_string(). Nothing this month should be large enough to warrant BufReader.
  • String::lines() to iterate over lines of text data.
  • Unit tests with #[test]
  • Raw strings with r"blah"
  • Indexing into a string's chars is verbose. For AoC purposes, we'll assume ASCII and 1 u8 = 1 character.
  • Basic use of the regex crate -- checking for matches, named capture groups, etc.
  • How to set up Cargo for multi-target packages. Less duplication of target metadata this way.
  • Q: Why is VS Code inserting suggestions after . or : in comments?
  • Q: How to generalize this code into a template more easily applicable to future days' problems?
  • Basic 2D grid struct with new/get/set methods
  • vec! macro for array-like Vec declarations
  • ${fileBasenameNoExtension} substitution works in launch.json (no more day-specific debug configurations!)
  • Debugging Rust unit tests in VS Code (use the target/debug/deps/project-hash.exe executable, run with --test-threads=1 to keep the callstack from jumping around)
  • Basic HashMap usage
  • Custom message for assert failures
  • match statement, with non-fatal None handling for Option<T>
  • radix conversion with u32::from_str_radix()
  • in-place array sorting: a.sort()
  • std::cmp::max(a,b) and std::cmp::min(a,b)
  • nothing new, really
  • HashSet for value-less hash maps
  • String.split() returns an iterator, not a collection
  • Started to run into lifetime issues. I can solve them by just making things String until they go away, but that's not sustainable.
  • I made an enum. Though in this case it could've been a struct in the end, since NOPs have args as well.
  • Q: how to safely add a signed integer to a usize? (typecasting around feels like it misses the point)
  • I feel like HashMap.entry() could save me some redundant lookups, but performance hasn't been an issue yet.
  • Some basic functional programming with .map() and lambdas
  • Q: How best to pass side-channel data into the "solve" functions, such as the history size for part 1, or the target sum from part 2? I guess an enum of some sort?
  • Hash map keys must be borrowed. Even if they're literals. (Q: why?)
  • HashMap.Get(&k).unwrap_or(default) for potentially missing values
  • std::mem::swap() to exchange two mutable locations without deinitializing
  • No ternary operator; if-else expressions have a value instead: `x = if (c) { a } else { b };
  • integer casts: usize::try_from(n).unwrap()
  • #[rustfmt::skip] on a function/etc. to opt out of rustfmt
  • absolute value is a method on integer types, e.g. -3.abs()
  • No Python-esque tuple assignments; if wx and wy exist, you can't swap with wx,wy = wy,wx;
  • Probably rediscovered some modular arithmetic theorem? (Sure enough!)
  • Rust calls reduce() fold().
  • Successful use of HashMap::entry(): *memory.entry(addr).or_default() = val;
  • HashMaps are slow in debug builds.
  • Need to come back and reoptimize/clean this up so I can re-enable the unit tests for part 2, I'm doing a gajillion unnecessary lookups.
  • cargo clippy! Went back and fixed all the clippy lints in previous days' solutions.
  • Use 64-bit integers everywhere!
  • HashSet
  • static constant arrays
  • Tuple structs
  • Initializing collections with .with_capacity() instead of new() if an upper-bound (or exact) size is known at creation time.
  • Some new string iteration functions: .matches(), .match_indices(), .position(), etc. But, definitely not clear which are defined on which string types.
  • I am not good at String/str/&str/[u8] manipulation in Rust :(. In part 2 especially, I'm creating new Strings all over the place just to keep the borrow checker happy.
  • Iterator::any() and all()
  • Escape curly braces in format strings with {{ and }}
  • Implementing Display trait for custom struct
  • Manually advancing an iterator mid-loop, using next() and while let Some(_) = iter.next()
  • collect() doesn't seem to work on iterators over &str, which is unfortunate.
  • sort_by() on collections, for custom sort functions
  • I tried to go more functional this time where possible.
  • DefaultHasher for a 64-bit hash of arbitrary bytes (even provided incrementally). Handy!
  • Man I wish indexing arrays by non-usize wasn't a constant pain
  • This is getting more natural!
  • Anticlimatic

About

Advent of Code 2020

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages