Типовая задача

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

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

Поток данных представляет из себя поток символьных строк, разделенных символом «новой строки» — ‘\n’.

Каждая строка состоит из серии чисел. Количество чисел в строках неизменно и всегда равно 423 числа. Числа разделяются символом «пробел».

Мощность потока — одна строка в секунду.

Все числа в строке — целые, их значения находятся в диапазоне от -32768 по +32767 включительно. Те числа, с которыми предстоит работать, имеют еще более узкий диапазон: от 0 по 4095. То есть только положительные.

Причем работать предстоит не со всеми числами сразу, а с группами по 100 чисел, расположенных друг за другом. Количество групп — четыре. Первая группа начинается с числа, находящегося на позиции (в колонке) 12, вторая — с позиции 112, третья — с позиции 212 и четвертая — с позиции 312.

Вот пример потока данных, в котором имеется три символьных строки:


0 0 1216 702 0 1226 2068 2070 2040 2068 4095 3165 3185 3190 3166 3188 3189 3165 3190 3189 3165 3192 3188 3165 3192 3187 3166 3193 3188 3168 3193 3188 3169 3195 3189 3168 3195 3188 3170 3196 3187 3170 3200 3188 3172 3200 3188 3171 3200 3188 3170 3200 3189 3172 3200 3190 3172 3200 3189 3166 3166 3168 3187 3196 3172 3193 3194 3173 3194 3196 3173 3195 3195 3172 3200 3195 3173 3200 3192 3172 3200 3192 3174 3200 3192 3173 3200 3193 3174 3200 3192 3175 3201 3191 3176 3200 3190 3172 3202 3190 3174 3201 3190 3174 3202 3189 3172 3201 3188 3174 1820 2072 2050 2064 2079 2050 2064 2078 2048 2060 2077 2048 2061 2079 2050 2063 2080 2050 2062 2078 2048 2061 2080 2048 2061 2077 2049 2061 2076 2049 2060 2077 2048 2060 2078 2049 2065 2077 2048 2058 2074 2048 2058 2077 2048 2059 2078 2048 2066 2077 2048 2061 2077 2048 2057 2077 2049 2060 2079 2048 2059 2078 2048 2061 2075 2048 2060 2074 2048 2060 2076 2048 2059 2075 2048 2056 2076 2048 2061 2077 2048 2059 2076 2048 2058 2076 2048 2057 2076 2048 2060 2078 2048 2062 2076 2048 2057 2076 2048 2055 55 946 914 928 937 912 931 937 912 932 937 911 935 937 910 935 935 910 935 936 912 936 935 911 939 934 911 940 934 912 941 933 913 941 933 913 941 933 912 940 933 912 942 932 914 943 932 915 943 934 915 943 932 915 944 932 915 944 933 916 944 932 917 942 933 916 944 933 915 945 932 915 945 933 916 945 932 917 943 934 916 943 931 915 945 930 915 943 932 914 943 932 914 943 932 915 943 929 914 942 2772 2048 2062 2075 2048 2054 2074 2048 2056 2073 2048 2056 2074 2048 2054 2072 2048 2056 2073 2048 2054 2072 2048 2054 2074 2048 2056 2073 2048 2054 2070 2048 2055 2073 2048 2054 2076 2048 2053 2072 2048 2056 2073 2048 2051 2070 2048 2056 2075 2048 2054 2072 2040 2052 2071 2048 2055 2073 2040 2054 2073 2048 2056 2074 2048 2054 2072 2048 2056 2075 2048 2057 2076 2048 2052 2071 2048 2053 2074 2048 2054 2072 2048 2056 2072 2048 2059 2072 2048 2051 2074 2048 2059 2075 2048 2055 2073 2048 2056 2072 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1217 702 0 1226 2059 2074 2048 2060 4095 3161 3180 3190 3166 3187 3189 3165 3187 3189 3166 3190 3189 3165 3191 3190 3165 3192 3188 3168 3194 3189 3167 3195 3189 3168 3196 3189 3168 3196 3188 3169 3200 3187 3171 3200 3188 3172 3200 3187 3173 3200 3188 3172 3200 3188 3172 3200 3188 3169 3169 3166 3189 3193 3172 3194 3194 3173 3195 3194 3174 3196 3194 3172 3200 3194 3172 3200 3193 3174 3200 3192 3175 3200 3193 3173 3202 3192 3174 3200 3190 3174 3201 3190 3174 3201 3189 3175 3200 3190 3174 3200 3190 3175 3202 3188 3175 3201 3187 3174 1821 2072 2048 2066 2078 2051 2064 2078 2052 2061 2077 2048 2060 2078 2050 2063 2079 2048 2063 2080 2048 2064 2078 2050 2060 2077 2048 2059 2077 2051 2062 2080 2048 2063 2077 2049 2061 2076 2048 2064 2077 2048 2060 2079 2048 2060 2076 2048 2060 2075 2048 2060 2076 2050 2057 2077 2048 2059 2077 2048 2058 2077 2048 2063 2078 2048 2062 2077 2048 2057 2077 2048 2059 2078 2048 2060 2077 2048 2060 2075 2048 2058 2077 2048 2058 2078 2048 2058 2076 2048 2059 2080 2048 2060 2076 2048 2060 2078 2048 2060 55 945 914 928 938 912 930 936 911 933 936 911 933 936 911 936 935 911 937 934 910 937 934 911 939 933 911 939 934 912 941 934 912 940 934 911 942 933 911 941 931 914 943 933 914 942 932 914 943 933 913 944 932 915 945 931 916 943 931 917 944 933 916 944 932 916 944 931 916 945 931 917 944 932 916 944 933 917 945 932 917 944 931 917 943 930 918 943 931 916 942 931 916 943 930 915 943 929 915 941 2774 2048 2062 2072 2048 2054 2073 2048 2057 2073 2048 2056 2074 2048 2056 2073 2048 2058 2073 2048 2056 2073 2048 2056 2071 2048 2056 2072 2048 2054 2073 2048 2057 2072 2048 2055 2072 2048 2054 2074 2048 2057 2076 2048 2055 2073 2048 2056 2072 2048 2055 2071 2048 2054 2072 2048 2056 2073 2039 2053 2071 2048 2055 2073 2048 2053 2072 2048 2054 2072 2048 2054 2076 2048 2054 2073 2048 2056 2073 2048 2053 2073 2048 2054 2073 2048 2056 2074 2048 2053 2073 2048 2055 2073 2048 2055 2074 2048 2057 2073 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1218 703 0 1232 2048 2069 2069 2048 4095 3179 3171 3197 3180 3171 3200 3180 3173 3200 3182 3170 3200 3182 3172 3200 3182 3172 3197 3182 3171 3200 3183 3172 3200 3184 3172 3200 3183 3171 3200 3184 3173 3200 3184 3172 3200 3185 3174 3200 3184 3174 3201 3186 3174 3200 3186 3173 3200 3202 3202 3191 3194 3172 3194 3194 3172 3196 3193 3172 3200 3193 3172 3200 3192 3174 3200 3192 3174 3201 3192 3174 3200 3190 3175 3201 3192 3176 3200 3190 3175 3201 3192 3174 3202 3190 3175 3202 3190 3176 3201 3189 3176 3201 3190 3174 3202 3189 3175 3202 1858 2052 2058 2078 2052 2062 2079 2051 2065 2079 2050 2064 2077 2050 2059 2077 2049 2060 2078 2050 2063 2078 2049 2064 2077 2050 2064 2077 2048 2061 2076 2050 2062 2078 2048 2061 2080 2049 2061 2076 2048 2060 2077 2048 2058 2078 2048 2059 2075 2048 2058 2079 2048 2062 2077 2048 2060 2076 2048 2057 2075 2048 2059 2075 2048 2060 2077 2048 2059 2074 2048 2059 2076 2048 2058 2076 2048 2058 2076 2048 2057 2076 2048 2059 2078 2048 2063 2077 2048 2057 2075 2048 2057 2076 2048 2059 2078 2048 2060 2076 69 917 931 938 913 934 938 912 933 937 912 936 937 911 936 935 910 937 935 910 938 934 911 939 934 911 940 936 912 940 932 912 940 934 912 942 933 912 940 933 913 940 933 913 941 934 914 943 932 915 943 932 916 941 931 916 943 931 914 942 932 915 945 932 916 946 931 917 945 933 918 945 931 915 945 931 918 946 929 917 945 930 918 944 931 916 944 930 916 945 928 917 944 931 916 944 931 916 942 930 2740 2073 2071 2040 2061 2075 2048 2056 2072 2048 2056 2073 2048 2055 2073 2048 2056 2072 2048 2054 2072 2048 2057 2072 2048 2055 2073 2048 2056 2073 2048 2057 2074 2048 2053 2072 2048 2056 2074 2048 2055 2074 2048 2055 2072 2048 2055 2072 2048 2053 2072 2048 2056 2072 2048 2055 2073 2048 2054 2072 2048 2056 2075 2048 2054 2073 2048 2057 2073 2048 2054 2071 2048 2054 2072 2048 2057 2074 2048 2051 2072 2048 2056 2076 2048 2056 2073 2048 2056 2071 2048 2054 2074 2048 2053 2075 2048 2059 2073 2048 0 0 0 0 0 0 0 0 0 0 0 0 0

Возможно, придется откинуть несколько чисел (например по 5 чисел) в начале и в конце группы, и произвести вычисления на меньшем количестве чисел (для примера — на 90 числах).

Какие вычисления нужно произвести в каждой группе чисел

1. Нужно посчитать среднее арифметическое значение. (Математическое ожидание).

2. Найти минимальное и максимальное значение в группе.

3. Вычислить в процентном отношении максимальное отклонение от среднего.

Особые требования к программе

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

Ориентировочный формат вывода следующий:


3172.3 7.1 2047.7 12.4 933.2 6.5 2056.5 10.1
3124.3 6.8 2051.7 11.8 942.5 8.2 2062.1 9.8

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

Язык решения не оговаривается. Можно написать прогу на Python, можно на Perl, можно на C/C++. Можно обойтись даже средствами bash, но я что-то не особо представляю как можно этим методом будет быстро преобразовать под сотню символьных выражений чисел в числа, чтобы посчитать заданные значения.

Задача, в общем-то не для прожженого разработчика-программиста, а для ученика старшего класса. Но ее нужно сделать. Срок изготовления имеет значение — чем раньше, тем лучше.

Думаю, что я эту работу и сам сделаю, но поскольку эта работа простая, то можно просто поучаствовать в «корпоратиффчике». Типа меня пожурить за корявый код, и предложить своё решение.

Ну, вроде бы всё сказал.

Вот, для затравки мой вариант:

#!/usr/bin/env python
#coding:utf8

'''
Утилита предназначена для вычисления среднего значения и отклонения от него
в пакетах от Модуля Электро-Каротажа.

Пакет ПРК разбивается на четыре группы, в каждой из которых производятся
заявленные выше вычисления.
'''

LeftIndex = 12
GroupLength = 100
LeftSkip = 5
RightSkip = 3


def get_ave(group):
  sum = 0.0
  for number in group:
    sum += number

  group_ave = sum / len(group)
  group_min = min(group)
  group_max = max(group)
  
  group_dev = (group_max - group_min) / 2.0 * (100.0 / group_ave)
  
  return group_ave, group_dev


def conv(chlist):
  intlist = []
  for number in chlist:
    intlist.append(int(number))
  
  return intlist

if __name__ == "__main__":
  while True:
    try:
      row = raw_input()
      li = row.split()
      
      for i in range(4):
        group = li[(LeftIndex + GroupLength * i + LeftSkip):(LeftIndex + GroupLength * (i + 1) - RightSkip)]
        int_group = conv(group)      
        int_ave, int_dev = get_ave(int_group)    
        print "%.2f %.2f\t" % (int_ave, int_dev),
      
      print
      
    except:
      exit(0)

Это не идеальный вариант, тут еще можно много чего улучшить. Важно, что он работает. Точнее — программа отработала своё назначение и более уже почти не нужна. С ее помощью я нащупал тонкую грань аппаратной настройки модуля МЭК, где количество помех в сигнале минимально.

Прога запускается незатейливо:

$ cat /dev/ttyUSB0 | ./prk-ave.py

и выводит на экран вот такой расколбас:

prk-2015-v.0.3-ave

Вот результат:

prk-2015-v.03

Сравните с тем, что было:

prk-2015-1

Если кому интересно как я решил проблему устранения помех по питанию, то это мне удалось сделать методом синхронизации работы АЦП и источника питания.

 

UPDATE 28.05.2015

Ну вот, новая версия проги, «причёсанная и натрахмаленная»:

#!/usr/bin/env python
#coding:utf8

'''
Утилита предназначена для вычисления среднего значения и отклонения от него
в пакетах от Модуля Электро Каротажа (МЭК.

Пакет ПРК разбивается на четыре группы, в каждой из которых производятся
указанные выше вычисления.

Вывод данных по всем четырем группам осуществляется в однй строку
'''

# Праметры для вычисления начала и конца расположения групп в пакете
LeftIndex = 12
GroupLength = 100
LeftSkip = 5
RightSkip = 3


def main():

  while True:
    try:
      raw_packet = raw_input()     # Пакет в формате монолитной строки символов
      packet = raw_packet.split()  # Пакет в виде списка значений

      # В пакете находятся четыре группы значений
      for i in range(4):

        # Выделим группу значений для анализа
        begin_group = LeftIndex + GroupLength * i + LeftSkip
        end_group = LeftIndex + GroupLength * (i + 1) - RightSkip
        group = packet[begin_group:end_group]

        int_group = [int(value) for value in group]  # Конвертируем симольные значения в числа
        group_ave = sum(int_group) / len(int_group)  # Среднее арифметическое
        group_dev = (100.0 / group_ave) * (max(int_group) - min(int_group)) / 2.0  # Отклонение от ср. арифм.

        print '{0:.2f} {1:.2f} '.format(group_ave, group_dev) , # Не переходим на новую строку!

      print

    except:
      exit(0)


if __name__ == "__main__":
  main()

Прога делает тоже самое, но выглядит более по-Питоновски.

Реклама

6 responses to “Типовая задача

  1. Особо в задачу не вникал, но с точки зрения питоноводства:
    1) Константы надо писать большими буквами.
    2) Функция conv реализуется так:
    def conv(in_list):
    return [int(v) for v in in_list]
    3) В функции get_ave можно применить встроенную функцию sum() https://docs.python.org/2/library/functions.html#sum
    def get_ave(group_list):
    total = sum(group_list)
    group_ave = total / len(group)
    group_min = min(group)
    group_max = max(group)
    group_dev = (group_max — group_min) / 2.0 * (100.0 / group_ave)
    return group_ave, group_dev
    4) Блок try-except должен оборачивать минимальный кусок кода
    5) В print надо использовать .format():
    >>> print ‘{:.2f} = {:.2f}’.format(0.1, 0.2)
    0.10 = 0.20

    • Во! Спасибо!

      С грамотным человеком всегда было приятно побеседовать, ибо в процессе разговора обретаешь знания.

      1) Здесь целая тема. Разольюсь мыслью по дереву и отвечу отдельной статьёй. И, к стати, конкретно по этой проге — я предполагал, что значения этим переменным я буду определять в процессе работы программы. Например, передавать из командной строки или через переменные окружения. Я пока еще сам не определился, чего хочу.

      2) Абсолютно с Вами согласен. Ваш вариант отвечает духу Питона.

      3) Здесь тоже возражений нет. Я знаю о функции sum, но когда начал писать код, забыл об этом — ну в смысле, что есть такая функция. Так что поправка принимается с благодарностью.

      4) Тут тоже отдельная тема. Пока оставлю вопрос без комментариев.

      5) А тут, мне кажется, что этот вопрос на любителя. Мне больше нравится писать по-старинке. Мне, лично мне, так более понятно. Но, это впрочем, дело опыта. Если часто писать форматированный вывод, как Вы, то и к этому стилю тоже можно привыкнуть. Я привык писать так, как написал.

      И да! Знак равенства в строке вывода — лишний! С ним вывод красиво смотрится, и даже легче читается, но при дальнейшей программной обработке он (знак) может начать мешаться. Так что лучше убрать лишние «бантики».

      А в целом, спасибо Вам за Ваш отклик и желание сделать мир лучше!

  2. «Если кому интересно как я решил проблему устранения помех по питанию, то это мне удалось сделать методом синхронизации работы АЦП и источника питания» – решение по месту Ок. Но лучше проектировать БП более тщательно.

    • Юрий, а «более тщательно» — это значит как?

      Вы бы не могли показать, где и что конкретно в БП у меня сделано неправильно?

      Ну, например, вот эта дорожка на печатной плате должна пойти не так, а эдак. Или вот в этом месте нужно установить керамический конденсатор, а в этом конденсатор бесполезен. Или в таких БП нужно использовать не IR21531, а схему на основе мультивибратора на двух транзисторах и ферритовом кольце типа https://embedderslife.wordpress.com/ . Или вместо полевых транзисторов мне нужно было взять биполярные. Ну и так далее. Мне нужен конкретный действенный совет, а не общие слова.
      Я и сам знаю, что нужно «проектировать более тщательнее», но я не знаю как это делать.

      Общие слова, которые Вы произносите, — это ни о чём. Прошу Вас, поделитесь своими соображениями. Необходимые схемы и рисунок печатной платы, параметры ферритового трансформатора — любую информацию, которая Вам нужна для анализа — я с удовольствием предоставлю.

      А то получается как-то не очень красиво.

      — Папа, я упал с велосипеда-а-а и содрал коленку…
      — Сынок, нужно более тщательно уметь ездить.
      — А по конкретнее?
      — В гугел!

      К стати, даже фирменные блоки питания TRACO POWER тоже не хило фонят. Товарищ из другой организации, занимается примерно тем же чем я, так он вообще отключает Траковские модули по входу Enable, чтобы во время измерения они создавали помех. В общем-то, тоже метод. А что делать?

      Для справки. У меня помеха от БП попадает на высокоомные входы операционного усилителя, включенного по схеме дифференциального усилителя. Rвх по обоим входам относительно общего провода — 1 МОм, дифференциальное Rвх = 2 МОм.

      С платы входного усилителя проброшены две витые пары на токоприемные электроды, которые представляют из себя металлические пружины с примерными габаритами 10 х 50 мм. Витая пара — это два провода свитых вместе с шагом повива примерно 100 мм. Одна пара для инвертирующего входа, другая — для неинвертирующего. Один из проводков в каждой паре, понятно, подключен ко входу усилителя и токоприемной пружине. Второй проводок в парах — это общий (экранирующий) провод. Он подключен только к общему проводу на печатной плате операционника. Второй конец этих экранирующих проводов в парах никуда не подключен.

      Когда МЭК будет собран в корпус, к этим пружинам добавятся еще латунные кольца внешним диаметром 50 мм, шириной 5 мм. Расстояние между кольцами 100 мм, длина витых пар к усилителю 120-130 мм. Короче не сделать.

      Почему используется витая пара, а не экранированный провод? Потому, что провода находятся внутри металлического (дюраль) шасси. Шасси гальванически связано с оплеткой геофизического кабеля.

      Расстояние от входов усилителя до блока питания примерно 300-350 мм, что, в общем-то, достаточно далеко, чтобы оказывать воздействие на входы усилителя. Мне кажется, что помеха от БП бежит по шасси. Дело в том, что есть еще и внешняя цепь, куда эта помеха может наводится.

      К МЭК подключен девайс — эквивалент нагрузки (ЭН). Этот ЭН цепляется ко всем четырем кольца МЭК не экранированными проводами. Оно и понятно — матушку Землю мы собираемся измерять, а не экранировать. Внешние (возбуждающие) кольца разнесены друг относительно друга на 700 мм. Поэтому, провода, идущие к ним — это полноценные антенны! Вполне возможно, что помеха наводится на них.

      Мне наверно лучше зафотать это всё…

      Вообще давным давно нас в институте учили, что бороться с помехами нужно не в месте их приема, а в месте их возникновения. Поэтому все мои претензии не к схеме усилителя, АЦП, процессора, а именно к БП. Когда я запускаю МЭК от батареек «Крона», то ведь никаких помех нет и в помине! Когда я смотрю на сигналы, при отключенном ЭН, помех от БП тоже не наблюдаю. Они, конечно, есть, но они ниже заданного уровня.

      Юрий, вопрос к Вам — Вы уверены, что сможете помочь решить мою проблему? Я просто, не знаю какой Ваш опыт. Может и в самом деле я чего-то упускаю из виду.

      • Апнот №70 вам в помощь, Александр. Там у Вильямса есть 2 самодельных зонда для EMI, с их помощью можно тонко исследовать готовую схему и понять, где именно «свистит», в каких цепях. Там же (в апнотах «линеара») полно рекомендаций по топологии источников питания.

        «Я и сам знаю, что нужно «проектировать более тщательнее», но я не знаю как это делать,» – потому я и отправляю вас к апнотам.

        «Вы уверены, что сможете помочь решить мою проблему?» – я пытаюсь подсказать вам путь решения, а не решать за вас проблему в вашем устройстве.

      • Ай! Ну, всё равно спасибо!
        Да, похоже, придется делать подобный EMI Sniffer Probe.

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

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

Логотип WordPress.com

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

Фотография Twitter

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

Фотография Facebook

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

Google+ photo

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

Connecting to %s