Инженерный тур. 2 этап
Задачи, представленные во втором отборочном этапе, разделены на два блока: индивидуальные и командные.
Они охватывают такие темы, как электротехника, закон Ома, RC-фильтр, электроника, цифро-аналоговый преобразователь, сдвиговый регистр, аналоговый сигнал, линейная интерполяция, спектр, преобразование Фурье, TCP-соединение. Задачи оцениваются разным количеством баллов в зависимости от сложности.
Индивидуальные задачи второго этапа инженерного тура открыты для решения. Соревнование доступно на платформе Яндекс.Контест: https://contest.yandex.ru/contest/69908/enter/.
Выпрямительные схемы применяют для преобразования переменного напряжения в постоянное. Для оценки качества выпрямления напряжения используют различные метрики, характеризующие пульсацию выходного выпрямленного сигнала. Одной из таких метрик является коэффициент пульсации.
Оценка характеристик выходного выпрямленного напряжения проводится посредством микроконтроллера, который с помощью АЦП производит снятие сигнала напряжения на выходе выпрямительной схемы.
Примечательно, что АЦП может работать в разных режимах разрядности и иметь различное опорное напряжение.
Учитывая вышесказанное, разработайте программу для расчета коэффициента пульсации напряжения по данным, полученным с АЦП микроконтроллера.
Формат входных данных
На вход программы первой строкой подается число \(V\), обозначающее опорное напряжение АЦП (максимальное напряжение относительно потенциала заземления, для которого может быть проведено измерение напряжения).
Вторая строка содержит целое число \(B\), обозначающее разрядность АЦП, с помощью которого был принят цифровой сигнал.
Третья строка содержит целое число \(N\) — количество последующих построчно записанных значений, полученных с АЦП.
Далее следует \(N\) строк, содержащих значения АЦП.
Формат выходных данных
На выходе ожидается вещественное число (процент), округленное до двух знаков после запятой по правилам арифметического округления, обозначающее коэффициент пульсации.
Тестовые данные
| Номер теста | Стандартный ввод | Стандартный вывод |
|---|---|---|
1 |
3.3 8 10 127 177 208 208 177 127 77 46 46 77 |
63.78 |
Примечание
Использование внешних библиотек для решения задачи запрещено.
Ниже представлено решение на языке Python.
def coef(V, B, signal):
minVal = -1
maxVal = -1
meanVal = -1
voltageVals = []
for i in signal:
if type(i) == int:
voltageVals.append(float(V * i / (2**B-1)))
minVal = min(voltageVals)
maxVal = max(voltageVals)
meanVal = sum(voltageVals)/len(voltageVals)
k = (maxVal - minVal) / (2 * meanVal) * 100
return round(k, 2)
def main():
signal = []
V = float(input())
B = int(input())
N = int(input())
for item in range(N):
signal.append(int(input()))
print(str(coef(V, B, signal)))
main()
Архив с тестовыми данными, условием и авторским решением доступен по ссылке: https://disk.yandex.ru/d/_lMq-bNmyI8Avg/task1_1.zip.
ЦАП (цифро-аналоговый преобразователь) — это устройство, которое преобразует цифровые сигналы в аналоговые. ЦАП используется во многих аудио- и видеоустройствах, чтобы трансформировать информацию из цифрового формата (например, из MP3-файла) в аналоговый, который может быть воспроизведен через динамики или другие аналоговые устройства вывода звука.
Зачастую микроконтроллеры не обладают встроенными цифро-аналоговыми преобразователями. Однако существуют внешние ЦАП. Один из видов ЦАП построен на основе R-2R матрицы.
Параллельная архитектура такого устройства обеспечивает его высокое быстродействие.
Однако чем выше разрядность ЦАП, тем большее количество ключевых входов задействовано для его работы, что зачастую делает невозможным его использование в непосредственной связи с микроконтроллером.
Одним из способов сокращения задействованных выводов микроконтроллера, выполняющих функции электрических ключей, является применение сдвиговых регистров.
Сдвиговый регистр — это цифровая схема для хранения и передачи данных.
Основная функция сдвигового регистра состоит в том, чтобы «сдвигать» двоичные данные влево или вправо, то есть перемещать значения в ячейках памяти на одну позицию. Это позволяет выполнять различные операции, такие как сдвиги, умножение или деление на 2, а также осуществлять последовательную и параллельную передачу данных.
Сдвиговые регистры могут быть реализованы с использованием триггеров (например, триггеров типа D). Существуют два типа этих устройств:
- сдвиговые регистры, сдвигающие данные влево (
left shift registers) — данные сдвигаются влево, а в свободный правый бит (младший бит) может быть записано новое значение; - сдвиговые регистры, сдвигающие данные вправо (
right shift registers) — данные перемещаются вправо, а в свободный левый бит (старший бит) можно ввести новое значение.
В технике используются специальные термины, обозначающие очередность передачи данных: LSB-first и MSB-first. Они описывают порядок, в котором биты сохраняются или передаются в цифровых системах. Это имеет значение при интерпретации данных:
- В формате
LSB-firstмладший значимый бит (LSB) передается или записывается первым. Это означает, что наименее значимый бит находится в первом (левом) положении, и с каждым следующим передаваемым битом идет следующее значение. Например, для двоичного числа 1101 порядок передачи будет выглядеть так: \(1 \text{ (LSB)} \rightarrow 0 \rightarrow 1 \rightarrow 1\) (MSB). - В формате
MSB-firstстарший значимый бит (MSB) передается или записывается первым. Таким образом, более значимый бит находится в первом (левом) положении, и последовательно идут биты меньшей ценности. Например, для двоичного числа 1101 порядок передачи будет выглядеть так: \(1 \text{ (MSB)} \rightarrow 1 \rightarrow 0 \rightarrow 1\) (LSB)
Необходимо разработать программу, рассчитывающую выходное напряжение на ЦАП вида R-2R, подключенного к восьмибитному сдвиговому регистру, сдвиг которого осуществляется влево. Биты подаются в режиме MSB-first.
Формат входных данных
На вход программы подается список, содержащий два элемента.
Первой строкой подается число \(A\), означающее опорное напряжение.
Вторая строка содержит число \(B\) (\(N\)-битное в десятичной системе исчисления), характеризующее состояние электронных ключей.
Число \(N\) — произвольное.
Формат выходных данных
На выходе программы ожидается вещественное число, округленное до сотых по правилам арифметического округления, которое отражает напряжение на выходе ЦАП при данной конфигурации электронных ключей.
Тестовые данные
| Номер теста | Стандартный ввод | Стандартный вывод |
|---|---|---|
1 |
3.3 246 |
3.17 |
2 |
7 226 |
6.18 |
Примечания
Использование внешних библиотек для решения задачи запрещено. В случае, если на вход подано число, превышающее восьмибитную размерность, следует учесть только те биты, которые останутся в регистре, после того как число будет прочитано и передано полностью согласно условию задачи: порядку передачи данных и направлению сдвига.
Ниже представлено решение на языке Python.
def DAC(voltage, number):
dacStr = list(str(bin(number)).replace("0b",""))
while len(dacStr) < 8:
dacStr.insert(0,'0')
while len(dacStr) > 8:
dacStr.pop(0)
count = 1
vOut = 0
for i in dacStr:
vOut += voltage * int(i) / 2**(count)
count+=1
return round(vOut, 2)
def main():
V = float(input())
B = int(input())
print(str(DAC(V, B)))
main()
Архив с тестовыми данными, условием и авторским решением доступен по ссылке: https://disk.yandex.ru/d/_lMq-bNmyI8Avg/task1_2.zip.
Для корректного измерения синусоидального сигнала, поступающего с датчика на АЦП микроконтроллера, необходимо избавиться от высокочастотных шумов, которые могут искажать результаты измерений.
С этой целью в цепь добавляется RC-фильтр нижних частот, который пропускает только низкочастотные компоненты сигнала, устраняя нежелательные высокочастотные помехи.
Задача — написать программу, высчитывающую действующее значение напряжения после прохождения RC-фильтра.
Номиналы элементов в фильтре: \(R = 100\) Ом, \(C = 4{,}7\) мкФ.
Формат входных данных
На вход программы подаются две строки данных.
Первой строкой подается число \(f\), означающее частоту сигнала.
Вторая строка содержит список, содержащий значения сигнала за период времени.
Формат выходных данных
На выходе программы ожидается число, характеризующее действующее значение синусоидального сигнала, полученного на выходе RC-фильтра.
Тестовые данные
| Номер теста | Стандартный ввод | Стандартный вывод |
|---|---|---|
1 |
100 0 14 20 14 0 -14 -20 -14 |
13.56 |
Примечания
Использование внешних библиотек для решения задачи запрещено.
Действующее значение напряжения высчитывается по следующей формуле \[U_d = \frac{U_{max}}{\sqrt{2}},\]где \(U_{max}\) — максимальное напряжение за период.
Данный сигнал содержит только переменную составляющую.
Ответ округлите до двух знаков после запятой.
Ниже представлено решение на языке Python.
import math
def find_VOut(voltage,freq):
voltage_max = max(voltage)
voltage_min = min(voltage)
R = 100
C = 4.7*10**(-6)
Xc = 1 / (2*3.1416*freq*C)
Impedance = math.sqrt(R**2 + Xc**2)
voltage_out = ((voltage_max + voltage_min)/2 + voltage_max)*Xc/Impedance
print(round((voltage_out/math.sqrt(2)),2))
def main():
freq = int(input())
voltage= list(input().split(" "))
voltage = [ int(x) for x in voltage ]
find_VOut(voltage,freq)
main()
Архив с тестовыми данными, условием и авторским решением доступен по ссылке: https://disk.yandex.ru/d/_lMq-bNmyI8Avg/task1_3.zip.
Для измерения температуры с помощью микроконтроллера в качестве датчика температуры используют термопару.
Термопара — это устройство, используемое для измерения температуры, основанное на термоэлектрическом эффекте. Она состоит из двух проводников, сделанных из различных металлов, которые соединены на одном конце.
При изменении температуры возникает электродвижущая сила (ЭДС), которая пропорциональна разнице температур между спаями.
Задача — разработать программу, определяющую показание АЦП по данным аналогового датчика температуры.
Формат входных данных
На вход программы первой строкой подается число \(N\), обозначающее мощность словаря.
Вторая строка содержит число \(V\) — опорное напряжение АЦП.
Третьей строкой идет число \(M\), означающее разрядность АЦП микроконтроллера, которым считываются показания с датчика.
Четвертая строка — число \(T\), обозначающее показание температуры.
Далее идет \(N\) строк, содержащих показания температуры и показания выходного напряжения с датчика температуры, разделенных пробелом.
Формат выходных данных
На выходе программы ожидается значение АЦП, соответствующего показанию температуры и разрядности АЦП. Учтите, что показание АЦП может быть только целым.
В случае возникновения дробного расчетного значения АЦП в ответ должна попасть только целая часть полученного числа.
Тестовые данные
| Номер теста | Стандартный ввод | Стандартный вывод |
|---|---|---|
1 |
11 10 12 5.0 -5.0 7.0 -3.0 7.1 -1.0 7.2 1.0 7.3 3.0 7.4 5.0 7.5 7.0 7.6 9.0 7.7 11.0 7.8 13.0 7.9 15.0 8.0 |
3071 |
Примечания
Использование внешних библиотек для решения задачи запрещено. Датчик имеет линейную зависимость напряжения от температуры. Если значения температуры нет среди поданных на вход значений, воспользуйтесь линейной интерполяцией.
Ниже представлено решение на языке Python.
def ADC(Vop, bit, temperature, tempDict):
x = []
templist = list(tempDict.keys())
for prev, curr, nxt in zip(templist, templist[1:], templist[2:]):
if prev <= x <= nxt:
x = [prev, nxt]
y = [tempDict[x[0]], tempDict[x[1]]]
k = (y[0] - y[1]) / (x[0] - x[1])
b = y[0] - k * x[0]
Vout = k * temperature + b
ADC_val = int((2**bit - 1) * Vout / Vop)
return ADC_val
def main():
N = int(input())
Vop = float(input())
B = int(input())
cur_temp = float(input())
tempDict = {}
for j in range(N):
strList = input().strip().split(' ')
tempDict[float(strList[0])] = float(strList[1])
print(ADC(Vop, B, cur_temp, tempDict))
main()
Архив с тестовыми данными, условием и авторским решением доступен по ссылке: https://disk.yandex.ru/d/_lMq-bNmyI8Avg/task1_4.zip.
Командные задачи второго этапа инженерного тура открыты для решения. Соревнование доступно на платформе Яндекс.Контест: https://contest.yandex.ru/contest/69931/enter/.
В своей жизни мы часто сталкиваемся с аналоговыми сигналами: звуком, давлением, температурой и др. Для того чтобы использовать внешние воздействия окружающей среды различной природы (механической, термической, световой и пр.) в применениях электронных устройств, необходимо преобразовать это внешнее воздействие в электрический сигнал: напряжение или ток. Для этого применяют соответствующие датчики (или сенсоры), которые и выполняют такое преобразование.
Обычно для упрощения представления о природе сигналов любой сложный аналоговый сигнал (необязательно периодический) можно представить в виде суммы гармоник (синусоидальных волн), каждая из которых обладает своей частотой, амплитудой и фазовым сдвигом.
Чтобы определить количество таких гармоник и их параметры, применяют преобразование Фурье — операцию, сопоставляющую одной функции вещественной переменной другую (вообще говоря, комплекснозначную) функцию вещественной переменной. Эта новая функция описывает коэффициенты («амплитуды») при разложении исходной функции на элементарные составляющие — гармонические колебания с разными частотами.
После дискретизации и квантования исходный сложный аналоговый сигнал будет представлен как смесь цифровых сигналов, являющейся алгебраической суммой исходных цифровых сигналов, полученных от разных источников.
Задача — разработать программу, которая, благодаря прямому дискретному преобразованию Фурье, вычисляет амплитудный спектр смеси входных цифровых сигналов, полученных с заданной частотой дискретизации.
Однако в командном задании есть еще одна задача. Для того чтобы получить максимальный балл, нужно вывести программой значение токена. Для получения токена необходимо написать внешнюю программу, задача которой — выполнить TCP-подключение по адресу: "80.243.1.26:58080" и получить токен. В процессе соединения на сервер должен быть передан ID пользователя платформы Talent-ID. Для выполнения задания необходимо указать токен, соответствующий Talent-ID любого участника команды.
Формат входных данных
Первой строкой программа должна получить число \(F_s\), обозначающее частоту дискретизации.
Вторая строка содержит в себе число \(N\) — это длина массива значений сигнала.
С третьей по пятую строки представлены данные трех сигналов, каждый из них содержит в себе \(N\) значений сигнала.
Формат выходных данных
На выходе программы необходимо вывести частоты и значения амплитудного спектра для каждой частоты от \(0\) до \((F_s-1)\), разделенные пробелом. Записи необходимо выводить построчно.
Последней строкой ожидается токен команды.
Тестовые данные
| Номер теста | Стандартный ввод | Стандартный вывод |
|---|---|---|
1 |
12 12 64.0 80.0 91.713 96.0 91.713 80.0 64.0 48.0 36.287 32.0 36.287 48.0 0.0 22.928 -6.928 -16.0 6.928 9.072 0.0 -9.072 -6.928 16.0 6.928 -22.928 0 0 0 0 0 0 0 0 0 0 0 0 |
0 768 1 192 2 0 3 96 4 48 5 0 6 0 7 0 8 48 9 96 10 0 11 192 X$CzhM&C54J&C#58 |
Примечания
Использование внешних библиотек запрещено. Каждое значение амплитудного спектра должно быть округлено до целого числа по правилам арифметического округления.
Ниже представлено решение на языке Python.
import cmath
import socket
def spectra(X):
spectra_sum_n = [0.0 + 0j for it in range(len(X))]
spectra_sum_k = [0.0 + 0j for it in range(len(X))]
for k in range(len(spectra_sum_k)):
for n in range(len(spectra_sum_n)):
spectra_sum_n[n] = X[n] * cmath.exp(-2*cmath.pi * k * n * 1j / len(X))
spectra_sum_k[k] = sum(spectra_sum_n)
return spectra_sum_k
def request_token(server_ip='82.179.190.60', server_port=9090):
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client_socket.connect((server_ip, server_port))
print("Connected to the server.")
token = client_socket.recv(1024).decode()
except Exception as e:
pass
finally:
client_socket.close()
return str(token)
def main():
Fs = int(input())
L = int(input())
X1 = [float(i) for i in input().strip().split(' ')]
X2 = [float(i) for i in input().strip().split(' ')]
X3 = [float(i) for i in input().strip().split(' ')]
X = [i + j + k for i, j, k in zip(X1, X2, X3)]
Y = [round(abs(it)) for it in spectra(X)]
X_axis = [int(Fs / (len(X)) * it) for it in range(len(X))]
spectra_dict = dict.fromkeys(X_axis)
for it in range(len(spectra_dict)):
spectra_dict[X_axis[it]] = Y[it]
print(request_token())
for freq in spectra_dict:
print(str(int(freq)) + ' ' + str(int(spectra_dict[freq])))
main()
Архив с тестовыми данными, условием и авторским решением доступен по ссылке: https://disk.yandex.ru/d/_lMq-bNmyI8Avg/task2.zip.


