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> { 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 steps: usize = 0;
let mut current = *start; let mut current = *start;
// mark the start tile as loop tile and with its directions // mark the start tile as loop tile and with its directions
@ -124,12 +122,10 @@ fn main() {
}).collect()); }).collect());
} }
let mut distance: usize = 0; let mut distance: usize = 0;
let mut num_tiles: usize = 0;
for direction in [N, S, E, W] { for direction in [N, S, E, W] {
println!("Starting at ({},{})", start_pos.x, start_pos.y); println!("Starting at ({},{})", start_pos.x, start_pos.y);
if let Some(steps) = follow(&mut tiles, &start_pos, direction) { if let Some(steps) = follow(&mut tiles, &start_pos, direction) {
assert!(steps % 2 == 0, "steps={} not even", steps); assert!(steps % 2 == 0, "steps={} not even", steps);
num_tiles = steps;
distance = steps / 2; distance = steps / 2;
break; 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 | | [07](07) | Rust | 210 | 0,007 s | not pretty, but pretty fast |
| [08](08) | Rust | 101 | 0,039 s | | | [08](08) | Rust | 101 | 0,039 s | |
| [09](09) | Rust | 88 | 0,003 s | implemented triangle datatype | | [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 Lines of code are without blank lines and comments

View File

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

View File

@ -12,82 +12,123 @@ FMT_WARN='\e[33m%s\e[0m\n'
echo Making Readme of day $day in $readme echo Making Readme of day $day in $readme
function find_lang { function find_lang {
# 1: fileext, 2: lang, 3: howto # args: 1: fileext, 2: lang, 3: howto
sourcefile=$(ls $day_dir/*.$1 2> /dev/null) sources=($(IFS=$'\n' ls $day_dir/*.$1 2> /dev/null))
[[ $? != 0 ]] && return [[ $? != 0 ]] && return
lang=$2 if [[ ${#sources[@]} -gt 1 ]]; then
sourcefilebase=$(basename $sourcefile) printf "$FMT_WARN" "Found multiple sources for language $2 (using first as main): ${sources[@]}"
printf "$FMT_VAR" "Determined Langugae" "$2 ($sourcefilebase)" fi
sed -i "s/LANG/$2/" $readme if [[ ${#sources[@]} -gt 1 ]]; then
howto=$(echo "$3" | sed "s|SOURCE|$sourcefilebase|") printf "$FMT_WARN" "Found multiple sources for language $2 (using first as main): ${sources[@]}"
sed -i "s(HOWTORUN($howto(" $readme fi
loc=$(sed -r '/^\s*(#|\/\/|\/\*|;)/d;/^\s*$/d' $sourcefile | wc -l) mainsource=${sources[0]}
sed -i "s(LOC($loc(" $readme 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 { function get_time {
cd $day_dir cd $day_dir
exe=$(find . -type f -executable) 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) exe=$(basename $exe)
if [[ $(echo $exe | wc -w) != 1 ]]; then 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 .. cd ..
return 1 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 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="" gifts=""
for i in $(seq $day); do gifts+=":gift:"; done 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 get_time
if [[ $? == 0 ]]; then if [[ $? == 0 ]]; then
cd ..
printf "$FMT_VAR" "exectime" "$time" printf "$FMT_VAR" "exectime" "$time"
sed -i "s/EXECTIME/$time/" $readme sed -i "s/EXECTIME/$time/" "$readme"
else else
cd ..
printf "$FMT_WARN" "No execution time determined" printf "$FMT_WARN" "No execution time determined"
sed -i '/.*EXECTIME.*/d' $readme sed -i '/.*EXECTIME.*/d' "$readme"
fi fi
if [[ -z $1 ]]; then if [[ -z $1 ]]; then
printf "$FMT_WARN" "No comment provided" printf "$FMT_WARN" "No comment provided"
sed -i "/<!-- COMMENT -->/d" $readme sed -i '/<!-- COMMENT -->/d' "$readme" || echo "ERROR comment"
else else
printf "$FMT_VAR" "Comment" "'$1'" printf "$FMT_VAR" "Comment" "'$1'"
sed -i "s|COMMENT|$1|" $readme sed -i "s|COMMENT|$1|" "$readme" || echo "ERROR comment2"
fi fi
dayexec="day${day_dir}"
loc=0
find_lang py Python "python3 SOURCE" find_lang py Python "python3 SOURCE"
find_lang rs Rust "rustc SOURCE\n./day${day_dir}" find_lang rs Rust "rustc SOURCE\n./$dayexec"
find_lang cpp C++ "g++ SOURCE -o day${day_dir}\n ./day${day_dir}" 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="| Day | Language | Lines of code | Execuction time | Comment |\n"
table+="|:---:|:---:| ---:| ---: |--- |\n" table+="|:---:|:---:| ---:| ---: |--- |\n"
for day in $(seq -f "%02g" 1 25); do maxday=$(ls -d */ | sed -r 's|0*(.*)/|\1|g' | tail -1)
[[ ! -d "$day" ]] && continue 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 # echo $day
lang=$(grep -E "Today's language:" $day/README.md | sed -r 's/.*\*\*(.+)\*\*.*/\1/') 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/') exectime=$(grep -E "Execution time:" $day/README.md | sed -r 's/.*\*\*(.+)\*\*.*/\1/')