← Назад к вопросам
Функция определения пересечения двух интервалов
2.0 Middle🔥 121 комментариев
#Стандарты разработки
Условие
Напишите функцию, которая определяет факт пересечения двух интервалов.
Интервалы могут быть заданы с открытыми и закрытыми границами:
(или)- открытая граница (значение не включено)[или]- закрытая граница (значение включено)
Пример
Вход: интервал1 = (-2; 3), интервал2 = [3; 5] Выход: Ложь (так как 3 не входит в первый интервал)
Вход: интервал1 = [-2; 3], интервал2 = [3; 5] Выход: Истина (так как 3 входит в оба интервала)
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Обзор задачи
Задача требует определить, пересекаются ли два интервала с учётом типов границ (открытые и закрытые). Это важно для обработки числовых диапазонов в 1С, например при работе с расписанием, ценовыми диапазонами или временными окнами.
Математическая основа
Два интервала пересекаются, если:
- Левая граница одного интервала меньше правой границы другого
- Правая граница одного интервала больше левой границы другого
При сравнении нужно учитывать тип границ (открытая/закрытая).
Реализация на 1С
Функция ПересекаютсяИнтервалы(Интервал1, Интервал2)
// Парсим первый интервал
Граница1Лева = Интервал1[0]; // Символ скобки
Значение1Лева = Интервал1[1]; // Число
Значение1Права = Интервал1[2]; // Число
Граница1Права = Интервал1[3]; // Символ скобки
// Парсим второй интервал
Граница2Лева = Интервал2[0];
Значение2Лева = Интервал2[1];
Значение2Права = Интервал2[2];
Граница2Права = Интервал2[3];
// Определяем левую и правую границы общего пересечения
ПересечениеЛева = Макс(Значение1Лева, Значение2Лева);
ПересечениеПрава = Мин(Значение1Права, Значение2Права);
// Если левая граница явно больше правой - нет пересечения
Если ПересечениеЛева > ПересечениеПрава Тогда
Возврат Ложь;
КонецЕсли;
// Если левая граница равна правой - проверяем открытость границ
Если ПересечениеЛева = ПересечениеПрава Тогда
// Определяем открытость границы слева
ОткрытаГраницаСлева = Ложь;
Если ПересечениеЛева = Значение1Лева И (Граница1Лева = "(" ИЛИ Граница1Лева = ")") Тогда
ОткрытаГраницаСлева = Истина;
КонецЕсли;
Если ПересечениеЛева = Значение2Лева И (Граница2Лева = "(" ИЛИ Граница2Лева = ")") Тогда
ОткрытаГраницаСлева = Истина;
КонецЕсли;
// Определяем открытость границы справа
ОткрытаГраницаСправа = Ложь;
Если ПересечениеПрава = Значение1Права И (Граница1Права = ")" ИЛИ Граница1Права = "(") Тогда
ОткрытаГраницаСправа = Истина;
КонецЕсли;
Если ПересечениеПрава = Значение2Права И (Граница2Права = ")" ИЛИ Граница2Права = "(") Тогда
ОткрытаГраницаСправа = Истина;
КонецЕсли;
// Если обе границы открыты - нет пересечения
Если ОткрытаГраницаСлева И ОткрытаГраницаСправа Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
Возврат Истина;
КонецФункции
Улучшенная версия с помощником функцией
Функция ПарсИнтервала(СтрокаИнтервала)
// Извлекаем скобки и числа из строки вида "(-2; 3)" или "[-2; 3]"
СтрокаОчищенная = СтрОкончание(СтрокаИнтервала, 1); // Последняя скобка
ГраницаПрава = СтрОкончание(СтрокаИнтервала, 1);
СтрокаБезПосле = Лево(СтрокаИнтервала, СтрДлина(СтрокаИнтервала) - 1);
ГраницаЛева = Лево(СтрокаБезПосле, 1);
СтрокаЧисел = Середина(СтрокаБезПосле, 2);
// Разбиваем по разделителю ";" или ","
Позиция = Найти(СтрокаЧисел, ";");
Если Позиция = 0 Тогда
Позиция = Найти(СтрокаЧисел, ",");
КонецЕсли;
ЗначениеЛева = Число(Триум(Лево(СтрокаЧисел, Позиция - 1)));
ЗначениеПрава = Число(Триум(Середина(СтрокаЧисел, Позиция + 1)));
Возврат Новый Структура(
"ГраницаЛева, ЗначениеЛева, ЗначениеПрава, ГраницаПрава",
ГраницаЛева, ЗначениеЛева, ЗначениеПрава, ГраницаПрава);
КонецФункции
Функция ПересекаютсяИнтервалыУлучшенная(Интервал1, Интервал2)
Инт1 = ПарсИнтервала(Интервал1);
Инт2 = ПарсИнтервала(Интервал2);
ЛеваяТочка = Макс(Инт1.ЗначениеЛева, Инт2.ЗначениеЛева);
ПраваяТочка = Мин(Инт1.ЗначениеПрава, Инт2.ЗначениеПрава);
Если ЛеваяТочка > ПраваяТочка Тогда
Возврат Ложь;
КонецЕсли;
Если ЛеваяТочка = ПраваяТочка Тогда
// Проверяем открытость
КоличествоОткрытых = 0;
Если ЛеваяТочка = Инт1.ЗначениеЛева И Инт1.ГраницаЛева = "(" Тогда
КоличествоОткрытых = КоличествоОткрытых + 1;
КонецЕсли;
Если ЛеваяТочка = Инт2.ЗначениеЛева И Инт2.ГраницаЛева = "(" Тогда
КоличествоОткрытых = КоличествоОткрытых + 1;
КонецЕсли;
Если ПраваяТочка = Инт1.ЗначениеПрава И Инт1.ГраницаПрава = ")" Тогда
КоличествоОткрытых = КоличествоОткрытых + 1;
КонецЕсли;
Если ПраваяТочка = Инт2.ЗначениеПрава И Инт2.ГраницаПрава = ")" Тогда
КоличествоОткрытых = КоличествоОткрытых + 1;
КонецЕсли;
Возврат КоличествоОткрытых < 2;
КонецЕсли;
Возврат Истина;
КонецФункции
Примеры использования
// Пример 1: (-2; 3) и [3; 5] - не пересекаются
Результат1 = ПересекаютсяИнтервалыУлучшенная("(-2; 3)", "[3; 5]"); // Ложь
// Пример 2: [-2; 3] и [3; 5] - пересекаются в точке 3
Результат2 = ПересекаютсяИнтервалыУлучшенная("[-2; 3]", "[3; 5]"); // Истина
// Пример 3: [1; 5] и [3; 7] - пересекаются в интервале [3; 5]
Результат3 = ПересекаютсяИнтервалыУлучшенная("[1; 5]", "[3; 7]"); // Истина
Ключевые моменты
- Открытая граница — значение не входит в интервал
- Закрытая граница — значение входит в интервал
- Граничные точки — требуют особой проверки типов границ
- Парсинг — критически важен для корректной работы функции