Skip to content

Commit 71fedd4

Browse files
committed
20: Finally get the last star
The lack of 2D arrays is terrible. Named functions variables kind of work to bypass that. Lots of subshells and calls to tac/rev because I got lazy.
1 parent ac5c056 commit 71fedd4

File tree

2 files changed

+142
-19
lines changed

2 files changed

+142
-19
lines changed

20.sh

Lines changed: 141 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,145 @@
11
#! /usr/bin/env bash
2+
rotate() {
3+
local -n in=$1 out=$2
4+
local len=${#in[0]}
5+
for i in "${idx[@]:1:len}"; do
6+
out[len-i]=$(printf "%s\n" "${in[@]}" | cut -c"$i" | tr -d '\n' )
7+
done
8+
}
9+
210
IFS=$'\n'
3-
A=($(tr '.' '_' < "${1:-20.txt}"))
4-
T=($(printf "%s\n" "${A[@]}" | grep -o "[0-9]*" ))
5-
U=($(printf "%s\n" "${A[@]}" | grep -A1 T | grep -E "[_#]" ))
6-
D=($(printf "%s\n" "${A[@]}" T | grep -B1 T | grep -E "[_#]" ))
7-
IFS=$' T' L=($(printf "%s\n" "${A[@]}" | cut -c1 | tail +2 | tr -d '\n '))
8-
IFS=$' :' R=($(printf "%s\n" "${A[@]}" | cut -c${#U[1]} | tail +2 | tr -d '\n '))
9-
IFS=$'\n'
10-
Ur=($(printf "%s\n" "${U[*]}" | rev))
11-
Dr=($(printf "%s\n" "${D[*]}" | rev))
12-
Lr=($(printf "%s\n" "${L[*]}" | rev))
13-
Rr=($(printf "%s\n" "${R[*]}" | rev))
14-
ENDS=() x=0
11+
A=($(tr '.' '_' < "${1:-20.txt}")) # . is a wildcard
12+
idx=(${!A[@]})
13+
rotate A A270
14+
ENDS=() NUM=() D=() U=() len=${#A[1]}
15+
for ((i=0;i<${#A[@]};i+=len+1)); do
16+
NUM+=(${A[i]//[^0-9]})
17+
U+=(${A[i+1]})
18+
D+=(${A[i+len]})
19+
done
20+
IFS=$' \n'
21+
L=(${A270[-1]//[^_#]/ })
22+
R=(${A270[0]//[^_#]/ })
23+
Ur=($(printf "%s\n" "${U[@]}" | rev))
24+
Dr=($(printf "%s\n" "${D[@]}" | rev))
25+
Lr=($(printf "%s\n" "${L[@]}" | rev))
26+
Rr=($(printf "%s\n" "${R[@]}" | rev))
27+
N="${#U[@]}"
28+
for n in "${idx[@]:2:N}";do ((n*n==N)) && break; done
29+
printf -v ALL "%s\n" "${U[@]}" "${R[@]}" "${Dr[@]}" "${Lr[@]}"
30+
IFS=$' :\n'
1531
for i in "${!U[@]}"; do
16-
x=$(printf "%s\n" "${U[*]}" "${Ur[*]}" "${D[*]}" "${Dr[*]}" "${L[*]}" "${Lr[*]}" "${R[*]}" "${Rr[*]}" | grep -c -e "${U[i]}" -e "${Dr[i]}" -e "${Lr[i]}" -e "${R[i]}" )
17-
[ "$x" = 6 ] && ENDS+=("${T[i]}")
32+
x=()
33+
while read -r k _; do
34+
(((--k%N)!=i)) && x+=("$((k/N)):$((k%N))")
35+
done < <(echo "$ALL" | grep -n -E -x "(${U[i]}|${R[i]}|${Dr[i]}|${Lr[i]}|${Ur[i]}|${Rr[i]}|${D[i]}|${L[i]})")
36+
PIC[i]=${x[*]}
37+
case ${#x[*]} in
38+
2) ENDS[i]="${NUM[i]}";;
39+
3|4) : ;;
40+
*) echo "ERROR($i): ${x[*]}"; break;;
41+
esac
42+
done
43+
IFS=$' \n'
44+
printf -v prod "*%s" "${ENDS[@]}"; prod=${prod:1}
45+
echo "20A: $prod=$((prod))"
46+
GRID=() FOUND=() ROT=() s1=() s2=()
47+
index=(${!ENDS[@]})
48+
next=${index[0]}
49+
50+
# Top row. Rotation is based on neighbors, so that has to wait
51+
FOUND[next]=0; GRID[0]=$next
52+
for i in "${idx[@]:1:n-1}"; do
53+
for k in ${PIC[next]//?:}; do
54+
[[ -n ${FOUND[k]} || ${PIC[k]} == *:*:*:*:* ]] && continue
55+
next=$k; FOUND[k]=$i; GRID[i]=$k; break
56+
done
57+
done
58+
#Rows 2-12. Exactly one side should not be done already
59+
for i in "${idx[@]:n:N-n}"; do
60+
for j in ${PIC[GRID[i-n]]}; do
61+
k=${j/?:}; [[ -n ${FOUND[k]} ]] && continue
62+
FOUND[k]=$i; GRID[i]=$k; ROT[i]=${j/:*}; break
63+
done
64+
done
65+
# Circle back to the first row
66+
for i in "${idx[@]:0:n-1}"; do
67+
if [[ ${PIC[GRID[i+n]]} =~ ([0-9]):${GRID[i]} ]]; then
68+
ROT[i]=$(( BASH_REMATCH[1]+2 ))
69+
fi
70+
done
71+
72+
edges=(R Dr Lr U L Ur Rr D)
73+
segde=(L Ur Rr D R Dr Lr U) # flipped
74+
get_edges() {
75+
local -n both=$1 left=${edges[$3]} right=${segde[$3]}
76+
both=(${left[$2]} ${right[$2]})
77+
}
78+
# Make sure the left/right sides match
79+
for ((i=1 ; i < N; i+=2)); do
80+
get_edges s1 "${GRID[i-1]}" ${ROT[i-1]}
81+
get_edges s2 "${GRID[i]}" ${ROT[i]}
82+
if [[ ${s1[0]} == "${s2[1]}" ]]; then ((ROT[i]-=4, ROT[i-1]-=4)) # flip both
83+
elif [[ ${s1[1]} == "${s2[1]}" ]]; then ((ROT[i]-=4)) # flip right
84+
elif [[ ${s1[0]} == "${s2[0]}" ]]; then ((ROT[i-1]-=4)) # flip left
85+
elif [[ ${s1[1]} == "${s2[0]}" ]]; then : # no flip
86+
else echo "ERROR: idx $((i-1)) and $i don't match: ${s1[*]} != ${s2[*]}"
87+
fi
88+
done
89+
90+
rot0(){
91+
local X=() offset=$((11*$1))
92+
for i in {1..8}; do X+=(${A[offset+i+1]:1:8}); done
93+
printf "%s\n" "${X[@]}"
94+
}
95+
rot270() {
96+
local X=() offset=$((11*$1))
97+
for i in {1..8}; do X+=(${A270[i]:offset+2:8}); done
98+
printf "%s\n" "${X[@]}"
99+
}
100+
rot180(){ rot0 "$@" | tac | rev; }
101+
rot90(){ rot270 "$@" | tac | rev; }
102+
flip0() { rot0 "$@" | rev; }
103+
flip270() { rot270 "$@" | rev; }
104+
flip180() { rot0 "$@" | tac; }
105+
flip90() { rot270 "$@" | tac; }
106+
TOTAL=() FINAL=() FINAL270=()
107+
TRANSFORM=(flip0 flip270 flip180 flip90 rot0 rot270 rot180 rot90)
108+
for i in "${!GRID[@]}"; do
109+
TOTAL+=($(${TRANSFORM[ROT[i]]} "${GRID[i]}"))
110+
done
111+
112+
# Assemble image
113+
for ((i=0; i < n; ++i)); do
114+
for ((j=0; j < 8; ++j)); do
115+
for ((k=0; k < n; ++k)); do
116+
FINAL[8*i+j]+=${TOTAL[8*n*i+j+k*8]}
117+
done
118+
done
119+
done
120+
rotate FINAL FINAL270
121+
monster="..................(#..{77}#....##....##....###.{77}.#..#..#..#..#..#...)"
122+
monsterlen=${monster//[^\#]}; monsterlen=${#monsterlen}
123+
regex=${monster/................../[_\#]\{18\}} # no newline at start
124+
i=0
125+
printf -v "MAP[i++]" "%s\n" "${FINAL[@]}"
126+
MAP[i++]=$(printf "%s\n" "${FINAL[@]}" | tac)
127+
MAP[i++]=$(printf "%s\n" "${FINAL[@]}" | rev| tac)
128+
MAP[i++]=$(printf "%s\n" "${FINAL[@]}" | rev)
129+
printf -v "MAP[i++]" "%s\n" "${FINAL270[@]}"
130+
MAP[i++]=$(printf "%s\n" "${FINAL270[@]}" | tac)
131+
MAP[i++]=$(printf "%s\n" "${FINAL270[@]}" | rev| tac)
132+
MAP[i++]=$(printf "%s\n" "${FINAL270[@]}" | rev)
133+
hashes=${MAP[0]//[^#]}; total=${#hashes} found=0
134+
for map in "${MAP[@]}"; do
135+
if [[ $map =~ $regex ]]; then
136+
break
137+
fi
138+
done
139+
140+
# Change the head of the monster so it is only found once
141+
while [[ $map =~ $regex ]]; do
142+
((++found < 200)) || { echo "Error: replace is failing ($found monsters)"; break; }
143+
map=${map/"${BASH_REMATCH[1]}"/"O${BASH_REMATCH[1]:1}"}
18144
done
19-
printf -v sum "*%s" "${ENDS[@]}"; sum=${sum:1}
20-
echo "20A: $sum=$((sum))"
145+
echo "20B: $total-$monsterlen*$found = $((total-monsterlen*found))"

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ Description of what I'm doing. Contains spoilers....
102102

103103
### 20.sh
104104
1. Slice and dice all permutations of the edges into arrays. Grep each tile against all permutations of edges. Convert line number to index/rotation. The ones with only 2 matches are corners. The ones with 3 are edges. Use that to assemble the image.
105-
2. Not done yet: Once the picture is assembled, use a multi-line regex to find the monsters. Then count.
105+
2. Almost impossible in bash. The grep gave me the rotation, but not which tiles needed flipping. A second step compares left and right sides of each pair of tiles to decide which ones must be flipped. Once the picture is assembled, use a multi-line bash regex to find a monster. Modify one char to not trigger again on that monster. Repeat until no more monsters are found. Then count.
106106

107107
### 21.sh
108108
Grep, sort, count
@@ -123,5 +123,3 @@ Description of what I'm doing. Contains spoilers....
123123

124124
### 25.sh
125125
1. While loop for 15M rounds. Yay. Awk finishes in seconds.
126-
2. I need to complete 20-2 to get this one. Nope.
127-

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy