03 Bash
S=0
# read the input file line by line
while read line; do
# get the first half of the string
x1=${line:0:${#line}/2}
# second half
x2=${line:${#line}/2:${#line}}
# iterate over characters in the left half
for (( i=0; i<${#x1}; i++ )); do
# that is the character at position $i
ch=${x1:$i:1}
# if $ch contained in the string $x2?
if [[ "$x2" == *"$ch"* ]]; then
# convert chars to their ASCII values
n=$(printf '%d' "'$ch")
# a = 97 b = 98 ... A = 65 B = 66 ...
if ((n < 96)); then
# turn values 65... into values 27...
a=$((n-64+26))
S=$((S+a))
else
# turn values 97... into values 1...
a=$((n-96))
S=$((S+a))
fi
break
fi
done
done < "03.input"
echo "$S"
Second part
#!/bin/bash
# shebang is highly recommended
set -e # fail immediately
S=0 # sum
N=1 # line number
L1="" # next-to-previous line
L2="" # previous line
L3="" # current line
while read -r line; do
# update last three lines
L1=$L2
L2=$L3
L3=$line
# every 3rd line
if ((N%3==0)); then
# iterate over characters in $line string
for (( i=0; i<${#line}; i++ )); do
# get the $i-th character
ch=${line:$i:1}
# if $ch is both in the prev and the before-prev line
if [[ "$L2" == *"$ch"* && "$L1" == *"$ch"* ]]; then
# get the value with the ASCII trick
n=$(printf '%d' "'$ch")
if ((n < 96)); then
a=$((n-64+26))
S=$((S+a))
else
a=$((n-96))
S=$((S+a))
fi
break
fi
done
fi
((N++))
done < "03.input"
# print the result
echo "$S"
Pro tip
Always use shellcheck!
What I learned
- arithmetic context
- C-style for loop
- string manipulation
read
without-r
can mangle backslashes in input
published: 2022-12-03
last modified: 2023-01-21
https://vit.baisa.cz/notes/code/advent-of-code-2022/03/
last modified: 2023-01-21
https://vit.baisa.cz/notes/code/advent-of-code-2022/03/