Advertisement
autid

AoC 2018 Day21 FORTRAN

Dec 21st, 2018
736
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. PROGRAM DAY21
  2.   IMPLICIT NONE
  3.   TYPE OP
  4.      PROCEDURE(), POINTER, NOPASS :: P
  5.      INTEGER(8) :: ARGS(3)
  6.   END TYPE OP
  7.   INTEGER(8), TARGET :: REGISTERS(0:5)=0
  8.   INTEGER :: I,J,K,IERR,ANSWER
  9.   INTEGER(8), POINTER :: INSTRUCTION
  10.   CHARACTER(LEN=4) :: INLINE
  11.   TYPE(OP), ALLOCATABLE :: PROG(:)
  12.   INTEGER(8),ALLOCATABLE:: PREVIOUS(:,:)
  13.   OPEN(1,FILE='input.txt')
  14.   I=-1
  15.   DO
  16.      READ(1,*,IOSTAT=IERR)
  17.      IF(IERR.NE.0)EXIT
  18.      I=I+1
  19.   END DO
  20.   REWIND(1)
  21.   READ(1,*)INLINE,J
  22.   INSTRUCTION=>REGISTERS(J)
  23.   ALLOCATE(PROG(0:I-1))
  24.   DO J=0,I-1
  25.      READ(1,*)INLINE,PROG(J)%ARGS
  26.      SELECT CASE(INLINE)
  27.      CASE('addr')
  28.         PROG(J)%P=>ADDR
  29.      CASE('addi')
  30.         PROG(J)%P=>ADDI
  31.      CASE('mulr')
  32.         PROG(J)%P=>MULR
  33.      CASE('muli')
  34.         PROG(J)%P=>MULI
  35.      CASE('banr')
  36.         PROG(J)%P=>BANR
  37.      CASE('bani')
  38.         PROG(J)%P=>BANI
  39.      CASE('borr')
  40.         PROG(J)%P=>BORR
  41.      CASE('bori')
  42.         PROG(J)%P=>BORI
  43.      CASE('setr')
  44.         PROG(J)%P=>SETR
  45.      CASE('seti')
  46.         PROG(J)%P=>SETI
  47.      CASE('gtir')
  48.         PROG(J)%P=>GTIR
  49.      CASE('gtri')
  50.         PROG(J)%P=>GTRI
  51.      CASE('gtrr')
  52.         PROG(J)%P=>GTRR
  53.      CASE('eqir')
  54.         PROG(J)%P=>EQIR
  55.      CASE('eqri')
  56.         PROG(J)%P=>EQRI
  57.      CASE('eqrr')
  58.         PROG(J)%P=>EQRR
  59.      END SELECT
  60.   END DO
  61.   REGISTERS=0
  62.   I=2
  63.   ALLOCATE(PREVIOUS(0:5,15000))
  64.   ANSWER=PROG(28)%ARGS(1)
  65.   PREVIOUS=0
  66.   DO
  67.      IF(INSTRUCTION.EQ.28)THEN
  68.         IF(I.EQ.2)WRITE(*,'("Part 1: ",I0)')REGISTERS(ANSWER)
  69.         IF(I>SIZE(PREVIOUS,DIM=2))CALL EXTEND()
  70.         IF(ANY((/(ALL(PREVIOUS(:,J).EQ.REGISTERS),J=1,I-1)/)))EXIT
  71.         PREVIOUS(:,I)=REGISTERS
  72.         I=I+1
  73.      END IF
  74.      CALL PROG(INSTRUCTION)%P(PROG(INSTRUCTION)%ARGS(1),PROG(INSTRUCTION)%ARGS(2),PROG(INSTRUCTION)%ARGS(3))
  75.      INSTRUCTION=INSTRUCTION+1
  76.   END DO
  77.   DO
  78.      I=I-1
  79.      IF(ANY(PREVIOUS(ANSWER,1:I-1).EQ.PREVIOUS(ANSWER,I)))CYCLE
  80.      WRITE(*,'("Part 2: ",I0)')PREVIOUS(ANSWER,I)
  81.      EXIT
  82.   END DO
  83.  
  84. CONTAINS
  85.   SUBROUTINE EXTEND()
  86.     INTEGER(8),ALLOCATABLE :: BACKUP(:,:)
  87.     ALLOCATE(BACKUP(5,SIZE(PREVIOUS,DIM=2)+1000))
  88.     BACKUP=0
  89.     BACKUP(:,1:SIZE(PREVIOUS,DIM=2))=PREVIOUS
  90.     DEALLOCATE(PREVIOUS)
  91.     ALLOCATE(PREVIOUS(0:5,SIZE(BACKUP,DIM=2)))
  92.     PREVIOUS=BACKUP
  93.     DEALLOCATE(BACKUP)
  94.   END SUBROUTINE EXTEND
  95.   SUBROUTINE ADDR(A,B,C)
  96.     INTEGER, INTENT(IN) :: A,B,C
  97.     REGISTERS(C)=REGISTERS(A)+REGISTERS(B)
  98.   END SUBROUTINE ADDR
  99.   SUBROUTINE ADDI(A,B,C)
  100.     INTEGER, INTENT(IN) :: A,B,C
  101.     REGISTERS(C)=REGISTERS(A)+B
  102.   END SUBROUTINE ADDI
  103.   SUBROUTINE MULR(A,B,C)
  104.     INTEGER, INTENT(IN) :: A,B,C
  105.     REGISTERS(C)=REGISTERS(A)*REGISTERS(B)
  106.   END SUBROUTINE MULR
  107.   SUBROUTINE MULI(A,B,C)
  108.     INTEGER, INTENT(IN) :: A,B,C
  109.     REGISTERS(C)=REGISTERS(A)*B
  110.   END SUBROUTINE MULI
  111.   SUBROUTINE BANR(A,B,C)
  112.     INTEGER, INTENT(IN) :: A,B,C
  113.     REGISTERS(C)=IAND(REGISTERS(A),REGISTERS(B))
  114.   END SUBROUTINE BANR
  115.   SUBROUTINE BANI(A,B,C)
  116.     INTEGER, INTENT(IN) :: A,B,C
  117.     REGISTERS(C)=IAND(REGISTERS(A),B)
  118.   END SUBROUTINE BANI
  119.   SUBROUTINE BORR(A,B,C)
  120.     INTEGER, INTENT(IN) :: A,B,C
  121.     REGISTERS(C)=IOR(REGISTERS(A),REGISTERS(B))
  122.   END SUBROUTINE BORR
  123.   SUBROUTINE BORI(A,B,C)
  124.     INTEGER, INTENT(IN) :: A,B,C
  125.     REGISTERS(C)=IOR(REGISTERS(A),B)
  126.   END SUBROUTINE BORI
  127.   SUBROUTINE SETR(A,B,C)
  128.     INTEGER, INTENT(IN) :: A,B,C
  129.     REGISTERS(C)=REGISTERS(A)
  130.   END SUBROUTINE SETR
  131.   SUBROUTINE SETI(A,B,C)
  132.     INTEGER, INTENT(IN) :: A,B,C
  133.     REGISTERS(C)=A
  134.   END SUBROUTINE SETI
  135.   SUBROUTINE GTIR(A,B,C)
  136.     INTEGER, INTENT(IN) :: A,B,C
  137.     REGISTERS(C)=0
  138.     IF(A>REGISTERS(B))THEN
  139.        REGISTERS(C)=1
  140.     ELSE
  141.        REGISTERS(C)=0
  142.     END IF
  143.   END SUBROUTINE GTIR
  144.   SUBROUTINE GTRI(A,B,C)
  145.     INTEGER, INTENT(IN) :: A,B,C
  146.     IF(REGISTERS(A)>B)THEN
  147.        REGISTERS(C)=1
  148.     ELSE
  149.        REGISTERS(C)=0
  150.     END IF
  151.   END SUBROUTINE GTRI
  152.   SUBROUTINE GTRR(A,B,C)
  153.     INTEGER, INTENT(IN) :: A,B,C
  154.     IF(REGISTERS(A)>REGISTERS(B))THEN
  155.        REGISTERS(C)=1
  156.     ELSE
  157.        REGISTERS(C)=0
  158.     END IF
  159.   END SUBROUTINE GTRR
  160.   SUBROUTINE EQIR(A,B,C)
  161.     INTEGER, INTENT(IN) :: A,B,C
  162.     IF(A.EQ.REGISTERS(B))THEN
  163.        REGISTERS(C)=1
  164.     ELSE
  165.        REGISTERS(C)=0
  166.     END IF
  167.   END SUBROUTINE EQIR
  168.   SUBROUTINE EQRI(A,B,C)
  169.     INTEGER, INTENT(IN) :: A,B,C
  170.     IF(REGISTERS(A).EQ.B)THEN
  171.        REGISTERS(C)=1
  172.     ELSE
  173.        REGISTERS(C)=0
  174.     END IF
  175.   END SUBROUTINE EQRI
  176.   SUBROUTINE EQRR(A,B,C)
  177.     INTEGER, INTENT(IN) :: A,B,C
  178.     IF(REGISTERS(A).EQ.REGISTERS(B))THEN
  179.        REGISTERS(C)=1
  180.     ELSE
  181.        REGISTERS(C)=0
  182.     END IF
  183.   END SUBROUTINE EQRR
  184. END PROGRAM DAY21
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement