Advertisement
autid

AoC 2019 Day7 FORTRAN

Dec 7th, 2019
1,500
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. PROGRAM DAY7
  2.   ! Run with mpirun -np 6 ./day7
  3.   USE MPI
  4.   TYPE OP
  5.      PROCEDURE(), POINTER, NOPASS :: OP
  6.      INTEGER :: NARGS
  7.   END TYPE OP
  8.   INTEGER :: I,N,IERR,MODES,OPCODE,A,B,C,D,E,PART1,PART2,RES
  9.   INTEGER :: LASTOUT
  10.   CHARACTER(LEN=1) CHAR
  11.   INTEGER, ALLOCATABLE :: PROG(:),STOREDPROG(:)
  12.   TYPE(OP) :: OPS(8)
  13.   INTEGER :: IERROR, NPROC, ICOMM, IRANK,SENDTO(5),RECVFROM(5)
  14.   LOGICAL :: AMROOT,RUNNING,SETUP,FIRST
  15.   INTEGER :: STATUS(MPI_STATUS_SIZE)
  16.  
  17.   CALL MPI_INIT(IERROR)
  18.   ICOMM = MPI_COMM_WORLD
  19.   CALL MPI_COMM_SIZE(ICOMM,NPROC,IERROR)
  20.   CALL MPI_COMM_RANK(ICOMM, IRANK, IERROR)
  21.   AMROOT = IRANK.EQ.0
  22.  
  23.   IF(AMROOT)THEN
  24.      OPEN(1,FILE="input.txt")
  25.      N=1
  26.      DO
  27.         READ(1,'(A1)',IOSTAT=IERR,ADVANCE="NO")CHAR
  28.         IF(IERR.NE.0)EXIT
  29.         IF(CHAR.EQ.",")N=N+1
  30.      END DO
  31.      REWIND(1)
  32.      ALLOCATE(PROG(0:N-1))
  33.      READ(1,*)PROG
  34.      DO I=1,NPROC-1
  35.         CALL MPI_SEND(N,1,MPI_INTEGER,I,0,ICOMM,IERROR)
  36.         CALL MPI_SEND(PROG,N,MPI_INTEGER,I,1,ICOMM,IERROR)
  37.      END DO
  38.      PART1=0
  39.      DO A=0,4
  40.         DO B=0,4
  41.            IF(B.EQ.A)CYCLE
  42.            DO C=0,4
  43.               IF(ANY((/A,B/).EQ.C))CYCLE
  44.               DO D=0,4
  45.                  IF(ANY((/A,B,C/).EQ.D))CYCLE
  46.                  DO E=0,4
  47.                     IF(ANY((/A,B,C,D/).EQ.E))CYCLE
  48.                     CALL MPI_SEND(A,1,MPI_INTEGER,1,2,ICOMM,IERROR)
  49.                     CALL MPI_SEND(0,1,MPI_INTEGER,1,3,ICOMM,IERROR)
  50.                     CALL MPI_SEND(B,1,MPI_INTEGER,2,2,ICOMM,IERROR)
  51.                     CALL MPI_SEND(C,1,MPI_INTEGER,3,2,ICOMM,IERROR)
  52.                     CALL MPI_SEND(D,1,MPI_INTEGER,4,2,ICOMM,IERROR)
  53.                     CALL MPI_SEND(E,1,MPI_INTEGER,5,2,ICOMM,IERROR)
  54.                     CALL MPI_RECV(RES,1,MPI_INTEGER,5,999,ICOMM,STATUS,IERROR)
  55.                     PART1=MAX(PART1,RES)
  56.                  END DO
  57.               END DO
  58.            END DO
  59.         END DO
  60.      END DO
  61.      PART2=0
  62.      DO A=5,9
  63.         DO B=5,9
  64.            IF(B.EQ.A)CYCLE
  65.            DO C=5,9
  66.               IF(ANY((/A,B/).EQ.C))CYCLE
  67.               DO D=5,9
  68.                  IF(ANY((/A,B,C/).EQ.D))CYCLE
  69.                  DO E=5,9
  70.                     IF(ANY((/A,B,C,D/).EQ.E))CYCLE
  71.                     CALL MPI_SEND(A,1,MPI_INTEGER,1,2,ICOMM,IERROR)
  72.                     CALL MPI_SEND(0,1,MPI_INTEGER,1,3,ICOMM,IERROR)
  73.                     CALL MPI_SEND(B,1,MPI_INTEGER,2,2,ICOMM,IERROR)
  74.                     CALL MPI_SEND(C,1,MPI_INTEGER,3,2,ICOMM,IERROR)
  75.                     CALL MPI_SEND(D,1,MPI_INTEGER,4,2,ICOMM,IERROR)
  76.                     CALL MPI_SEND(E,1,MPI_INTEGER,5,2,ICOMM,IERROR)
  77.                     CALL MPI_RECV(RES,1,MPI_INTEGER,5,999,ICOMM,STATUS,IERROR)
  78.                     PART2=MAX(PART2,RES)
  79.                  END DO
  80.               END DO
  81.            END DO
  82.         END DO
  83.      END DO
  84.      WRITE(*,'("Part 1: ",I0)') PART1
  85.      WRITE(*,'("Part 2: ",I0)') PART2
  86.      CALL MPI_SEND(-1,1,MPI_INTEGER,1,2,ICOMM,IERROR)
  87.      CALL MPI_SEND(-1,1,MPI_INTEGER,2,2,ICOMM,IERROR)
  88.      CALL MPI_SEND(-1,1,MPI_INTEGER,3,2,ICOMM,IERROR)
  89.      CALL MPI_SEND(-1,1,MPI_INTEGER,4,2,ICOMM,IERROR)
  90.      CALL MPI_SEND(-1,1,MPI_INTEGER,5,2,ICOMM,IERROR)
  91.   ELSE
  92.      OPS(1)%NARGS=3
  93.      OPS(1)%OP => ADD
  94.      OPS(2)%NARGS=3
  95.      OPS(2)%OP => MULTIPLY
  96.      OPS(3)%NARGS=1
  97.      OPS(3)%OP => INPUT
  98.      OPS(4)%NARGS=1
  99.      OPS(4)%OP => OUTPUT
  100.      OPS(5)%NARGS=2
  101.      OPS(5)%OP => JUMP_IF_TRUE
  102.      OPS(6)%NARGS=2
  103.      OPS(6)%OP => JUMP_IF_FALSE
  104.      OPS(7)%NARGS=3
  105.      OPS(7)%OP => LESS_THAN
  106.      OPS(8)%NARGS=3
  107.      OPS(8)%OP => EQUALS
  108.      SENDTO=(/2,3,4,5,1/)
  109.      RECVFROM=(/5,1,2,3,4/)
  110.      CALL MPI_RECV(N,1,MPI_INTEGER,0,0,ICOMM,STATUS,IERROR)
  111.      ALLOCATE(PROG(0:N),STOREDPROG(0:N))
  112.      CALL MPI_RECV(STOREDPROG,N,MPI_INTEGER,0,1,ICOMM,STATUS,IERROR)
  113.      RUNNING=.TRUE.
  114.      OUTER:DO
  115.         FIRST=.TRUE.
  116.         PROG=STOREDPROG
  117.         SETUP=.TRUE.
  118.         I=0
  119.         DO
  120.            IF(.NOT.RUNNING)EXIT OUTER
  121.            MODES=PROG(I)/100
  122.            OPCODE=MODULO(PROG(I),100)
  123.            IF(OPCODE.EQ.99)EXIT
  124.            CALL OPS(OPCODE)%OP(MODES,PROG(I+1:I+OPS(OPCODE)%NARGS),I)
  125.         END DO
  126.         IF(IRANK.EQ.5) CALL MPI_SEND(LASTOUT,1,MPI_INTEGER,0,999,ICOMM,IERROR)
  127.         IF(IRANK.EQ.1) CALL MPI_RECV(LASTOUT,1,MPI_INTEGER,5,3,ICOMM,STATUS,IERROR)
  128.      END DO OUTER
  129.   END IF
  130.   CALL MPI_FINALIZE(IERROR)
  131.  
  132. CONTAINS
  133.   SUBROUTINE ADD(MODES,PARAMS,I)
  134.     INTEGER, INTENT(IN) :: MODES, PARAMS(3)
  135.     INTEGER :: A,B
  136.     INTEGER, INTENT(INOUT) :: I
  137.     I=I+4
  138.    
  139.     IF(MODULO(MODES,10).EQ.0)THEN
  140.        A=PROG(PARAMS(1))
  141.     ELSE
  142.        A=PARAMS(1)
  143.     END IF
  144.     IF(MODULO(MODES,100)/10.EQ.0)THEN
  145.        B=PROG(PARAMS(2))
  146.     ELSE
  147.        B=PARAMS(2)
  148.     END IF
  149.     PROG(PARAMS(3))=A+B
  150.   END SUBROUTINE ADD
  151.  
  152.   SUBROUTINE MULTIPLY(MODES,PARAMS,I)
  153.     INTEGER, INTENT(IN) :: MODES, PARAMS(3)
  154.     INTEGER :: A,B
  155.     INTEGER, INTENT(INOUT) :: I
  156.     I=I+4
  157.  
  158.     IF(MODULO(MODES,10).EQ.0)THEN    
  159.        A=PROG(PARAMS(1))
  160.     ELSE
  161.        A=PARAMS(1)
  162.     END IF
  163.     IF(MODULO(MODES,100)/10.EQ.0)THEN
  164.        B=PROG(PARAMS(2))
  165.     ELSE
  166.        B=PARAMS(2)
  167.     END IF
  168.     PROG(PARAMS(3))=A*B
  169.   END SUBROUTINE MULTIPLY
  170.  
  171.   SUBROUTINE INPUT(MODES,PARAMS,I)
  172.     INTEGER, INTENT(IN) :: MODES, PARAMS(3)
  173.     INTEGER :: A
  174.     INTEGER, INTENT(INOUT) :: I
  175.     I=I+2
  176.     IF(SETUP)THEN
  177.        CALL MPI_RECV(A,1,MPI_INTEGER,0,2,ICOMM,STATUS,IERROR)
  178.        IF(A<0)RUNNING=.FALSE.
  179.        SETUP=.FALSE.
  180.     ELSE
  181.        IF(FIRST.AND.IRANK.EQ.1)THEN
  182.           CALL MPI_RECV(A,1,MPI_INTEGER,0,3,ICOMM,STATUS,IERROR)
  183.           FIRST=.FALSE.
  184.        ELSE
  185.           CALL MPI_RECV(A,1,MPI_INTEGER,RECVFROM(IRANK),3,ICOMM,STATUS,IERROR)
  186.        END IF
  187.     END IF
  188.     PROG(PARAMS(1))=A
  189.   END SUBROUTINE INPUT
  190.  
  191.   SUBROUTINE OUTPUT(MODES,PARAMS,I)
  192.     INTEGER, INTENT(IN) :: MODES, PARAMS(3)
  193.     INTEGER :: A,B
  194.     INTEGER, INTENT(INOUT) :: I
  195.     I=I+2
  196.  
  197.     IF(MODULO(MODES,10).EQ.0)THEN
  198.        A=PROG(PARAMS(1))
  199.     ELSE
  200.        A=PARAMS(1)
  201.     END IF
  202.     IF(MODULO(MODES,100)/10.EQ.0)THEN
  203.        B=PROG(PARAMS(2))
  204.     ELSE
  205.        B=PARAMS(2)
  206.     END IF
  207.     CALL MPI_SEND(A,1,MPI_INTEGER,SENDTO(IRANK),3,ICOMM,IERROR)
  208.     LASTOUT=A
  209.   END SUBROUTINE OUTPUT
  210.  
  211.   SUBROUTINE JUMP_IF_TRUE(MODES,PARAMS,I)
  212.     INTEGER, INTENT(IN) :: MODES, PARAMS(2)
  213.     INTEGER :: A,B
  214.     INTEGER, INTENT(INOUT) :: I
  215.  
  216.     IF(MODULO(MODES,10).EQ.0)THEN
  217.        A=PROG(PARAMS(1))
  218.     ELSE
  219.        A=PARAMS(1)
  220.     END IF
  221.     IF(MODULO(MODES,100)/10.EQ.0)THEN
  222.        B=PROG(PARAMS(2))
  223.     ELSE
  224.        B=PARAMS(2)
  225.     END IF
  226.     IF(A.NE.0)THEN
  227.        I=B
  228.     ELSE
  229.        I=I+3
  230.     END IF
  231.   END SUBROUTINE JUMP_IF_TRUE
  232.  
  233.   SUBROUTINE JUMP_IF_FALSE(MODES,PARAMS,I)
  234.     INTEGER, INTENT(IN) :: MODES, PARAMS(2)
  235.     INTEGER :: A,B
  236.     INTEGER, INTENT(INOUT) :: I
  237.  
  238.     IF(MODULO(MODES,10).EQ.0)THEN
  239.        A=PROG(PARAMS(1))
  240.     ELSE
  241.        A=PARAMS(1)
  242.     END IF
  243.     IF(MODULO(MODES,100)/10.EQ.0)THEN
  244.        B=PROG(PARAMS(2))
  245.     ELSE
  246.        B=PARAMS(2)
  247.     END IF
  248.     IF(A.EQ.0)THEN
  249.        I=B
  250.     ELSE
  251.        I=I+3
  252.     END IF
  253.   END SUBROUTINE JUMP_IF_FALSE
  254.  
  255.   SUBROUTINE LESS_THAN(MODES,PARAMS,I)
  256.     INTEGER, INTENT(IN) :: MODES, PARAMS(3)
  257.     INTEGER :: A,B
  258.     INTEGER, INTENT(INOUT) :: I
  259.     I=I+4
  260.  
  261.     IF(MODULO(MODES,10).EQ.0)THEN    
  262.        A=PROG(PARAMS(1))
  263.     ELSE
  264.        A=PARAMS(1)
  265.     END IF
  266.     IF(MODULO(MODES,100)/10.EQ.0)THEN
  267.        B=PROG(PARAMS(2))
  268.     ELSE
  269.        B=PARAMS(2)
  270.     END IF
  271.     IF(A<B)THEN
  272.        PROG(PARAMS(3))=1
  273.     ELSE
  274.        PROG(PARAMS(3))=0
  275.     END IF
  276.   END SUBROUTINE LESS_THAN
  277.  
  278.   SUBROUTINE EQUALS(MODES,PARAMS,I)
  279.     INTEGER, INTENT(IN) :: MODES, PARAMS(3)
  280.     INTEGER :: A,B
  281.     INTEGER, INTENT(INOUT) :: I
  282.     I=I+4
  283.  
  284.     IF(MODULO(MODES,10).EQ.0)THEN    
  285.        A=PROG(PARAMS(1))
  286.     ELSE
  287.        A=PARAMS(1)
  288.     END IF
  289.     IF(MODULO(MODES,100)/10.EQ.0)THEN
  290.        B=PROG(PARAMS(2))
  291.     ELSE
  292.        B=PARAMS(2)
  293.     END IF
  294.     IF(A.EQ.B)THEN
  295.        PROG(PARAMS(3))=1
  296.     ELSE
  297.        PROG(PARAMS(3))=0
  298.     END IF
  299.   END SUBROUTINE EQUALS
  300.  
  301. END PROGRAM DAY7
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement