Actual 2023 day 12 solution

More aggressively memoised
main
Petra 2023-12-16 14:44:41 +13:00
parent 2f8f875990
commit a0efdb9cce
1 changed files with 27 additions and 56 deletions

View File

@ -7,6 +7,7 @@ program day12
character(max_chars) :: fline
character(max_chars) :: springs, spt
integer :: cache(1:20, 1:300)
integer(kind=b_kind) :: cache2(0:100, 0:1000, 1:1000)
integer :: tn_spr, n_springs
integer :: n_arguments
integer :: n_repeats
@ -31,7 +32,7 @@ program day12
stop
end if
open(10, file=fname)
total_valid = 0
total_valid = 0_b_kind
do i=1,max_rows
read(10, "(a)", iostat=istat) fline
strlen = len_trim(fline)
@ -76,8 +77,12 @@ program day12
print *, "Number of wildcards: ", num_wc
print *, "Wildcard Combinations: ", 2**num_wc
cache = -1
cache2 = -1_b_kind
val = nvalid(springs, n_springs, specifiers, n_specifiers)
print *, "Valid: ", val
if (val .lt. 1) then
stop
end if
print *
total_valid = total_valid + val
deallocate(tspec)
@ -93,7 +98,7 @@ program day12
character(*), intent(in) :: springs
integer, intent(in) :: specs(:)
integer, intent(in) :: n_spr, n_specs
integer :: nv
integer(kind=b_kind) :: nv
integer :: ex_dist, i, cur
cur = 0
do i=1, n_specs
@ -102,35 +107,45 @@ program day12
ex_dist = n_spr - cur + 1
print *, "Budget: ", ex_dist
print *, "Cnk: ", n_specs + ex_dist, ex_dist
nv = n_specval(springs, n_spr, specs, n_specs, 0, ex_dist, 1)
nv = mem_n_specval(springs, n_spr, specs, n_specs, 0, ex_dist, 1)
end function nvalid
recursive function mem_n_specval(springs, n_spr, specs, n_specs, i_gap, budget, cur) result(nsv)
implicit none
integer, intent(in) :: n_spr, n_specs, i_gap, budget, cur
integer, intent(in) :: specs(:)
character(*), intent(in) :: springs
integer(kind=b_kind) :: nsv
nsv = cache2(i_gap, budget, cur)
if (nsv .eq. -1_b_kind) then
nsv = n_specval(springs, n_spr, specs, n_specs, i_gap, budget, cur)
cache2(i_gap, budget, cur) = nsv
end if
end function mem_n_specval
recursive function n_specval(springs, n_spr, specs, n_specs, i_gap, budget, cur) result(nsv)
implicit none
integer, intent(in) :: n_spr, n_specs, i_gap, budget, cur
integer, intent(in) :: specs(:)
character(*), intent(in) :: springs
integer :: nsv
integer(kind=b_kind) :: nsv
integer :: b_used, cur2, curnew, brem
logical :: bad
if (i_gap .eq. n_specs) then
! Working on the last gap; all good so far
if (budget .eq. 0) then
! Nothing to consider
nsv = 1
nsv = 1_b_kind
else if (scan(springs((n_spr - budget + 1):n_spr), '#') .ne. 0) then
nsv = 0
nsv = 0_b_kind
else
nsv = 1
nsv = 1_b_kind
end if
return
end if
nsv = 0
nsv = 0_b_kind
do b_used=0,budget
cur2 = cur + b_used
if (i_gap .lt. 7) then
print *, i_gap, b_used, cur2, repeat('*', i_gap + 1)
end if
curnew = cur2 + specs(i_gap + 1) + 1
bad = .false.
if (.not. mem_specval(cur2, specs(i_gap + 1), springs, n_spr)) then
@ -145,39 +160,11 @@ program day12
end if
if (.not. bad) then
brem = budget - b_used
nsv = nsv + n_specval(springs, n_spr, specs, n_specs, i_gap + 1, brem, curnew)
nsv = nsv + mem_n_specval(springs, n_spr, specs, n_specs, i_gap + 1, brem, curnew)
end if
end do
end function n_specval
subroutine pr_specs(n_spr, n_specs, specs, s_starts)
implicit none
integer, intent(in) :: n_spr, n_specs, specs(:), s_starts(:)
character(len=max_chars) :: pstr
integer :: i
pstr = ' '
pstr(1:n_spr) = repeat('.', n_spr)
do i=1,n_specs
pstr(s_starts(i):(s_starts(i) + specs(i) - 1)) = repeat('#', specs(i))
end do
print *, trim(pstr)
end subroutine pr_specs
function spec_test(specs, spec_starts, n_specs, springs, n_spr)
implicit none
integer, intent(in) :: specs(:), spec_starts(:), n_specs, n_spr
character(*), intent(in) :: springs
logical :: spec_test
integer :: i
spec_test = .true.
do i=1,n_specs
if (.not. specval(spec_starts(i), specs(i), springs, n_spr)) then
spec_test = .false.
return
end if
end do
end function spec_test
function mem_specval(spec_start, spec_len, springs, n_spr)
implicit none
integer, intent(in) :: spec_start, spec_len, n_spr
@ -242,21 +229,5 @@ program day12
end do
end function numstr
function Cnk(n, k)
implicit none
integer, intent(in) :: n, k
integer :: Cnk
integer :: i
integer :: num, den
num = 1
do i = 0, k-1
num = num * (n-i)
end do
den = 1
do i = 1, k
den = den * i
end do
Cnk = num/den
end function Cnk
end program day12