Найти то, чего нет

Задача для школьников.

Имеется текстовый файл, в котором в каждой строке записана какая-то информация (не важно какая), принятая из внешнего устройства. Информация принимается в виде пакетов, каждый пакет занимает одну строку. Все пакеты однотипны.

Вот пример такого файла:

20:18:23:07 26 30.0 2162
20:18:23:08 26 30.0 2163
20:18:23:09 18 30.0 2164
20:18:23:10 33 30.0 2165
20:18:23:11 25 30.0 2166
20:18:23:12 31 30.0 2167
20:18:23:13 27 30.0 2168
20:18:23:14 32 30.0 2169
20:18:23:15 23 30.0 2170
20:18:23:16 25 30.0 2171
...
21:06:20:34 31 30.0 45224
21:06:20:35 19 30.0 45225
21:06:20:36 18 30.0 45226
21:06:20:37 27 30.0 45227
21:06:20:38 29 30.0 45228

В четвертом (последнем) столбце записан порядковый номер пакета.

Номер первого принятого пакета равен 2162, номер последнего принятого пакета — 45228.
Иначе говоря, было отправлено

(45228 — 2162) + 1 = 43067 пакетов.

Но файл содержит 43062 строки:

$ wc -l packs.txt
43062 packs.txt

Это значит, что при приеме были потери. Причем было было потеряно

43067 — 43062 = 5 пакетов.

Требуется найти номера потерянных пакетов.

Решение

Задачу будем решать на Питоне.

#!/usr/bin/env python

import sys

L = [int(line.split()[4]) for line in open(sys.argv[1]).readlines()]
#print len(L)

prev = L[0] - 1
for n in L :
  if not (prev + 1) == n :
    print (prev + 1)
  prev = n

В пятой строке строке программы создается список. Это чисто Питоновская технология.
Но я должен признаться, я все-таки мыслю не по-Питоновски, а по-Сишному. Мне сложно понимать такие конструкции, хотя уже кое-что могу состряпать (например, это).

Но вот чтобы просканировать список на отсутствие последовательных чисел, тут я не знаю как делать по-Питоновски. Поэтому вторую часть задачя я решал по-Сишному. Я буду признателен, если кто-нибудь сможет выразить вторую часть программы по-Питоновски.

Реклама

10 responses to “Найти то, чего нет

  1. for element in range(L[0], L[-1]):
        if L.count(element) == 0:
            print(element)
    
    • Ай, блин! Не туда ткнул… И форматирование сайт съел =(
      В общем, у меня вот такое придумалось. Строим новый список с закрытыми «дырами». Т.е. в случае L = [2,5,7], новый список будет [2,3,4,5,6] (да, похорошему, надо бы range(L[0], L[-1]+1), но последний элемент-то в любом случае есть в исходном списке).
      Дальше идем по новому списку и сравниваем его со старым. Если какой-то элемент отсутствует в старом списке, то печатаем его.

      • А вообще, да. Было бы более правильно составить список без «дыр» и уже по нему проверять имеющийся список. Признаю, у меня не совсем хорошо реализован алгоритм.

        Хочу также внести в Вашу идею свои 5 копеек: во букварях советуют вместо range использовать xrange. Я не уверен, что это сыграет большую роль на современных компах, но с другой стороны — а почему бы не попробовать?

  2. Этот код на третьем питоне написан, надо было это указать, наверное. В нем переименовали xrange в range.

  3. Здравствуйте
    А как можно решить такую задачу.
    Есть файл с набором данных в виде строк.
    Как сделать чтобы программа на питоне читала данный файл и выдавала строки в последовательный порт с необходимой скоростью?
    Спасибо.

    • Здравствуйте, Nick!

      Сама по себе задача не сложная, но Вы умолчали ряд важных факторов. Поэтому я не могу ответить на Ваш вопрос.

      Для того чтобы приступить к решению Вашей задачи нужно знать следующие моменты:

      1. В последовательный порт выдаются именно строки, а не символы?
      2. Как часто или с какой периодичностью происходит отправка строк (символов)?
      3. Строки имеют произвольную длину?
      4. Какая может быть максимальная длина строки? А минимальная?
      5. Сколько строк в файле? (хотя бы для ориентации — 10 строк, 1000 или 10000000.)

      Это какое-то учебное задание?

      • 1. Да, строки
        2. 10 раз в секунду
        3. Да
        4. 30-100 символов
        5. Пусть будет 1000

        Это не учебное задание. Это для себя, помоделировать работу устройства

      • Ну, как бы вот…

        #!/usr/bin/env python3
        # coding:utf-8
        
        '''
        poet.py
        
        Прога выводит содержимое текстового файла построчно в последовательный порт.
        '''
        
        HELP = '''
        Используйте так:
        
        poet period_ms serial file
        
        где
          period_ms -- период вывода строк, в миллисекундах
          serial    -- последовательный порт, например, /dev/ttyUSB0
          file      -- текстовый файл
        '''
        
        ECHO = True
        
        
        import sys
        import time
        import serial
        
        if __name__ == "__main__":
          if len(sys.argv) < 3:
            print(HELP)
            exit()
            
          dt = int(sys.argv[1])
          if not 1 <= dt <= 1000:
            print(u"Недопустимый значение периода {0}".format(dt))
            exit()
          
          try:  
            ser = serial.Serial(sys.argv[2])
          except:
            print(u"Порт {0} не доступен".format(sys.argv[2]));
            exit()
          
          try: 
            with open(sys.argv[3], "rt") as fin:
              for line in fin:
                ser.write(bytearray(line, encoding="utf-8"))
                if ECHO:
                  print(line, end = '')
                time.sleep(dt / 1000.)
          except:
            print(u"Не могу открыть файл {0}".format(sys.argv[3]))
            exit
        

        Только надо отдавать себе отчёт, что эта прога работает на компе с операционной системой, которая не принадлежит к классу операционных систем реального времени. Поэтому жестко заданный времена отправки строк в последовательный порт могут не выдерживаться. А это значит, что создавать в проге дополнительный поток, создавать таймер и по таймеру осуществлять вывод строк не имеет смысла.

        Это с одной стороны. А с другой — компы настолько быстрые, что вывод сотни байт происходит практически мгновенно.

        Поэтому будет более разумно написать прогу так, что она будет выводить строки через равные промежутки времени, периодически притормаживая свой главный поток.

        Прога не коммерческая. Написана на рабоче-крестьянский манер.

        В проге присутствует логическая переменная ECHO, которая определяет будет ли одновременно осуществляться вывод информации в терминал.

      • Спасибо. Буду пробовать.
        А вообще, надо садиться и изучать Питон.

      • Надо. Тут как в искусстве — чем больше упражняешься, тем лучше владеешь инструментом.

        Как съесть слона? (с)

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s