AdventOfFortran/2019/src/day02.f90

95 lines
3.2 KiB
Fortran

program day2
implicit none
integer, parameter :: path_length = 100
character(path_length) :: fname
integer :: n_arguments
integer, allocatable :: intcode(:)
integer :: n_codes
logical :: run_successful
n_arguments = command_argument_count()
if (n_arguments .eq. 1) then
call get_command_argument(1, fname)
print *, "File: ", fname
else
print *, "Wrong number of arguments: ", n_arguments
stop
end if
intcode = read_intcode(fname)
n_codes = size(intcode)
print "(4i5)", intcode
print *, "Running intcode"
call execute_intcode(intcode, n_codes, run_successful)
if (run_successful) then
print *, "Clean exit"
else
print *, "ERROR!"
end if
print *
print "(4i5)", intcode
print *
print *, "Value at position 0: ", intcode(0 + 1)
deallocate(intcode)
contains
function read_intcode(fname)
integer, parameter :: fstr_len = 10000
character(*), intent(in) :: fname
integer, allocatable :: read_intcode(:)
character(fstr_len) :: fstr
integer :: fstr_true_len
integer :: n_values = 0
integer :: i
open(10, file=fname)
read(10, "(A)") fstr
close(10)
fstr_true_len = len_trim(fstr)
do i=1, fstr_true_len
if (fstr(i:i) .eq. ',') n_values = n_values + 1
end do
allocate(read_intcode(0:n_values))
read(fstr, *) read_intcode
end function read_intcode
subroutine execute_intcode(intcode, icodelen, clean_exit)
integer, intent(inout) :: intcode(0:)
integer, intent(in) :: icodelen
logical, intent(out) :: clean_exit
integer, parameter :: max_iterations = 10000
integer :: code_line
integer :: opcode
integer :: ipos_1
integer :: ipos_2
integer :: opos
integer :: op_result
!print "(4i5)", intcode
clean_exit = .false.
do code_line = 0, max_iterations
if (code_line * 4 .ge. icodelen) then
print *, "Overran intcode looking for opcode at line ", code_line
return
end if
opcode = intcode(code_line * 4)
if (opcode .eq. 99) then
print *, "Finished at line ", code_line
clean_exit = .true.
return
end if
ipos_1 = intcode(code_line * 4 + 1)
ipos_2 = intcode(code_line * 4 + 2)
opos = intcode(code_line * 4 + 3)
if (opcode .eq. 1) then
op_result = intcode(ipos_1) + intcode(ipos_2)
intcode(opos) = op_result
else if (opcode .eq. 2) then
op_result = intcode(ipos_1) * intcode(ipos_2)
intcode(opos) = op_result
else
print *, "Unknown opcode at line", code_line, " - ", opcode
return
end if
end do
end subroutine execute_intcode
end program day2