Skip to content

Instantly share code, notes, and snippets.

@angus-g
Created December 4, 2019 00:31
Show Gist options
  • Save angus-g/20c1c779d40b0af880d3780805b6b26e to your computer and use it in GitHub Desktop.
Save angus-g/20c1c779d40b0af880d3780805b6b26e to your computer and use it in GitHub Desktop.
advent of code day 3
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