Перейти к контенту
← Назад

Проектный тур

Примеры задач

Внимание! Данные примеры заданий в явном виде НЕ встретятся на заключительном этапе ВсОШ по информатике в направлении Робототехника.
Мы публикуем их для тренировки навыков, и проверки работоспособности Вашего устройства, собранного согласно требованиям Единого технического задания (далее ЕТЗ) опубликованного на сайте Текст ЕТЗ (09.02.2026)

Задача 1

На листе ответов нарисован прямоугольник 5 х 7 см. Задача – закрасить геометрическое место точек, которые находятся на расстоянии 10 мм от ближайшей точки, принадлежащей изначально нарисованной фигуре.

Задача 2

На лист ответов наклеивается прямоугольник из алюминиевой фольги (параллельно краям листа) размером 5х5 см. Можно использовать подпружиненные скользящие контакты либо индукционный щуп (датчик на принципе изменения параметров высокочастотного магнитного поля при приближении металлического объекта). Датчик встроен в маркер, выданный для данного задания. Задача — обвести прямоугольник на расстоянии 10 мм от области, детектируемой датчиком (датчик дает либо 1 либо 0).

Задача 3

Внешний контроллер (на заключительном этапе его выдают организаторы), с соответствующими логическим уровням ЕТЗ сигналами (в примере дан код для arduino с делителем напряжения на выходном пине), генерирует Морзе сигнал из пяти цифр, прерываясь на 5 секунд между повторениями. Задача посчитать остаток от деления суммы переданных цифр на 10. Ответом считается закрашенный чекбокс в соответствующей клетке таблицы на листе ответов.

Код к заданию

// Copyright (c) 2026 ЦПМК по информатике
// Licensed under the MIT License.
// https://robot.mipt.ru/

/*
Согласно стандарту международного союза электросвязи (ITU)
длительность точки является базовой единицей измерения времени в азбуке Морзе.
Интервал между сигналами и их продолжительность:
Тире равно трем точкам.
Интервал между сигналами, образующими одну букву, равен одной точке.
Интервал между двумя буквами равен трем точкам.
Интервал между двумя словами равен семи точкам. 
http://itu.int/rec/R-REC-M.1677-1-200910-I/
*/

const int outPin = 13;  // пин для вывода сигнала
const int dotDuration = 200; // длительность точки в мс

// Массив кодов Морзе для цифр от 0 до 9
const char* morseNumbers[] = {
  "-----",  // 0
  ".----",  // 1
  "..---",  // 2
  "...--",  // 3
  "....-",  // 4
  ".....",  // 5
  "-....",  // 6
  "--...",  // 7
  "---..",  // 8
  "----."   // 9
};

void setup() {
  pinMode(outPin, OUTPUT);
}

void loop() {
  // Пример: передаем число 22 3 26
  sendNumber(22326);

  delay(5000);  // Ждем 5 секунд перед повтором
}


// Рекурсивная функция: выводит цифры по порядку
void sendNumber(unsigned long n) {
  // Сначала обрабатываем "голову" числа
  if (n >= 10) {
    sendNumber(n / 10);
  }

  // Передаем последний символ как индекс массива
  sendMorseSymbol(morseNumbers[n % 10]);

  // Пауза между цифрами
  delay(dotDuration * 3);
}

// Функция для проигрывания конкретной последовательности точек и тире
void sendMorseSymbol(const char* sequence) {
  for (int i = 0; sequence[i] != '\0'; i++) {
    if (sequence[i] == '.') {
      dot();
    } else if (sequence[i] == '-') {
      dash();
    }
  }
}

void dot() {
  digitalWrite(outPin, HIGH);
  delay(dotDuration);
  digitalWrite(outPin, LOW);
  delay(dotDuration);
}

void dash() {
  digitalWrite(outPin, HIGH);
  delay(dotDuration * 3);
  digitalWrite(outPin, LOW);
  delay(dotDuration);
}

Чекбокс считается закрашенным, если в нем присутствует символ Х, O, V, + или иной другой, размером 6х6 мм (измеренный размер символа в пределах рамки составляет от 3 до 9 мм, при размере рамки чекбокса 10х10 мм.

Задача 4

На сетке 3х3 дан “японский кроссворд” — это логическая головоломка в которой с помощью чисел зашифровано черно-белое изображение. Задача — восстановить картинку (отметить клетки, решающие кроссворд). Рядом с клетками расположены коды, обозначающие количество закрашенных ячеек в соответствующих им строках и столбцах.

Чекбокс считается закрашенным, если в нем присутствует символ Х, O, V, + или иной другой, размером 6х6 мм (измеренный размер символа в пределах рамки составляет от 3 до 9 мм, при размере рамки чекбокса 10х10 мм.

Задача 5

Дан лист, размеченный в координатах XY в пределах +8 до -8 (одна единица соответствует сантиметру). По протоколу UART устройство, выданное организаторами, ожидает пакет: 0xAA 0xBB (заголовок), 4 байта float, 1 байт CRC. В ответ устройство отправляет: 0xFF (заголовок), 0xYY (длина данных), ни одного, один два float и 1 байт CRC. ответ это значения Y для уравнения (x-X0)^2 +(y-Y0)^2 = R^2

  1. Необходимо нарисовать на листе ответов не менее 5 отрезков параллельных оси Х, с началом и концом в координатах переданных устройством.
  2. Необходимо нарисовать окружность, соответствующую изначальному уравнению (параметры необходимо вычислить из чисел, переданных устройством)

Устройство использует порядок Little-endian (младший байт идет первым). Убедитесь, что Ваше устройство (например, скрипт на Python) использует тот же порядок. В устройстве реализован простейший алгоритм CRC-8 на базе операции XOR (исключающее ИЛИ). Механика работы: Алгоритм работает по принципу побайтового суммирования без переноса: Инициализируется переменная crc со значением 0x00. Каждый последующий байт данных «смешивается» с текущим значением crc с помощью логической операции XOR (^). Результат итоговой операции после прохождения всего массива данных и является контрольной суммой.

Код к заданию

// Copyright (c) 2026 ЦПМК по информатике
// Licensed under the MIT License.
// https://robot.mipt.ru/

unsigned long lastByteTime = 0;   // Время получения последнего байта
const unsigned long TIMEOUT = 50; // Таймаут в мс (настрой под свою скорость UART)


// Параметры окружности из вашего уравнения: (x-X0)^2 + (y+Y0)^2 = R^2
const float X0 = 2.0;
const float Y0 = -2.0;
const float R = 5.0;

// Структура для конвертации 4 байт в float
union FloatConverter {
  float f;
  uint8_t b[4];
};

// Функция расчета CRC8 (простое XOR)
uint8_t getCRC8(uint8_t *data, uint8_t len) {
  uint8_t crc = 0x00;
  for (uint8_t i = 0; i < len; i++) {
    crc ^= data[i];
  }
  return crc;
}

void setup() {
  Serial.begin(9600);  // Настройка UART
}

void loop() {
  // Очистка буфера, если данные устарели или недопринятый пакет
  if (Serial.available() > 0 && (millis() - lastByteTime > TIMEOUT)) {
    while(Serial.available()) Serial.read(); 
  }


  // Ждем пакет: заголовок (2) + float (4) + CRC (1) = 7 байт
  if (Serial.available() >= 7) {
    if (Serial.read() == 0xAA) {    // Первый байт заголовка
      if (Serial.read() == 0xBB) {  // Второй байт заголовка

        FloatConverter xVal;
        for (int i = 0; i < 4; i++) {
          xVal.b[i] = Serial.read();
        }

        uint8_t receivedCRC = Serial.read();

        // Проверяем CRC входящих данных (только float части)
        if (getCRC8(xVal.b, 4) == receivedCRC) {

          float dx = xVal.f - X0;
          float discriminant = (R * R) - (dx * dx);

          FloatConverter y1, y2;
          uint8_t dataLength = 0;

          // Логика решения
          if (discriminant < 0) {
            // Точек нет
            dataLength = 0;
          } else if (discriminant == 0) {
            // Одна точка
            y1.f = Y0;
            dataLength = 4;
          } else {
            // Две точки
            float sqrtD = sqrt(discriminant);
            y1.f = Y0 + sqrtD;
            y2.f = Y0 - sqrtD;
            dataLength = 8;
          }

          // Формируем ответ
          sendResponse(y1, y2, dataLength);
        }
      }
    }
  }
}

void sendResponse(FloatConverter v1, FloatConverter v2, uint8_t len) {
  uint8_t buffer[8];
  if (len >= 4) memcpy(buffer, v1.b, 4);
  if (len == 8) memcpy(buffer + 4, v2.b, 4);

  uint8_t sendCRC = getCRC8(buffer, len);

  Serial.write(0xFF);  // Заголовок ответа
  Serial.write(len);   // Длина данных (0, 4 или 8)
  if (len > 0) {
    Serial.write(buffer, len);
  }
  Serial.write(sendCRC);  // CRC
}