My yearly advent-of-code solutions
at main 6.7 kB view raw
1module day_05_utils 2 implicit none 3contains 4 subroutine append_to_integer_array(arr, val) 5 implicit none 6 integer, allocatable, intent(inout) :: arr(:) 7 integer, intent(in) :: val 8 integer, allocatable :: temp(:) 9 if(.not. allocated(arr)) then 10 ERROR STOP 'Array not allocated' 11 end if 12 allocate(temp(size(arr) + 1)) 13 temp(1:size(arr)) = arr 14 temp(size(arr) + 1) = val 15 call move_alloc(temp, arr) 16 end subroutine append_to_integer_array 17 function fix_and_get_middle_value(arr, left, right) result(res) 18 ! we are going to fix the array swapping until its right 19 ! there's probably a better way maybe? but I just want to get it done 20 implicit none 21 integer, allocatable, intent(in) :: arr(:), left(:), right(:) 22 integer, allocatable :: work(:), copy(:) 23 integer :: res, i, j, tmp 24 logical :: found 25 allocate(copy(size(arr))) 26 copy = arr 27 do 28 found = .false. 29 outer: do i = 1, size(copy) 30 if(i+1 < size(copy)) then ! if we can check forward 31 if(allocated(work)) then 32 deallocate(work) 33 end if 34 do j = 1, size(right) ! find value in right and save left to work 35 if (copy(i) == right(j)) then 36 if(.not. allocated(work)) then 37 allocate(work(1)) 38 work(1) = left(j) 39 else 40 call append_to_integer_array(work, left(j)) 41 end if 42 end if 43 end do 44 do j = i+1, size(copy) 45 if(any(work == copy(j))) then 46 tmp = copy(i) 47 copy(i) = copy(j) 48 copy(j) = tmp 49 found = .true. 50 exit outer 51 end if 52 end do 53 end if 54 55 if(.not. found) then ! if we are still valid lets keep going 56 if(allocated(work)) then 57 deallocate(work) 58 end if 59 if(i-1 > 0) then ! if we can check backwards 60 do j = 1, size(left) ! find value in left and save left to work 61 62 if (copy(i) == left(j)) then 63 if(.not. allocated(work)) then 64 allocate(work(1)) 65 work(1) = right(j) 66 else 67 call append_to_integer_array(work, right(j)) 68 end if 69 end if 70 end do 71 do j = 1, size(copy) 72 if(any(work == copy(j) .and. j < i)) then 73 tmp = copy(i) 74 copy(i) = copy(j) 75 copy(j) = tmp 76 found = .true. 77 exit outer 78 end if 79 end do 80 end if 81 else 82 exit outer 83 end if 84 end do outer 85 if(.not. found) exit 86 end do 87 res = copy((size(copy) + 1)/2) 88 deallocate(copy) 89 if(allocated(work)) then 90 deallocate(work) 91 end if 92 end function fix_and_get_middle_value 93end module day_05_utils 94program day_05 95 use day_05_utils 96 implicit none 97 integer :: io, ios, idx, a, b, ct, i, j, res, res_part2 98 integer, allocatable :: left(:), right(:), print_list(:), work(:) 99 character(len=100) ::line 100 logical :: found 101 102 open(newunit=io, file='./day_05_input.txt', status='old', action='read') 103 res = 0 104 res_part2 = 0 105 do 106 read(io, '(a)', iostat=ios) line 107 if(ios /= 0) exit !eof 108 idx = index(line, '|') 109 if(idx > 0) then ! rules 110 read(line(1:idx-1), *) a 111 read(line(idx+1:), *) b 112 if(.not. allocated(left)) then 113 allocate(left(1)) 114 left(1) = a 115 else 116 call append_to_integer_array(left, a) 117 end if 118 if(.not. allocated(right)) then 119 allocate(right(1)) 120 right(1) = b 121 else 122 call append_to_integer_array(right, b) 123 end if 124 end if 125 idx = index(line, ',') 126 if (idx > 0 ) then ! print_list 127 ct = 1 128 do i = 1 , len_trim(line) 129 if(line(i:i) == ',') then 130 ct = ct + 1 131 end if 132 end do 133 allocate(print_list(ct)) 134 read(line, *) print_list 135 found = .false. 136 do i = 1, size(print_list) 137 if(i+1 < size(print_list)) then ! if we can check forward 138 do j = 1, size(right) ! find value in right and save left to work 139 if (print_list(i) == right(j)) then 140 if(.not. allocated(work)) then 141 allocate(work(1)) 142 work(1) = left(j) 143 else 144 call append_to_integer_array(work, left(j)) 145 end if 146 end if 147 end do 148 do j = 1, size(work) 149 if(any(print_list(i+1:size(print_list)) == work(j))) then 150 found = .true. 151 exit 152 end if 153 end do 154 deallocate(work) 155 end if 156 if(.not. found) then ! if we are still valid lets keep going 157 if(i-1 > 0) then ! if we can check backwards 158 do j = 1, size(left) ! find value in left and save left to work 159 if (print_list(i) == left(j)) then 160 if(.not. allocated(work)) then 161 allocate(work(1)) 162 work(1) = right(j) 163 else 164 call append_to_integer_array(work, right(j)) 165 end if 166 end if 167 end do 168 do j = 1, size(work) 169 if(any(print_list(1:i-1) == work(j))) then 170 found = .true. 171 exit 172 end if 173 end do 174 deallocate(work) 175 end if 176 else 177 exit 178 end if 179 end do 180 if (.not. found) then 181 res = res + print_list((size(print_list) + 1)/2) 182 else 183 res_part2 = res_part2 + fix_and_get_middle_value(print_list, left, right) 184 end if 185 deallocate(print_list) 186 end if 187 end do 188 189 deallocate(left) 190 deallocate(right) 191 print*, "Result ", res 192 print*, "Part 2 Result ", res_part2 193end program day_05