···
4
+
subroutine swap_to_first_positive_integer_from_end(arr, idx)
6
+
integer, allocatable, intent(inout) :: arr(:)
7
+
integer, intent(in) :: idx
8
+
integer, allocatable :: temp(:)
10
+
do i = 0, size(arr) - 1
11
+
if(arr(size(arr) - i) > -1) then
12
+
arr(idx) = arr(size(arr) - i)
13
+
allocate(temp(size(arr) - (i +1)))
14
+
temp = arr(1:size(arr) - (i+1))
15
+
call move_alloc(temp, arr)
19
+
end subroutine swap_to_first_positive_integer_from_end
20
+
subroutine append_to_integer_array_times(arr, val, times)
22
+
integer, allocatable, intent(inout) :: arr(:)
23
+
integer, intent(in) :: val, times
24
+
integer, allocatable :: temp(:)
25
+
if(.not. allocated(arr)) then
26
+
ERROR STOP 'Array not allocated'
28
+
allocate(temp(size(arr) + times))
29
+
temp(1:size(arr)) = arr
30
+
temp(size(arr) + 1:size(temp)) = val
31
+
call move_alloc(temp, arr)
32
+
end subroutine append_to_integer_array_times
33
+
end module day_09_utils
35
+
use iso_fortran_env, only: int64
38
+
integer :: io, ios, i, j, block_n, ct, block_start, block_end, space_start, space_end
39
+
integer(kind=int64) :: res
40
+
character(len=1) :: c
41
+
integer, allocatable :: system(:), work(:)
42
+
logical :: is_space, space_block_start
44
+
open(newunit=io, file='./day_09_input.txt', status='old', action='read', access='stream')
48
+
read(io, iostat=ios) c
50
+
read(c, *, iostat=ios) i
56
+
if (.not. allocated(system)) then
58
+
system(1:i) = block_n
60
+
block_n = block_n + 1
63
+
call append_to_integer_array_times(system, -1, i)
66
+
call append_to_integer_array_times(system, block_n, i)
67
+
block_n = block_n + 1
72
+
allocate(work(size(system)))
74
+
ct = count(work > -1)
76
+
do i = 1, size(work)
77
+
if (i == ct) exit outer ! we are done
78
+
if(work(i) < 0) then
79
+
call swap_to_first_positive_integer_from_end(work, i)
85
+
do i = 1, size(work)
86
+
if(work(i) > -1) then
87
+
res = res + ((i-1) * work(i))
95
+
allocate(work(size(system)))
100
+
do i = 0, size(work) -1
101
+
if(block_n == -1 .and. work(size(work) - i) > -1) then
102
+
! we are starting a block
103
+
block_end = size(work) - i
104
+
block_n = work(size(work) - i)
105
+
else if (block_n /= -1 .and. block_n /= work(size(work)-i)) then
106
+
! we are ending the block
107
+
block_start = size(work) - i
108
+
! lets try to move the block
109
+
space_block_start = .true.
110
+
do j = 1, size(work)
111
+
if (j >= block_start) exit
112
+
if(space_block_start .and. work(j) == -1) then
114
+
space_block_start = .false.
115
+
else if (.not. space_block_start .and. work(j) /= -1) then
117
+
space_block_start = .true.
118
+
if(space_end - space_start >= block_end - block_start) then
119
+
work(space_start:(space_start + (block_end - (block_start +1) ))) = work((block_start +1):block_end)
120
+
work(block_start+1:block_end) = -1
129
+
block_n = work(size(work) - i)
130
+
block_end = size(work) - i
134
+
do i = 1, size(work)
135
+
if(work(i) > -1) then
136
+
res = res + ((i-1) * work(i))