Advertisement
autid

AoC 2018 Day16 FORTRAN

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