My day 3 code ended up being a kludge. I took the liberty of encoding the dimensions in advance and just using brute-force. Not particularly proud of the code…
Spoiler Alert - Day 3
program day3
implicit none
!integer, parameter :: M = 10
integer, parameter :: M = 140
character(len=M) :: rows(M), cm(M), pm(M)
integer :: fu, i, n, t, j
integer :: tl, tu, rl, ru
integer :: col, ns, ne, psum, pnum
integer :: z(1000000), k, gii, gjj
integer :: zi(1000000), zj(1000000)
integer :: gi(1000000), gj(1000000), gsum
logical :: zb(1000000)
!open(newunit=fu,file="day3_test.txt",status='old')
open(newunit=fu,file="day3_input.txt",status='old')
read(fu,'(A140)') (rows(i), i=1,M)
close(fu)
cm = repeat('F',M)
do i = 1, size(rows)
print *, rows(i), ' ', cm(i)
end do
! Mask punctuation symbols
do i = 1, size(rows)
n = 0
do
t = next_punct(rows(i)(n+1:))
if (t > 0) cm(i)(n+t:n+t) = 'T'
n = n + t
if (t == 0) exit
end do
end do
print *, "Punctuations masks, DONE!"
pm = repeat('N',M)
! Part mask
do i = 1, size(rows)
n = 0
rl = max(1,i-1)
ru = min(M,i+1)
do
t = scan(cm(i)(n+1:),'T')
if (t > 0) then
tl = max(1,n+t-1)
tu = min(M,n+t+1)
do j = rl, ru
pm(j)(tl:tu) = 'PPP'
end do
end if
n = n + t
if (t == 0) exit
end do
end do
print *, "Part masks, DONE!"
k = 0
psum = 0
do i = 1, size(rows)
col = 0
print *, "ROW ", i
print *, rows(i)
do
ns = scan(rows(i)(col+1:),'0123456789')
ne = verify(rows(i)(col+ns:),'0123456789')
if (ns > 0) then
tl = col+ns
tu = merge(col+ns+ne-2,len(rows(i)),ne > 0)
!print *, rows(i)(tl:tu)
if (any([((pm(i)(j:j) == 'P'),j=tl,tu)])) then
print *, rows(i)(tl:tu), " is a part"
read(rows(i)(tl:tu),*) pnum
psum = psum + pnum
if (gears_nearby(i,tl,tu,gii,gjj)) then
k = k + 1
z(k) = pnum
zi(k) = i
zj(k) = tl
gi(k) = gii
gj(k) = gjj
end if
else
print *, rows(i)(tl:tu), " is not a part"
end if
end if
col = min(col + ns + ne - 2, M)
if (ns == 0 .or. ne == 0) exit
end do
!if (i == 16) stop
end do
print *, "Part number scanning, DONE!"
write(*,*)
do i = 1, size(rows)
print *, rows(i), ' ', cm(i), ' ', pm(i)
end do
write(*,*)
write(*,*) "Sum of part numbers = ", psum
!
! Find gear number ratio
!
print *, "Numbers and gears"
zb = .false.
do i = 1, k
print *, z(i), zi(i), zj(i), gi(i), gj(i)
end do
gsum = 0
do i = 1, k
if (zb(i)) cycle
do j = i+1, k
if (gi(i) == gi(j) .and. gj(i) == gj(j)) then
print *, "Found gears: ", z(i), z(j)
gsum = gsum + z(i) * z(j)
zb(i) = .true.
zb(j) = .true.
exit
end if
end do
end do
print *, "Gear sum = ", gsum
contains
function next_punct(str)
character(len=*), intent(in) :: str
integer :: next_punct
next_punct = verify(str,'0123456789.')
end function
logical function gears_nearby(i,tl,tu,gi,gj)
integer, intent(in) :: i, tl, tu
integer, intent(out) :: gi, gj
integer :: ii, jj
gears_nearby = .false.
do ii = i-1,i+1
do jj = tl-1, tu + 1
if (ii < 1 .or. ii > M) cycle
if (jj < 1 .or. jj > M) cycle
if (rows(ii)(jj:jj) == '*') then
gears_nearby = .true.
gi = ii
gj = jj
return
end if
end do
end do
end function
end program