Compare commits

..

No commits in common. "04eceded4fa63b9e0077994696d7c457e5f709ef" and "a08c04717850c11a2222d491d92b64127ab7095b" have entirely different histories.

9 changed files with 53 additions and 248 deletions

View File

@ -1,16 +0,0 @@
# [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,6 +33,8 @@ 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
@ -122,10 +124,12 @@ 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;
} }

View File

@ -1,13 +0,0 @@
# [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
```

View File

@ -1,22 +0,0 @@
# [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 -->

View File

@ -1,94 +0,0 @@
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,8 +13,5 @@ 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,8 +3,6 @@
Today's language: **LANG** Today's language: **LANG**
Lines of code: **LOC**
Execution time: **EXECTIME** Execution time: **EXECTIME**
```shell ```shell

View File

@ -12,123 +12,82 @@ 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 {
# args: 1: fileext, 2: lang, 3: howto # 1: fileext, 2: lang, 3: howto
sources=($(IFS=$'\n' ls $day_dir/*.$1 2> /dev/null)) sourcefile=$(ls $day_dir/*.$1 2> /dev/null)
[[ $? != 0 ]] && return [[ $? != 0 ]] && return
if [[ ${#sources[@]} -gt 1 ]]; then lang=$2
printf "$FMT_WARN" "Found multiple sources for language $2 (using first as main): ${sources[@]}" sourcefilebase=$(basename $sourcefile)
fi printf "$FMT_VAR" "Determined Langugae" "$2 ($sourcefilebase)"
if [[ ${#sources[@]} -gt 1 ]]; then sed -i "s/LANG/$2/" $readme
printf "$FMT_WARN" "Found multiple sources for language $2 (using first as main): ${sources[@]}" howto=$(echo "$3" | sed "s|SOURCE|$sourcefilebase|")
fi sed -i "s(HOWTORUN($howto(" $readme
mainsource=${sources[0]} loc=$(sed -r '/^\s*(#|\/\/|\/\*|;)/d;/^\s*$/d' $sourcefile | wc -l)
if [[ -z $lang ]]; then sed -i "s(LOC($loc(" $readme
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 executables for day $day: '$exe'" printf "$FMT_ERR" "Found multiple or no executables for day $day: '$exe'"
cd .. cd ..
return 1 return 1
fi time=Error
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 else
time="$sec,$msec s" 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
# 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/" > "$readme" sed "s/DAY/$day/g" README.md.temp | sed "s/:gift:/$gifts/" > $day_dir/README.md
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" || echo "ERROR comment" sed -i "/<!-- COMMENT -->/d" $readme
else else
printf "$FMT_VAR" "Comment" "'$1'" printf "$FMT_VAR" "Comment" "'$1'"
sed -i "s|COMMENT|$1|" "$readme" || echo "ERROR comment2" sed -i "s|COMMENT|$1|" $readme
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./$dayexec" find_lang rs Rust "rustc SOURCE\n./day${day_dir}"
find_lang cpp C++ "g++ SOURCE -o ${dayexec}\n./${dayexec}" find_lang cpp C++ "g++ SOURCE -o day${day_dir}\n ./day${day_dir}"
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,16 +2,8 @@
table="| Day | Language | Lines of code | Execuction time | Comment |\n" table="| Day | Language | Lines of code | Execuction time | Comment |\n"
table+="|:---:|:---:| ---:| ---: |--- |\n" table+="|:---:|:---:| ---:| ---: |--- |\n"
maxday=$(ls -d */ | sed -r 's|0*(.*)/|\1|g' | tail -1) for day in $(seq -f "%02g" 1 25); do
for day in $(seq -f "%02g" 1 $maxday); do [[ ! -d "$day" ]] && continue
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/')