Skip to content

Commit

Permalink
docs: add Python example to 15
Browse files Browse the repository at this point in the history
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
  • Loading branch information
henryiii committed Dec 15, 2023
1 parent 03012a2 commit 1bddc61
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 19 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ cargo fmt
cargo clippy
```

You should have Rust 1.74+ to use the `Cargo.toml` config for clippy.

## Tests

Use:
Expand All @@ -32,8 +34,16 @@ Use:
cargo run -r --bin 01
```

(`-r` for release mode highly recommended for `05` and `06`!)
(`-r` for release mode highly recommended for some problems, like `05`!)


## Docs

Some problems have docs, build with:

```bash
cargo docs --no-deps
```

## Notes

Expand Down
71 changes: 53 additions & 18 deletions src/bin/15.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,77 @@
#![warn(clippy::all, clippy::pedantic, clippy::nursery)]

use indexmap::IndexMap;
/*!
# Problem 15 - HASH and HASHMAP
This problem is very simple if you have an ordered hashmap. I originally
solved this one on my phone in Python; for comparison, here it is:
```python
INPUT = 'rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7'
def hsh(x):
s = 0
for v in x:
s += ord(v)
s *= 17
s %= 256
return s
type Num = usize;
print(sum(hsh(x) for x in INPUT.split(',')))
def hshmap(x):
boxes = {i: {} for i in range(256)}
for val in x:
code, op, fl = val.partition('=')
if op:
boxes[hsh(code)][code] = int(fl)
else:
code = val.removesuffix('-')
boxes[hsh(code)].pop(code, None)
return sum((b + 1)
* sum(n * fl for n, fl in enumerate(slts.values(), 1))
for b, slts in boxes.items())
print(hshmap(INPUT.split(',')))
```
*/
use indexmap::IndexMap;

fn compute(text: &str) -> Num {
fn compute_hash(text: &str) -> usize {
let arr = str_to_array(text);
arr.into_iter().map(hash).sum()
}

fn compute2(text: &str) -> Num {
fn compute_hashmap(text: &str) -> usize {
let arr = hashtable(&str_to_array(text));
arr.into_iter()
.enumerate()
.map(|(i, x)| {
x.values()
.enumerate()
.map(|(j, x)| (i + 1) * (j + 1) * x)
.sum::<Num>()
.sum::<usize>()
})
.sum()
}

#[inline]
fn str_to_array(text: &str) -> Vec<&str> {
text.trim().split(',').collect()
}

fn hash(text: &str) -> Num {
fn hash(text: &str) -> usize {
text.bytes()
.fold(0, |acc, x| ((acc + Num::from(x)) * 17) % 256)
.fold(0, |acc, x| ((acc + usize::from(x)) * 17) % 256)
}

fn hashtable<'a>(input: &[&'a str]) -> Vec<IndexMap<&'a str, Num>> {
let mut arr: Vec<_> = (0..256).map(|_| IndexMap::<&str, Num>::new()).collect();
fn hashtable<'a>(input: &[&'a str]) -> Vec<IndexMap<&'a str, usize>> {
let mut arr: Vec<_> = (0..256).map(|_| IndexMap::<&str, usize>::new()).collect();

for x in input {
if let Some((code, val)) = x.split_once('=') {
let val: Num = val.parse().unwrap();
let val: usize = val.parse().unwrap();
arr[hash(code)].insert(code, val);
} else if let Some((code, _)) = x.split_once('-') {
arr[hash(code)].shift_remove(code);
Expand All @@ -47,11 +82,11 @@ fn hashtable<'a>(input: &[&'a str]) -> Vec<IndexMap<&'a str, Num>> {

fn main() {
let text = std::fs::read_to_string("input/15.txt").unwrap();
let first_result = compute(&text);
println!("First = {first_result}");
let result = compute_hash(&text);
println!("HASH = {result}");

let second_result = compute2(&text);
println!("Second = {second_result}");
let result = compute_hashmap(&text);
println!("HASHMAP = {result}");
}

#[cfg(test)]
Expand All @@ -61,14 +96,14 @@ mod tests {
const INPUT: &str = "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7";

#[test]
fn test_first() {
let result = compute(INPUT);
fn test_hash() {
let result = compute_hash(INPUT);
assert_eq!(result, 1320);
}

#[test]
fn test_second() {
let result = compute2(INPUT);
fn test_hashmap() {
let result = compute_hashmap(INPUT);
assert_eq!(result, 145);
}
}

0 comments on commit 1bddc61

Please sign in to comment.