go Subroutine

recursive subroutine go(i, j, direction_from)

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: i

grid coordinate

integer, intent(in) :: j

grid coordinate

integer, intent(in) :: direction_from

direction coming from (TOP,BOTTOM,LEFT,RIGHT


Called by

proc~~go~~CalledByGraph proc~go problem_16::go proc~go->proc~go program~problem_16 problem_16 program~problem_16->proc~go

Source Code

    recursive subroutine go(i,j,direction_from)
        integer,intent(in) :: i, j !! grid coordinate
        integer,intent(in) :: direction_from !! direction coming from (TOP,BOTTOM,LEFT,RIGHT

        integer :: k

        if (i>nrows .or. i<1 .or. j>ncols .or. j<1) return ! off the board
        if (visited(direction_from, i, j)) return ! this case has already been done
        visited(direction_from, i, j) = .true. ! mark this one as visited in this direction

        associate (c => array(i,j))
            select case (c)
            case('.') ! continue in same direction
                k = 1
                do
                    ! loop until we hit something else
                    ! (to avoid unnecessary recursion)
                    select case (direction_from)
                    case(TOP)  ! V
                        if ((i+k)>nrows) return
                        if (array(i+k,j)/='.') then
                            call go(i+k,j,direction_from)
                            return
                        end if
                        visited(direction_from, i+k,j) = .true.
                    case(BOTTOM)  ! ^
                        if ((i-k)<1) return
                        if (array(i-k,j)/='.') then
                            call go(i-k,j,direction_from)
                            return
                        end if
                        visited(direction_from, i-k,j) = .true.
                    case(LEFT)  ! -->
                        if ((j+k)>ncols) return
                        if (array(i,j+k)/='.') then
                            call go(i,j+k,direction_from)
                            return
                        end if
                        visited(direction_from, i,j+k) = .true.
                    case(RIGHT)  ! <--
                        if ((j-k)<1) return
                        if (array(i,j-k)/='.') then
                            call go(i,j-k,direction_from)
                            return
                        end if
                        visited(direction_from, i,j-k) = .true.
                    end select
                    k = k + 1
                end do
            case('-')
                select case (direction_from)
                case(TOP,BOTTOM)  ! V, ^
                    call go(i,j+1,LEFT) ! split
                    call go(i,j-1,RIGHT)
                case(LEFT)  ! -->
                    call go(i,j+1,LEFT)
                case(RIGHT)  ! <--
                    call go(i,j-1,RIGHT)
               end select
            case('|')
                select case (direction_from)
                case(TOP)  ! V
                    call go(i+1,j,TOP)
                case(BOTTOM)  ! ^
                    call go(i-1,j,BOTTOM)
                case(LEFT,RIGHT)  ! -->, <--
                    call go(i+1,j,TOP)
                    call go(i-1,j,BOTTOM)
                end select
            case('/')
                select case (direction_from)
                case(TOP)  ! V
                    call go(i,j-1,RIGHT)
                case(BOTTOM)  ! ^
                    call go(i,j+1,LEFT)
                case(LEFT)  ! -->
                    call go(i-1,j,BOTTOM)
                case(RIGHT)  ! <--
                    call go(i+1,j,TOP)
                end select
            case('\')
                select case (direction_from)
                case(TOP)  ! V
                    call go(i,j+1,LEFT)
                case(BOTTOM)  ! ^
                    call go(i,j-1,RIGHT)
                case(LEFT)  ! -->
                    call go(i+1,j,TOP)
                case(RIGHT)  ! <--
                    call go(i-1,j,BOTTOM)
                end select
            end select
        end associate

    end subroutine go