Advertisement
autid

AoC 2019 Day3 FORTRAN (Improved)

Dec 4th, 2019
1,765
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. PROGRAM DAY3
  2.   TYPE NODE
  3.      INTEGER :: LOCATION(2),TIME
  4.      TYPE(NODE), POINTER :: NEXT => NULL()
  5.   END TYPE NODE
  6.   TYPE TABLE
  7.      TYPE(NODE), POINTER :: NEXT => NULL()
  8.   END TYPE TABLE
  9.   TYPE(TABLE) :: VISITED(0:9999)
  10.   INTEGER :: N1,N2,IERR,I,PART1,PART2,X,Y,T
  11.   CHARACTER(LEN=10), ALLOCATABLE :: WIRE1(:),WIRE2(:)
  12.   CHARACTER(LEN=1) :: CHAR
  13.  
  14.   ! Input
  15.   OPEN(1,FILE="input.txt")
  16.   N1=1
  17.   DO
  18.      READ(1,'(A1)',IOSTAT=IERR,ADVANCE="NO")CHAR
  19.      IF(IERR.NE.0)EXIT
  20.      IF(CHAR.EQ.",")N1=N1+1
  21.   END DO
  22.   REWIND(1)
  23.   READ(1,*)
  24.   N2=1
  25.   DO
  26.      READ(1,'(A1)',IOSTAT=IERR,ADVANCE="NO")CHAR
  27.      IF(IERR.NE.0)EXIT
  28.      IF(CHAR.EQ.",")N2=N2+1
  29.   END DO
  30.   REWIND(1)
  31.   ALLOCATE(WIRE1(N1),WIRE2(N2))
  32.   READ(1,*)WIRE1
  33.   READ(1,*)WIRE2
  34.   CLOSE(1)
  35.  
  36.   ! First wire
  37.   PART1=0
  38.   PART2=0
  39.   T=0
  40.   X=0
  41.   Y=0
  42.   DO I=1,SIZE(WIRE1)
  43.      CALL RUN(WIRE1(I),X,Y,T,VISITED,1,PART1,PART2)
  44.   END DO
  45.  
  46.   ! Second wire
  47.   T=0
  48.   X=0
  49.   Y=0
  50.   DO I=1,SIZE(WIRE2)
  51.      CALL RUN(WIRE2(I),X,Y,T,VISITED,2,PART1,PART2)
  52.   END DO
  53.  
  54.   ! Output
  55.   WRITE(*,'("Part 1: ",I0)') PART1
  56.   WRITE(*,'("Part 2: ",I0)') PART2
  57.  
  58. CONTAINS
  59.   SUBROUTINE RUN(INSTR,X,Y,T,VISITED,WIRE,PART1,PART2)
  60.     ! Calculate points visited due to INSTR
  61.     ! If wire 1, saves points in table
  62.     ! If wire 2, checks for intersections with wire 1
  63.     INTEGER, INTENT(INOUT) :: X,Y,T,PART1,PART2
  64.     CHARACTER(LEN=*), INTENT(IN) :: INSTR
  65.     INTEGER :: DIST,I,WIRE
  66.     TYPE(TABLE), INTENT(INOUT) :: VISITED(:)
  67.  
  68.     READ(INSTR(2:),*)DIST
  69.     DO I=1,DIST
  70.        T=T+1
  71.        SELECT CASE(INSTR(1:1))
  72.        CASE("U")
  73.           Y=Y+1
  74.        CASE("D")
  75.           Y=Y-1
  76.        CASE("R")
  77.           X=X+1
  78.        CASE("L")
  79.           X=X-1
  80.        END SELECT
  81.        IF(WIRE.EQ.1)THEN
  82.           CALL ADD((/X,Y/),T,VISITED)
  83.        ELSE
  84.           CALL FIND((/X,Y/),T,VISITED,PART1,PART2)
  85.        END IF
  86.     END DO
  87.  
  88.   END SUBROUTINE RUN
  89.  
  90.   SUBROUTINE ADD(LOCATION,TIME,VISITED)
  91.     ! Adds location and time to table if not yet visited
  92.     INTEGER, INTENT(IN) :: LOCATION(2),TIME
  93.     TYPE(TABLE), INTENT(INOUT) :: VISITED(:)
  94.     INTEGER :: KEY
  95.     TYPE(NODE), POINTER :: A
  96.  
  97.     KEY=MODULO(SUM(ABS(LOCATION)),SIZE(VISITED))
  98.     IF(.NOT.ASSOCIATED(VISITED(KEY)%NEXT))THEN
  99.        ALLOCATE(VISITED(KEY)%NEXT)
  100.        A => VISITED(KEY)%NEXT
  101.        A%LOCATION = LOCATION
  102.        A%TIME = TIME
  103.        RETURN
  104.     END IF
  105.  
  106.     A => VISITED(KEY)%NEXT
  107.     DO
  108.        IF(ALL(LOCATION.EQ.A%LOCATION))RETURN
  109.        IF(.NOT.ASSOCIATED(A%NEXT))EXIT
  110.        A => A%NEXT
  111.     END DO
  112.     ALLOCATE(A%NEXT)
  113.     A => A%NEXT
  114.     A%LOCATION = LOCATION
  115.     A%TIME = TIME
  116.   END SUBROUTINE ADD
  117.  
  118.   SUBROUTINE FIND(LOCATION,TIME,VISITED,PART1,PART2)
  119.     ! Checks for intersection with recorded points
  120.     ! Updates answers if found
  121.     INTEGER, INTENT(IN) :: LOCATION(2),TIME
  122.     TYPE(TABLE), INTENT(INOUT) :: VISITED(:)
  123.     INTEGER, INTENT(INOUT) :: PART1,PART2
  124.     INTEGER :: KEY
  125.     TYPE(NODE), POINTER :: A
  126.  
  127.     KEY=MODULO(SUM(ABS(LOCATION)),SIZE(VISITED))
  128.     IF(.NOT.ASSOCIATED(VISITED(KEY)%NEXT))RETURN
  129.  
  130.     A => VISITED(KEY)%NEXT
  131.     DO
  132.        IF(ALL(LOCATION.EQ.A%LOCATION))EXIT
  133.        IF(.NOT.ASSOCIATED(A%NEXT))RETURN
  134.        A => A%NEXT
  135.     END DO
  136.  
  137.     IF(PART1.EQ.0)PART1=SUM(ABS(LOCATION))
  138.     PART1 = MIN(SUM(ABS(LOCATION)),PART1)
  139.     IF(PART2.EQ.0)PART2=TIME+A%TIME
  140.     PART2=MIN(TIME+A%TIME,PART2)
  141.   END SUBROUTINE FIND
  142.  
  143. END PROGRAM
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement