Удалить повторяющиеся строки в Fortran77

У меня есть файл, который представляет собой таблицу из 119 столбцов (разделенных пробелами) и около 50000 строк (строк). Я хотел бы удалить дублированные записи, то есть те строки, которые имеют все идентичные столбцы (119). Я набросал этот код:

      PROGRAM deldup

      IMPLICIT NONE

      DOUBLE PRECISION PAR(119),PAR2(119)
      INTEGER I,J,K,LINE,TREP
      CHARACTER filename*40

c Get the input file name
      CALL getarg(1,filename)

c File where the results will be stored.
      OPEN(29, FILE="result.dat", STATUS='UNKNOWN')

c Current line number
      LINE=0
c counting repeated points
      TREP=0

 101  LINE=LINE+1
      OPEN(27, FILE=filename, STATUS='OLD')

c     Verifying that we are not in the first line... and we read the
c     corresponding one
      IF (LINE.NE.1) THEN 
         DO K=1,LINE-1
            READ(27,11,ERR=103,END=9999)
         END DO
      ENDIF
      READ(27,11,ERR=103,END=9999) (PAR(I),I=1,119)

c     Start comparing line by line looking for matches. If a match is
c     found , close the
c     file and open it again to read the next line. If the end of file is
c     reached and not iqual rows found, write the line in "results.dat"

 102  READ(27, 11,END=104, ERR=102) (PAR2(I),I=1,119)
      DO J=1,119
         IF ( PAR(J).NE.PAR2(J) ) THEN
            GOTO 102
         ELSEIF (J.EQ.119) THEN
            TREP=TREP+1
            GOTO 103
         ENDIF
      END DO

 104  WRITE(29,11) (PAR(I),I=1,119)

 103  CLOSE(27)
      GOTO 101

 9999 WRITE(*,*) "DONE!,", TREP, "duplicated points found!"
      CLOSE(27)
      CLOSE(28)
      CLOSE(29)

 11   FORMAT(200E14.6)
      END

который на самом деле работает, это просто супер медленно. Зачем? Есть ли библиотека, которую я могу использовать? Извините за мое невежество, я совершенно новый с Fortran77.

2 ответа

Решение

Для каждой строки вы открываете и закрываете исходный файл, что очень медленно! Чтобы ускорить процесс, вы можете просто использовать rewind,

Однако основная проблема заключается в сложности вашего алгоритма: O(n^2) Вы сравниваете каждую строку с каждой другой строкой. Для начала я бы сохранил список уникальных строк и сравнил их с этим списком. Если новая строка уже указана, отмените ее, если нет - это новая уникальная строка. Это уменьшит сложность до O(n*m)с (надеюсь) m << n (m - количество уникальных строк). Сортировка строк, вероятно, ускорит сравнение.

Следующим замечанием будет переход от ввода / вывода к памяти! Чтение полного файла в массив или, по крайней мере, сохранение списка уникальных строк в памяти. Массив двойной точности 50 000x119 требует ~45 МБ ОЗУ, поэтому я думаю, что это должно быть выполнимо;-) Запишите результат обратно одним куском на последнем этапе.

Первый вопрос: зачем придерживаться Fortran 77? С появлением g95 и gfortran нет никаких реальных причин использовать стандарт, который устарел уже более двадцати лет.

Канонический способ удалить дубликаты - это отсортировать их, удалить дубликаты, а затем вывести их в исходном порядке. Если вы используете хороший алгоритм сортировки, такой как быстрая сортировка или heapsort, это даст вам производительность O(n log n).

Еще одно замечание: также неплохо было бы добавлять магические числа, такие как 119, в вашу программу в операторы PARAMETER.

Другие вопросы по тегам