:date: 2023-12-03 12:00
WTF????!?!! Everything works 100% fine except line 117. No reason. You can delete that line and the new 117 fails. You can chop off the first half of the data sent and then it works - including the problematic line that was 117. This is bonkers!! WTF is going on? I solved this by just manually overriding the errors from 117 and all the rest were correct.
Here's a sample of the output showing the situation. Each number is isolated and its previous and next line's cut from the position are shown before and after. Only on line 117, the current line is repeated instead of using the next line cut.
OK-3 ....3./..
OK-376 ...*..376......
OK-191 *.....191......
115 | .........&....*..%........................................183......*......61................/........657..........163............255........
OK-183 ......183....*.
OK-61 ..#..61.....
---657 ......657......
OK-163 .*....163......
OK-255 ......255.....*
116 | ..674.......46..............392..251....507.................*.248...74..........+...775.97.....222.........%..........135...950.....*.......
OK-674 ......674....*.
OK-46 ...*.46.....
OK-392 ......392..*...
---251 ......251......
OK-507 ......507...*..
OK-248 ......248...#..
OK-74 *....74.....
---775 ......775......
---97 .....97.....
---222 ......222......
OK-135 ......135....*.
OK-950 ......950.&....
117 | ....*...........*967..533...*............*......949..245.276...#.........*.....728...................677..137.....*.....*..&........522.....
OK-967 .....*967.*967.
---533 ......533..533.
---949 ......949..949.
---245 ......245..245.
OK-276 ....*.276..276.
OK-728 ..+...728..728.
---677 ......677..677.
OK-137 ..%...137..137.
OK-522 .*....522..522.
118 | ...367.......196.......$..239..........510.748..*............/...481..722....................800........*........735..268...................
OK-367 ..*...367......
OK-196 ....*.196......
OK-239 ...*..239......
OK-510 ...*..510......
---748 ......748......
OK-481 ......481...*..
OK-722 ....*.722......
OK-800 ......800.%....
OK-735 ..*...735......
OK-268 ...*..268......
119 | .........442...................111...............752........567...*.........*..........696..%............790................................
---442 ......442......
---111 ......111......
#!/bin/bash
T=0
I=$1
LINES=$(wc -l $I)
for L in $(seq $(wc -l < $I)); do # Current line number.
Z=$(sed -n ${L}p $I); # Current line.
echo "$L | $Z" # Print original current line.
DOTSTATE=1
POS=1
S=$POS
set -f # Because some of the syms are stars which glob when alone in $($C)
for C in $( fold -w1 <<<${Z} ); do
if echo $C | grep '[^0-9]' >/dev/null ; then # Character is not a digit.
if test $DOTSTATE == "0"; then
E=$POS
N=$(cut -c ${S}-${E} <<<"$Z" )
if test $L -eq 1; then
ZP=$(sed -n ${L}p $I)
else
ZP=$(sed -n $((L-1))p $I)
fi
if test $L -eq $LINES; then
ZN=$(sed -n ${L}p $I)
else
ZN=$(sed -n $((L+1))p $I)
fi
OKS="$(cut -c ${S}-${E} <<<$ZP )${N}$(cut -c ${S}-${E} <<<$ZN )"
THENUMBER=$(tr -cd [0-9] <<<$N)
if echo "$OKS" | grep -v '^[0-9.][0-9.]*$' >/dev/null; then
echo "OK-$THENUMBER $OKS"
T=$(( $T + $THENUMBER ))
else
echo "---$THENUMBER $OKS"
fi
fi
DOTSTATE=1
else
if test $DOTSTATE == "1"; then
if test "$POS" -gt "1" ; then
S=$(( $POS - 1 ))
else
S=$POS
fi
fi
DOTSTATE=0
fi
POS=$(( $POS + 1 ))
done
#Add final if number is in final position
if test $DOTSTATE == "0"; then
E=$POS
N=$(cut -c ${S}-${E} <<<"$Z" )
#echo "Start: $S End: $E Cut: $N"
echo "FINAL: $N"
OKS="$(cut -c ${S}-${E} <<<$ZP )${N}$(cut -c ${S}-${E} <<<$ZN )"
THENUMBER=$(tr -cd [0-9] <<<$N)
if echo "$OKS" | grep -v '^[0-9.][0-9.]*$' >/dev/null; then
#THENUMBER=$(tr -cd [0-9] <<<$N)
echo "OK-$THENUMBER $OKS"
T=$(( $T + $THENUMBER ))
else
echo "---$THENUMBER $OKS"
fi
if test $L -eq 1; then
ZP=$(sed -n ${L}p $I)
else
ZP=$(sed -n $((L-1))p $I)
fi
if test $L -eq $LINES; then
ZN=$(sed -n ${L}p $I)
else
ZN=$(sed -n $((L+1))p $I)
fi
#echo "$(cut -c ${S}-${E} <<<$ZP )${N}$(cut -c ${S}-${E} <<<$ZN )"
fi
#read -p "Press enter to continue..."
done # looping over every line
echo "TOTAL: $T"
That's so weird. But... moving on!
This was nuts too. I'll just post the whole Python script to demonstrate how busy these solutions can be. I'm pretty sure I'm not overlooking tons of obvious consolidations into more elegant code. This problem just had tons of weird cases to worry about.
#!/usr/bin/python
# Correct: 78915902
R= list()
with open('input3','r') as f:
for l in f:
C= l.strip()
CL= list(C)
for i,c in enumerate(C):
if not ((ord(c) > 47) and (ord(c) < 58)):
if c != '.' and c != '*':
CL[i]= '.'
R.append(CL)
def find_top_row_pair(R,r,c):
digits1,digits2= str(),str()
d= c+1
still_in_number= True
while still_in_number:
try:
if R[r-1][d].isdigit():
digits2 += R[r-1][d]
#print(f"D2:{digits2}")
d+=1
else:
still_in_number= False
except IndexError:
still_in_number= False
d= c-1
still_in_number= True
while still_in_number:
try:
if R[r-1][d].isdigit():
digits1 += R[r-1][d]
d-=1
else:
still_in_number= False
except IndexError:
still_in_number= False
digits1= digits1[::-1]
print(f"{digits1}x{digits2}")
return int(digits1) * int(digits2)
def find_bot_row_pair(R,r,c):
digits1,digits2= str(),str()
d= c+1
still_in_number= True
while still_in_number:
try:
if R[r+1][d].isdigit():
digits2 += R[r+1][d]
d+=1
else:
still_in_number= False
except IndexError:
still_in_number= False
d= c-1
still_in_number= True
while still_in_number:
try:
if R[r+1][d].isdigit():
digits1 += R[r+1][d]
d-=1
else:
still_in_number= False
except IndexError:
still_in_number= False
digits1= digits1[::-1]
print(f"{digits1}x{digits2}")
return int(digits1) * int(digits2)
def find_same_line_pair(R,r,c):
d1= find_single_right(R,r,c)
d2= find_single_left(R,r,c)
print(f"{d1}x{d2}")
return int(d1) * int(d2)
def find_single_on_top(R,r,c):
digits= str()
d= c-1
still_in_number= True
while still_in_number:
try:
if R[r-1][d].isdigit():
digits += R[r-1][d]
d-=1
else:
still_in_number= False
except IndexError:
still_in_number= False
digits= digits[::-1] # These were searched from center to left. Reverse now.
if R[r-1][c].isdigit():
d= c # Start looking again directly above.
else:
d= c+1 # Start looking upper right.
still_in_number= True
while still_in_number:
try:
if R[r-1][d].isdigit():
digits += R[r-1][d]
d+=1
else:
still_in_number= False
except IndexError:
still_in_number= False
return int(digits)
def find_single_on_bot(R,r,c):
digits= str()
d= c-1
still_in_number= True
while still_in_number:
try:
if R[r+1][d].isdigit():
digits += R[r+1][d]
d-=1
else:
still_in_number= False
except IndexError:
still_in_number= False
digits= digits[::-1] # These were searched from center to left. Reverse now.
if R[r+1][c].isdigit():
d= c # Start looking again directly below.
else:
d= c+1 # Start looking lower right.
still_in_number= True
while still_in_number:
try:
if R[r+1][d].isdigit():
digits += R[r+1][d]
d+=1
else:
still_in_number= False
except IndexError:
still_in_number= False
return int(digits)
def find_single_left(R,r,c):
digits= str()
d= c-1
still_in_number= True
while still_in_number:
try:
if R[r][d].isdigit():
digits += R[r][d]
d-=1
else:
still_in_number= False
except IndexError:
still_in_number= False
digits= digits[::-1] # These were searched from center to left. Reverse now.
return int(digits)
def find_single_right(R,r,c):
digits= str()
d= c+1
still_in_number= True
while still_in_number:
try:
if R[r][d].isdigit():
digits += R[r][d]
d+=1
else:
still_in_number= False
except IndexError:
still_in_number= False
return int(digits)
T= 0
for ir,r in enumerate(R):
for ic,c in enumerate(r):
if R[ir][ic] == '*':
top_row_pair= R[ir-1][ic-1].isdigit() and not R[ir-1][ic].isdigit() and R[ir-1][ic+1].isdigit()
bot_row_pair= R[ir+1][ic-1].isdigit() and not R[ir+1][ic].isdigit() and R[ir+1][ic+1].isdigit()
one_on_top= R[ir-1][ic-1].isdigit() or R[ir-1][ic].isdigit() or R[ir-1][ic+1].isdigit()
one_on_bot= R[ir+1][ic-1].isdigit() or R[ir+1][ic].isdigit() or R[ir+1][ic+1].isdigit()
both_same_line= R[ir][ic-1].isdigit() and R[ir][ic+1].isdigit()
if top_row_pair:
T += find_top_row_pair(R,ir,ic)
elif bot_row_pair:
T += find_bot_row_pair(R,ir,ic)
elif one_on_top and one_on_bot:
A= find_single_on_top(R,ir,ic)
B= find_single_on_bot(R,ir,ic)
T+= (A*B)
elif both_same_line:
T += find_same_line_pair(R,ir,ic)
elif one_on_top and R[ir][ic-1].isdigit():
A= find_single_on_top(R,ir,ic)
B= find_single_left(R,ir,ic)
T+= (A*B)
elif one_on_bot and R[ir][ic-1].isdigit():
A= find_single_on_bot(R,ir,ic)
B= find_single_left(R,ir,ic)
T+= (A*B)
elif one_on_top and R[ir][ic+1].isdigit():
A= find_single_on_top(R,ir,ic)
B= find_single_right(R,ir,ic)
T+= (A*B)
elif one_on_bot and R[ir][ic+1].isdigit():
A= find_single_on_bot(R,ir,ic)
B= find_single_right(R,ir,ic)
T+= (A*B)
else: # It's a star but only one number near.
pass
print(f"TOTAL: {T}")
That's so baroque it's astonishing that it works. But I'm pretty sure most of that is necessary.