Programming challenge (19th century writers)

Well, I have not achieved complete genericity, but with a bit of help, I do have a subroutine that can reverse an array in place without taking particular care about the data type:

! reverse_array.f90 --
!     Attempt to create a generic routine that reverses an array - in place
!
module reverse_array
    implicit none

contains
subroutine reverse( array, assign )
    class(*), dimension(:), intent(inout), pointer     :: array
    interface
        subroutine assign( a, b )
            class(*), intent(out) :: a
            class(*), intent(in)  :: b
        end subroutine assign
    end interface

    class(*), allocatable                              :: tmp
    integer                                            :: i, j

    allocate( tmp, mold=array(1) )

    do i = 1,size(array)/2
        j        = size(array) + 1 - i
        call assign( tmp, array(i) )
        call assign( array(i), array(j) )
        call assign( array(j), tmp )
    enddo
end subroutine reverse
end module reverse_array

! test --
!     Test this implementation
!
program test_reverse_array
    use reverse_array

    type :: person
        ! Each person has a firstname, lastname, birth_year, and death year.
        character(len=30) :: firstname
        character(len=30) :: lastname
        integer           :: birth_year
        integer           :: death_year
    end type

    type(person), allocatable, dimension(:), target :: table
    class(*), dimension(:), pointer                 :: ptable

    table = [ &
        person( "Miguel",  "de Cervantes", 1547, 1616 ), &
        person( "Charles", "Dickens",      1812, 1870 ), &
        person( "George",  "Orwell",       1903, 1950 ), &
        person( "Ernest",  "Hemingway",    1899, 1961 ), &
        person( "William", "Shakespeare",  1564, 1616 ), &
        person( "Leo",     "Tolstoy",      1828, 1910 ), &
        person( "Scott",   "Fitzgerald",   1896, 1940 ), &
        person( "Franz",   "Kafka",        1883, 1924 ), &
        person( "Mark",    "Twain",        1835, 1910 ), &
        person( "Roald",   "Dahl",         1916, 1990 ), &
        person( "James",   "Joyce",        1882, 1941 ) ]

    ptable => table
    call reverse( ptable, assign_person )

    write(*,'(2a,2i6)') table

contains
subroutine assign_person( a, b )
    class(*), intent(out) :: a
    class(*), intent(in)  :: b

    select type( a )
        type is (person)
            select type( b )
                type is (person)
                    a = b
            end select
    end select
end subroutine assign_person
end program test_reverse_array

Out of laziness, I stole, eh, copied, the person data type and the table of persons from the above example.

1 Like