My yearly advent-of-code solutions
1program day_03_part_2
2 implicit none
3 logical :: find_a, is_dont
4 integer ::io, ios, a, b, state, res
5 character(len=1) :: c
6 character(len=10) :: buffer
7 character(len=4) :: mul_cmd = 'mul('
8 character(len=7) :: dont_cmd = "don't()"
9 character(len=4) :: do_cmd = 'do()'
10
11 res = 0
12 open(newunit=io, file='./day_03_input.txt', status='old', action='read', access='stream')
13 state = 0 ! 0 = find command, 1 = find number, 2 = calculate
14 find_a = .true.
15 is_dont = .false.
16 buffer = ''
17 do
18 read(io, iostat=ios) c
19 if (ios /= 0) exit
20 select case(state)
21 case (0) ! find command
22 buffer = trim(buffer) // c
23 if(is_dont) then
24 if (trim(buffer) == do_cmd) then
25 state = 0
26 buffer = ''
27 is_dont = .false.
28 else if (trim(buffer) /= do_cmd(1:len(trim(buffer)))) then
29 state = 0
30 buffer = ''
31 end if
32 else
33 if (trim(buffer) == dont_cmd) then
34 state = 0
35 buffer = ''
36 is_dont = .true.
37 else if(trim(buffer) == mul_cmd) then
38 state = 1
39 buffer = ''
40 else if(trim(buffer) /= mul_cmd(1:len(trim(buffer))) .and. trim(buffer) /= dont_cmd(1:len(trim(buffer)))) then
41 state = 0
42 buffer = ''
43 end if
44 end if
45 case (1) ! find digits
46 select case (iachar(c))
47 case (48:57) ! 0-9
48 buffer = trim(buffer) // c
49 case (44) ! ,
50 if (find_a .and. len(trim(buffer)) > 0) then
51 read(buffer, *) a
52 buffer = ''
53 find_a = .false.
54 else
55 state = 0 ! invalid
56 find_a = .true.
57 buffer = ''
58 end if
59 case (41) ! )
60 if(.not. find_a .and. len(trim(buffer)) > 0) then
61 read(buffer, *) b
62 state = 2
63 find_a = .true.
64 buffer = ''
65 else
66 state = 0
67 find_a = .true.
68 buffer = ''
69 end if
70 case default
71 state = 0
72 find_a = .true.
73 buffer = ''
74 end select
75 end select
76 if(state == 2) then
77 res = res + (a * b)
78 state = 0
79 buffer = ''
80 end if
81 end do
82 print*, res
83end program day_03_part_2