Compare commits

...

4 Commits

Author SHA1 Message Date
04eceded4f better errors 2023-12-13 16:29:26 +01:00
e1d2cb5f72 day 13: rust 2023-12-13 16:29:03 +01:00
5fa40357cd add loc 2023-12-13 16:28:46 +01:00
756f0fa9a0 rm redundant code 2023-12-13 16:28:07 +01:00
9 changed files with 249 additions and 54 deletions

16
10/README.md Normal file
View File

@ -0,0 +1,16 @@
# [Day 10](https://adventofcode.com/2023/day/10)
:gift::gift::gift::gift::gift::gift::gift::gift::gift::gift:
Today's language: **Rust**
Lines of code: **136**
Execution time: **0,003 s**
I used lots of simple bitwise operations because I might implement this solution later on my DIY 8-bit computer.
```shell
rustc day10.rs
./day10RUN
```
<!-- lots of bitwise operations -->

View File

@ -33,8 +33,6 @@ impl std::fmt::Display for Pos {
}
fn follow(tiles: &mut Vec<Vec<u8>>, start: &Pos, mut direction: u8) -> Option<usize> {
let xlen: usize = tiles[0].len(); // assume all are same size
let ylen: usize = tiles.len();
let mut steps: usize = 0;
let mut current = *start;
// mark the start tile as loop tile and with its directions
@ -124,12 +122,10 @@ fn main() {
}).collect());
}
let mut distance: usize = 0;
let mut num_tiles: usize = 0;
for direction in [N, S, E, W] {
println!("Starting at ({},{})", start_pos.x, start_pos.y);
if let Some(steps) = follow(&mut tiles, &start_pos, direction) {
assert!(steps % 2 == 0, "steps={} not even", steps);
num_tiles = steps;
distance = steps / 2;
break;
}

13
11/README.md Normal file
View File

@ -0,0 +1,13 @@
# [Day 11](https://adventofcode.com/2023/day/11)
:gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift:
Today's language: **Rust**
Lines of code: **66**
Execution time: **0,005 s**
```shell
rustc day11.rs
./day11RUN
```

22
13/README.md Normal file
View File

@ -0,0 +1,22 @@
# [Day 13](https://adventofcode.com/2023/day/13)
:gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift:
Today's language: **Rust**
Lines of code: **84**
Execution time: **0,002 s**
Once again, binary encoding is used to transform every line and every column of each pattern into one unsigned int.
The columns and lines are stored in one vector each. This means the same function can be used to find the reflection axis for both.
For task 2, we don't check whether two lines are equal, but whether they differ by 0 or 1 bit.
This approach is super fast since it has 0 heap allocations in loops and comparing two ints is way faster than comparing two strings.
```shell
rustc day13.rs
./day13RUN
```
<!-- binary encoding ftw -->

94
13/day13.rs Normal file
View File

@ -0,0 +1,94 @@
use std::io::{self, BufRead};
fn get_diff_bits_count(a: u32, b: u32) -> usize { // return 0 if equal, 1 if 1 bit is different, else 2
let diff = a ^ b;
if diff == 0 { return 0 }
if (diff & diff.overflowing_sub(1).0) == 0 { return 1 }
return 2;
}
fn find_reflection_axis(pattern: &Vec<u32>, has_smack: bool) -> Option<usize> {
for i in 1..pattern.len() {
let mut found_smack = false;
let diff = get_diff_bits_count(pattern[i-1], pattern[i]);
if has_smack && diff == 1 {
found_smack = true;
}
if diff == 0 || found_smack { // find two identical neighbors (or differing by 1 for task 2
let mut matching = true;
for j in 1..i.min(pattern.len() - i) { // check top and bottom if equal (or diff by 1 bit if has_smack)
let diff = get_diff_bits_count(pattern[i-1-j], pattern[i+j]);
if diff == 0 { continue; }
if has_smack && diff == 1 && !found_smack { // allow only one smack
found_smack = true;
continue;
}
matching = false;
break;
}
if matching && (!has_smack || (has_smack && found_smack)) { // require smack for task 2
return Some(i);
}
}
}
return None;
}
fn do_task(horizontal: &Vec<u32>, vertical: &Vec<u32>, has_smack: bool) -> usize {
let mut mirror_sum: usize = 0;
if let Some(x) = find_reflection_axis(&horizontal, has_smack) {
mirror_sum += x * 100;
}
if let Some(x) = find_reflection_axis(&vertical, has_smack) {
mirror_sum += x;
}
return mirror_sum;
}
fn main() {
// let input = "example.txt";
let input = "input.txt";
let lines = read_lines(&input);
let mut horizontal: Vec<u32> = Vec::new();
let mut vertical: Vec<u32> = Vec::new();
horizontal.reserve(20);
vertical.reserve(20);
let mut mirror_sum1: usize = 0;
let mut mirror_sum2: usize = 0;
let convert = |c| -> u32 { if c == '#' { 1 } else { 0 } };
for line in lines.map(|r| r.ok().unwrap()) {
if line.len() == 0 {
if horizontal.len() != 0 { // skip first time
mirror_sum1 += do_task(&horizontal, &vertical, false);
mirror_sum2 += do_task(&horizontal, &vertical, true);
}
horizontal.clear();
vertical.clear();
continue;
}
if horizontal.len() == 0 { // 0 for each column
(0..line.len()).for_each(|_| vertical.push(0));
}
horizontal.push(0);
for (i, n) in line.chars().map(|c| convert(c)).enumerate() {
*horizontal.last_mut().unwrap() |= (n << i);
vertical[i] |= (n << (horizontal.len()-1));
}
}
mirror_sum1 += do_task(&horizontal, &vertical, false);
mirror_sum2 += do_task(&horizontal, &vertical, true);
println!("Sum: (1): {}", mirror_sum1);
println!("Sum: (2): {}", mirror_sum2);
}
fn read_lines<P>(filename: P) -> io::Lines<io::BufReader<std::fs::File>>
where P: AsRef<std::path::Path>, {
return match std::fs::File::open(filename) {
Err(why) => panic!("Could not open file. {}", why),
Ok(file) => std::io::BufReader::new(file).lines()
};
}

View File

@ -13,5 +13,8 @@ This is a repository for my solutions for the [advent of code 2023](https://adve
| [07](07) | Rust | 210 | 0,007 s | not pretty, but pretty fast |
| [08](08) | Rust | 101 | 0,039 s | |
| [09](09) | Rust | 88 | 0,003 s | implemented triangle datatype |
| [10](10) | Rust | 136 | 0,003 s | lots of bitwise operations |
| [11](11) | Rust | 66 | 0,005 s | |
| [13](13) | Rust | 84 | 0,002 s | binary encoding ftw |
Lines of code are without blank lines and comments

View File

@ -3,6 +3,8 @@
Today's language: **LANG**
Lines of code: **LOC**
Execution time: **EXECTIME**
```shell

View File

@ -12,82 +12,123 @@ FMT_WARN='\e[33m%s\e[0m\n'
echo Making Readme of day $day in $readme
function find_lang {
# 1: fileext, 2: lang, 3: howto
sourcefile=$(ls $day_dir/*.$1 2> /dev/null)
# args: 1: fileext, 2: lang, 3: howto
sources=($(IFS=$'\n' ls $day_dir/*.$1 2> /dev/null))
[[ $? != 0 ]] && return
lang=$2
sourcefilebase=$(basename $sourcefile)
printf "$FMT_VAR" "Determined Langugae" "$2 ($sourcefilebase)"
sed -i "s/LANG/$2/" $readme
howto=$(echo "$3" | sed "s|SOURCE|$sourcefilebase|")
sed -i "s(HOWTORUN($howto(" $readme
loc=$(sed -r '/^\s*(#|\/\/|\/\*|;)/d;/^\s*$/d' $sourcefile | wc -l)
sed -i "s(LOC($loc(" $readme
if [[ ${#sources[@]} -gt 1 ]]; then
printf "$FMT_WARN" "Found multiple sources for language $2 (using first as main): ${sources[@]}"
fi
if [[ ${#sources[@]} -gt 1 ]]; then
printf "$FMT_WARN" "Found multiple sources for language $2 (using first as main): ${sources[@]}"
fi
mainsource=${sources[0]}
if [[ -z $lang ]]; then
lang=$2
else
lang=$lang,$2
fi
mainsource_base=$(basename $mainsource)
printf "$FMT_VAR" "Determined Language" "$2 ($mainsource_base)"
if [[ -n $3 ]]; then
howto=$(echo "$3" | sed "s|SOURCE|$mainsource_base|")
else
printf "$FMT_WARN" "No HOWTO provided for language $2"
fi
for file in ${sources[@]}; do
loc=$(( $loc + $(sed -r '/^\s*(#|\/\/|\/\*|;)/d;/^\s*$/d' "$file" | wc -l) ))
done
}
function get_time {
cd $day_dir
exe=$(find . -type f -executable)
if [[ -z $exe ]]; then
printf "$FMT_ERR" "Found no executable for day $day"
cd ..
return 2
fi
exe=$(basename $exe)
if [[ $(echo $exe | wc -w) != 1 ]]; then
printf "$FMT_ERR" "Found multiple or no executables for day $day: '$exe'"
printf "$FMT_ERR" "Found multiple executables for day $day: '$exe'"
cd ..
return 1
time=Error
else
time=$({ time ./$exe; } 2>&1)
if [[ $? != 0 ]]; then
printf "$FMT_ERR" "Execution error in './$exe' in '$(pwd)'. Output:"
printf "\e[34m"
echo -e "$time"
printf "\e[0m"
cd ..
return 1
fi
time=$(echo -e "$time" | tail -3 | head -1 | awk '{print $2}')
re='([[:digit:]]+)m([[:digit:]]+),([[:digit:]]+)s'
[[ $time =~ $re ]]
min=${BASH_REMATCH[1]}
sec=${BASH_REMATCH[2]}
msec=${BASH_REMATCH[3]}
if [[ $min != 0 ]]; then
time="$min m $sec,$msec s"
else
time="$sec,$msec s"
fi
cd ..
# elif [[ $sec != 0 ]]; then
# time="$sec,$msec s"
# else
# time="$((msec+0)) ms"
# fi
fi
time=$({ time ./$exe; } 2>&1)
if [[ $? != 0 ]]; then
printf "$FMT_ERR" "Execution error in './$exe' in '$(pwd)'. Output:"
printf "\e[34m"
echo -e "$time"
printf "\e[0m"
cd ..
return 1
fi
time=$(echo -e "$time" | tail -3 | head -1 | awk '{print $2}')
re='([[:digit:]]+)m([[:digit:]]+),([[:digit:]]+)s'
[[ $time =~ $re ]]
min=${BASH_REMATCH[1]}
sec=${BASH_REMATCH[2]}
msec=${BASH_REMATCH[3]}
if [[ $min != 0 ]]; then
time="$min m $sec,$msec s"
else
time="$sec,$msec s"
fi
# elif [[ $sec != 0 ]]; then
# time="$sec,$msec s"
# else
# time="$((msec+0)) ms"
# fi
cd ..
}
gifts=""
for i in $(seq $day); do gifts+=":gift:"; done
sed "s/DAY/$day/g" README.md.temp | sed "s/:gift:/$gifts/" > $day_dir/README.md
sed "s/DAY/$day/g" README.md.temp | sed "s/:gift:/$gifts/" > "$readme"
get_time
if [[ $? == 0 ]]; then
cd ..
printf "$FMT_VAR" "exectime" "$time"
sed -i "s/EXECTIME/$time/" $readme
sed -i "s/EXECTIME/$time/" "$readme"
else
cd ..
printf "$FMT_WARN" "No execution time determined"
sed -i '/.*EXECTIME.*/d' $readme
sed -i '/.*EXECTIME.*/d' "$readme"
fi
if [[ -z $1 ]]; then
printf "$FMT_WARN" "No comment provided"
sed -i "/<!-- COMMENT -->/d" $readme
sed -i '/<!-- COMMENT -->/d' "$readme" || echo "ERROR comment"
else
printf "$FMT_VAR" "Comment" "'$1'"
sed -i "s|COMMENT|$1|" $readme
sed -i "s|COMMENT|$1|" "$readme" || echo "ERROR comment2"
fi
dayexec="day${day_dir}"
loc=0
find_lang py Python "python3 SOURCE"
find_lang rs Rust "rustc SOURCE\n./day${day_dir}"
find_lang cpp C++ "g++ SOURCE -o day${day_dir}\n ./day${day_dir}"
find_lang rs Rust "rustc SOURCE\n./$dayexec"
find_lang cpp C++ "g++ SOURCE -o ${dayexec}\n./${dayexec}"
find_lang c C "gcc SOURCE -o ${dayexec}\n./${dayexec}"
find_lang java Java "javac Main.java\njava Main"
find_lang s Assembly ""
find_lang s65 Assembly "javac Main.java\njava Main"
find_lang awk Awk "awk -f SOURCE input.txt"
find_lang sh Bash "./SOURCE"
find_lang php PhP "php -S localhost:8000 -t .\nfirefox http://localhost:8000"
find_lang js Javascript ""
if [[ -z $lang ]]; then
printf "$FMT_WARN" "No languages found"
else
sed -i "s/LANG/$lang/" $readme
fi
if [[ -n $howto ]]; then
sed -i "s|HOWTO|$howto|" $readme
fi
if [[ $loc == 0 ]]; then
printf "$FMT_WARN" "No lines of code found"
else
sed -i "s(LOC($loc(" $readme
fi

View File

@ -2,8 +2,16 @@
table="| Day | Language | Lines of code | Execuction time | Comment |\n"
table+="|:---:|:---:| ---:| ---: |--- |\n"
for day in $(seq -f "%02g" 1 25); do
[[ ! -d "$day" ]] && continue
maxday=$(ls -d */ | sed -r 's|0*(.*)/|\1|g' | tail -1)
for day in $(seq -f "%02g" 1 $maxday); do
if [[ ! -d "$day" ]]; then
echo "Missing directory for day $day"
continue
fi
if [[ ! -f "$day/README.md" ]]; then
echo "Missing README for day $day"
continue
fi
# echo $day
lang=$(grep -E "Today's language:" $day/README.md | sed -r 's/.*\*\*(.+)\*\*.*/\1/')
exectime=$(grep -E "Execution time:" $day/README.md | sed -r 's/.*\*\*(.+)\*\*.*/\1/')