From a0efdb9cce9e31141c71f8bf0786fc12d33591fd Mon Sep 17 00:00:00 2001 From: Petra Date: Sat, 16 Dec 2023 14:44:41 +1300 Subject: [PATCH] Actual 2023 day 12 solution More aggressively memoised --- 2023/src/day12.f90 | 83 +++++++++++++++------------------------------- 1 file changed, 27 insertions(+), 56 deletions(-) diff --git a/2023/src/day12.f90 b/2023/src/day12.f90 index d5c4636..25d77d8 100644 --- a/2023/src/day12.f90 +++ b/2023/src/day12.f90 @@ -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