Created
December 4, 2019 00:31
-
-
Save angus-g/20c1c779d40b0af880d3780805b6b26e to your computer and use it in GitHub Desktop.
advent of code day 3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
program day3 | |
implicit none | |
character(len=2048) :: line | |
character(len=4), dimension(:), allocatable :: insn1, insn2 | |
integer, dimension(:,:), allocatable :: points1, points2, collisions | |
integer :: n, i, j, closest, x, y, t | |
open(1, file="day3.in") | |
! first input line | |
read(1, "(A)") line | |
n = count(transfer(line, "a", len(line)) == ",") | |
allocate(insn1(n+1)) | |
read(line, *) insn1 | |
! second input line | |
read(1, "(A)") line | |
n = count(transfer(line, "a", len(line)) == ",") | |
allocate(insn2(n+1)) | |
read(line, *) insn2 | |
close(1) | |
call calculate_lines(insn1, points1) | |
call calculate_lines(insn2, points2) | |
! calcluate intersections | |
do i = 1, size(insn1) | |
if (mod(i, 2) == 0) then | |
! vertical segment | |
do j = 1, size(insn2), 2 | |
! check segment intersection | |
if (intersection(points1(:,i:i+1), points2(:,j:j+1))) then | |
x = points1(1,i) | |
y = points2(2,j) | |
t = (points1(3,i) + abs(y - points1(2,i))) + (points2(3,j) + abs(x - points2(1,j))) | |
call array_append(collisions, [x, y, t]) | |
end if | |
end do | |
else | |
do j = 2, size(insn2), 2 | |
if (intersection(points2(:,j:j+1), points1(:,i:i+1))) then | |
x = points2(1,j) | |
y = points1(2,i) | |
t = (points2(3,j) + abs(y - points2(1,j))) + (points1(3,i) + abs(x - points1(2,i))) | |
call array_append(collisions, [x, y, t]) | |
end if | |
end do | |
end if | |
end do | |
closest = abs(collisions(1,1)) + abs(collisions(2,1)) | |
do i = 2, size(collisions, dim=2) | |
closest = min(closest, abs(collisions(1,i)) + abs(collisions(2,i))) | |
end do | |
print *, closest, collisions(3, 1) | |
contains | |
subroutine calculate_lines(insn, points) | |
character(len=*), dimension(:), intent(in) :: insn | |
integer, dimension(:,:), allocatable, intent(out) :: points | |
integer :: n, x, y, t, dx, dy, amt | |
! x, y, t | |
allocate(points(3, size(insn)+1)) | |
points(:,1) = [0, 0, 0] | |
x = 0 | |
y = 0 | |
t = 0 | |
do n = 1, size(insn) | |
read(insn(n)(2:), "(I3)") amt | |
select case (insn(n)(1:1)) | |
case ("R") | |
dx = amt | |
dy = 0 | |
case ("L") | |
dx = -amt | |
dy = 0 | |
case ("U") | |
dx = 0 | |
dy = amt | |
case ("D") | |
dx = 0 | |
dy = -amt | |
end select | |
x = x + dx | |
y = y + dy | |
t = t + amt | |
points(:,n+1) = [x, y, t] | |
end do | |
end subroutine calculate_lines | |
logical function intersection(vert, horiz) | |
integer, dimension(3,2), intent(in) :: vert, horiz | |
intersection = vert(1,1) >= min(horiz(1,1), horiz(1,2)) & | |
.and. vert(1,1) <= max(horiz(1,1), horiz(1,2)) & | |
.and. horiz(2,1) >= min(vert(2,1), vert(2,2)) & | |
.and. horiz(2,1) <= max(vert(2,1), vert(2,2)) | |
end function intersection | |
subroutine array_append(arr, el) | |
integer, dimension(:,:), allocatable, intent(inout) :: arr | |
integer, dimension(:), intent(in) :: el | |
integer, dimension(:,:), allocatable :: tmp | |
integer :: n | |
if (allocated(arr)) then | |
n = size(arr, dim=2) | |
allocate(tmp(size(arr, dim=1), n+1)) | |
tmp(:,1:n) = arr(:,1:n) | |
tmp(:,n+1) = el | |
deallocate(arr) | |
call move_alloc(tmp, arr) | |
else | |
allocate(arr(size(el), 1)) | |
arr(:,1) = el | |
end if | |
end subroutine array_append | |
end program day3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment