arefaste/1C_Forums huggingface dataset:
Распределение товаров по ячейкам в запросе
Теги: 1С,Минимализмы,Задачи

"Распределение в запросе" или "избавляемся от перебора"

# Код реализации

```1c
ВЫБРАТЬ
    Ячейки.Ячейка,
    СУММА(Слева.Количество) - МИНИМУМ(Ячейки.Количество) КАК КоличествоОт,
    СУММА(Слева.Количество) КАК КоличествоДо
ПОМЕСТИТЬ ЛинейкаЯчеек
ИЗ
    Ячейки КАК Ячейки
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Ячейки КАК Слева
        ПО (Слева.Ячейка <= Ячейки.Ячейка)

СГРУППИРОВАТЬ ПО
    Ячейки.Ячейка
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Товары.Товар,
    СУММА(Слева.Количество) - МИНИМУМ(Товары.Количество) КАК КоличествоОт,
    СУММА(Слева.Количество) КАК КоличествоДо
ПОМЕСТИТЬ ЛинейкаТоваров
ИЗ
    Товары КАК Товары
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Товары КАК Слева
        ПО (Слева.Товар <= Товары.Товар)

СГРУППИРОВАТЬ ПО
    Товары.Товар
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Ячейки.Ячейка КАК Ячейка,
    Товары.Товар КАК Товар,
    ВЫБОР
        КОГДА Товары.КоличествоДо < Ячейки.КоличествоДо
            ТОГДА Товары.КоличествоДо
        ИНАЧЕ Ячейки.КоличествоДо
    КОНЕЦ - ВЫБОР
        КОГДА Товары.КоличествоОт > Ячейки.КоличествоОт
            ТОГДА Товары.КоличествоОт
        ИНАЧЕ Ячейки.КоличествоОт
    КОНЕЦ КАК Количество
ИЗ
    ЛинейкаЯчеек КАК Ячейки
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЛинейкаТоваров КАК Товары
        ПО Ячейки.КоличествоОт < Товары.КоличествоДо
            И Ячейки.КоличествоДо > Товары.КоличествоОт
```
Объединение пересекающихся периодов в запросе
Теги: 1С,Минимализмы,Задачи

Требуется объединить перекрывающиеся периоды.

Например, шесть периодов
01.01.16 - 10.03.16;  01.02.16 - 20.03.16; 30.03.16 - 15.04.16; 10.04.16 - 12.04.16; 11.04.16 - 25.04.16; 30.04-16 - 10.05.16

должны объединиться в три
01.01.16 - 20.03.16; 30.03.16 - 25.04.16; 30.04-16 - 10.05.16

# Код реализации

```1c
ВЫБРАТЬ РАЗЛИЧНЫЕ
    Край.От
ПОМЕСТИТЬ ЛевыеКрая
ИЗ
    Интервалы КАК Край
        ЛЕВОЕ СОЕДИНЕНИЕ Интервалы КАК Интервалы
        ПО (Интервалы.От < Край.От)
            И Край.От <= Интервалы.До
ГДЕ
    Интервалы.От ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ РАЗЛИЧНЫЕ
    Край.До
ПОМЕСТИТЬ ПравыеКрая
ИЗ
    Интервалы КАК Край
        ЛЕВОЕ СОЕДИНЕНИЕ Интервалы КАК Интервалы
        ПО (Интервалы.От <= Край.До)
            И Край.До < Интервалы.До
ГДЕ
    Интервалы.От ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
    ЛевыеКрая.От,
    МИНИМУМ(ПравыеКрая.До) КАК До
ИЗ
    ЛевыеКрая КАК ЛевыеКрая
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПравыеКрая КАК ПравыеКрая
        ПО ЛевыеКрая.От <= ПравыеКрая.До

СГРУППИРОВАТЬ ПО
    ЛевыеКрая.От
```
Выделение разрядов числа без использования округления и деления по модулю
Теги: 1С,Минимализмы,Задачи

Первый параметр функции - число из максимум пяти разрядов цифр "0" и "1", второй параметр - номер разряда.
Функция, возвращающая значение разряда:

# Код реализации

```1c
Функция Ф(Х, У)
    Возврат ?(У < 2, 0 + (Х > 9999), Ф((Х - 10000 * (Х > 9999)) * 10, У - 1))
КонецФункции
```
Посчитать запросом суммарную длительность различных состояний
Теги: 1С,Минимализмы,Задачи

# Код реализации

```1c
ВЫБРАТЬ
    &Дата1 КАК Период,
    НаНачало.Скважина,
    НаНачало.Состояние
ПОМЕСТИТЬ Дано
ИЗ
    РегистрСведений.Резерв.СрезПоследних(&Дата1, ) КАК НаНачало

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Резерв.Период,
    Резерв.Скважина,
    Резерв.Состояние
ИЗ
    РегистрСведений.Резерв КАК Резерв
ГДЕ
    Резерв.Период МЕЖДУ &Дата1 И &Дата2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    &Дата2,
    НаКонец.Скважина,
    НаКонец.Состояние
ИЗ
    РегистрСведений.Резерв.СрезПоследних(&Дата2, ) КАК НаКонец
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Раньше.Период,
    Раньше.Скважина,
    Раньше.Состояние,
    РАЗНОСТЬДАТ(Раньше.Период, МИНИМУМ(Позже.Период), СЕКУНДА) КАК Длительность
ПОМЕСТИТЬ Интервалы
ИЗ
    Дано КАК Раньше
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Дано КАК Позже
        ПО Раньше.Скважина = Позже.Скважина
            И Раньше.Период < Позже.Период

СГРУППИРОВАТЬ ПО
    Раньше.Период,
    Раньше.Скважина,
    Раньше.Состояние
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Интервалы.Скважина,
    Интервалы.Состояние,
    СУММА(Интервалы.Длительность) КАК Длительность
ИЗ
    Интервалы КАК Интервалы

СГРУППИРОВАТЬ ПО
    Интервалы.Скважина,
    Интервалы.Состояние
```
Разбиение произвольного периода на интервалы в запросе
Теги: 1С,Минимализмы,Задачи

# Код реализации

```1c
ВЫБРАТЬ
    0 КАК Х
ПОМЕСТИТЬ Бит
ОБЪЕДИНИТЬ
ВЫБРАТЬ
    1
;
ВЫБРАТЬ
    Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * Б5.Х)))) КАК Х
ПОМЕСТИТЬ Периоды
ИЗ
    Бит КАК Б0,
    Бит КАК Б1,
    Бит КАК Б2,
    Бит КАК Б3,
    Бит КАК Б4,
    Бит КАК Б5
ГДЕ
    Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * Б5.Х)))) < РАЗНОСТЬДАТ(&Дата1, &Дата2, МЕСЯЦ)
;
ВЫБРАТЬ
    ЕСТЬNULL(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, МЕСЯЦ, Начала.Х + 1), МЕСЯЦ), &Дата1) КАК ДатаНачала,
    ЕСТЬNULL(КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, МЕСЯЦ, Окончания.Х), МЕСЯЦ), &Дата2) КАК ДатаОкончания
ИЗ
    Периоды КАК Начала
        ПОЛНОЕ СОЕДИНЕНИЕ Периоды КАК Окончания
        ПО (Начала.Х + 1 = Окончания.Х)
```

# Примечания

- Спасибо тебе, добрый человек
Поиск свободного штрихкода (EAN-13) внутри одного префикса
Теги: 1С,Штрихкод,Минимализмы,EAN-13

Решение основано на непосредственном получении следующего кода. Без необходимости перевода в числовой тип. 
В штрих-коде ищется последняя серия девяток. Она заменяется на серию нулей. Предшествующая цифра заменяется следующей в ряду цифр. Начало сохраняется. То есть решается задача инкрементирования числа непосредственно в символьном виде:

# Код реализации

```1c
ВЫБРАТЬ 0 КАК Х ПОМЕСТИТЬ Р1 ОБЪЕДИНИТЬ ВЫБРАТЬ 1
;
ВЫБРАТЬ А.Х + 2 * Б.Х КАК Х ПОМЕСТИТЬ Р2 ИЗ Р1 КАК А, Р1 КАК Б
;
ВЫБРАТЬ А.Х + 4 * Б.Х КАК Х ПОМЕСТИТЬ Р4 ИЗ Р2 КАК А, Р2 КАК Б
;
ВЫБРАТЬ ВЫРАЗИТЬ(ПОДСТРОКА(ШтрихКод, 1, А.Х - 1) КАК СТРОКА(12))
+ ПОДСТРОКА("123456789", Б.Х + 1, 1)
+ ПОДСТРОКА("000000000000", А.Х + 1, 12) КАК ШтрихКод
ПОМЕСТИТЬ ДаноПлюс
ИЗ РегистрСведений_ШтрихкодыНоменклатуры, Р4 КАК А, Р4 КАК Б
ГДЕ ШтрихКод ПОДОБНО ПОДСТРОКА("%999999999999", 1, 13 - А.Х)
И ШтрихКод НЕ ПОДОБНО ПОДСТРОКА("%999999999999", 1, 14 - А.Х)
И Б.Х < 9 И ПОДСТРОКА(ШтрихКод, А.Х, 1) = ПОДСТРОКА("012345678", Б.Х + 1, 1)
;
ВЫБРАТЬ ШтрихКод
ИЗ ДаноПлюс
ГДЕ ШтрихКод НЕ В
(ВЫБРАТЬ Дано.ШтрихКод ИЗ РегистрСведений_ШтрихкодыНоменклатуры КАК Дано)
```
Выбор записи по номеру из НЕПРОНУМЕРОВАННОЙ таблицы
Теги: 1С,Минимализмы,Задачи

Расчёт медианы числовых рядов запросом

# Код реализации

```1c
ВЫБРАТЬ
    0 КАК Х
ПОМЕСТИТЬ Бит

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    1
;
ВЫБРАТЬ
    NULL КАК Х
ПОМЕСТИТЬ Сдвиг
ИЗ
    Бит КАК Б0,
    Бит КАК Б1,
    Бит КАК Б2,
    Бит КАК Б3,
    Бит КАК Б4,
    Бит КАК Б5,
    Бит КАК Б6,
    Бит КАК Б7
ГДЕ
    Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * (Б5.Х + 2 * (Б6.Х + 2 * Б7.Х)))))) < 256 - &Номер
;
ВЫБРАТЬ
    Дано.Х КАК Х
ПОМЕСТИТЬ Дано
ИЗ
&Дано КАК Дано
;
ВЫБРАТЬ ПЕРВЫЕ 2
    ВЗ.Х
ИЗ
    (ВЫБРАТЬ ПЕРВЫЕ 256
        ВЗ.Х
    ИЗ
        (ВЫБРАТЬ
            Сдвиг.Х
        ИЗ
            Сдвиг КАК Сдвиг

        ОБЪЕДИНИТЬ ВСЕ

        ВЫБРАТЬ
            Дано.Х
        ИЗ
            Дано КАК Дано) КАК ВЗ

    УПОРЯДОЧИТЬ ПО
        Х) КАК ВЗ

УПОРЯДОЧИТЬ ПО
    Х УБЫВ
```
Как в запросе секунды преобразовать в часы и минуты
Теги: 1С,Минимализмы

# Код реализации

```1c
РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1), ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, &ДлительностьВСекундах), ЧАС)
    + МИНУТА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, &ДлительностьВСекундах)) / 100
```
Перебор всех строковых комбинаций "0" и "1" в порядке возрастания числа единиц
Теги: 1С,Минимализмы,Задачи

Очень полезная функция для организации перебора комбинаций. Без циклов!

# Код реализации

```1c
Функция СледующийКод(Код)
    Возврат Прав(СтрЗаменить(Код, "1", "0") + Лев("1" + Код, Найти(Код, "0"))
    + ?(Найти(Код, "01"), "0", "") + Сред(Код, Найти(Код + "01", "01") + 2), СтрДлина(Код))
КонецФункции
```
Заполнение пропусков в таблице цветов
Теги: 1С,Минимализмы,Задачи

Есть таблица: 1 красный; 2 null; 3 null; 4 синий; 5 null; 6 белый; 7 null; 8 null
Нужно получить таблицу: 1 красный; 2 красный; 3 красный; 4 синий; 5 синий; 6 белый; 7 белый; 8 белый

# Код реализации

```1c
ВЫБРАТЬ
    Дано.Номер,
    ЕСТЬNULL(Выше.Цвет, Дано.Цвет)
ИЗ
    Дано КАК Дано
        ЛЕВОЕ СОЕДИНЕНИЕ Дано КАК Выше
        ПО (Дано.Цвет ЕСТЬ NULL )
            И (Выше.Номер В
                (ВЫБРАТЬ
                    МАКСИМУМ(Было.Номер) КАК Номер
                ИЗ
                    Дано КАК Было
                ГДЕ
                    Было.Номер < Дано.Номер
                    И НЕ Было.Цвет ЕСТЬ NULL ))
```
Количество дней недели (понедельников/вторников/...) в заданном диапазоне одним запросом
Теги: 1С,Минимализмы,Задачи

# Код реализации

```1c
ВЫБРАТЬ
   Дни.ДеньНедели,
   РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, -Дни.ДеньНедели), НЕДЕЛЯ)
, НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&КонецПериода, ДЕНЬ, 1 - Дни.ДеньНедели), НЕДЕЛЯ), ДЕНЬ) / 7 КАК КоличествоДней
ИЗ
   (ВЫБРАТЬ 1 КАК ДеньНедели ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5
   ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7) КАК Дни
```
Свернуть строки в таблице значений конкатенацией
Теги: 1С,ТаблицаЗначений,Минимализмы,Задачи

# Код реализации

```1c
Дано.Сортировать("Поле1, Поле2");
ё = Дано.Количество();
Пока ё > 1 Цикл
   ё = ё - 1;
    Если Дано[ё - 1].Поле1 = Дано[ё].Поле1 И Дано[ё - 1].Поле2 = Дано[ё].Поле2 Тогда
        Дано[ё - 1].Поле3 = Дано[ё - 1].Поле3 + Дано[ё].Поле3;
        Дано.Удалить(ё)
    КонецЕсли
КонецЦикла;
```
Алгоритм перебора всех возможных сочетаний элементов
Теги: 1С,Минимализмы,Задачи

На входе массив из элементов: {X1, X2, ..., Xm}. Требуется составить все возможные сочетания элементов без учета размещения: {X1}, {X2}, ..., {Xm}, {X1, X2}, ..., {X1, Xm},...,{X2, Xm},...,{X1, X2, ..., Xm}. Другими словами, требуется получить все возможные подмножества множества элементов, заданного в исходном массиве.
Результат функции - массив списков значений, содержащих разные подмножества элементов исходного массива. Массив включает и пустое подмножество (на последнем месте).

# Код реализации

```1c
Функция ВсеПодмножества(Множество)
    Ответ = Новый Массив;
    Ответ.Добавить(Новый СписокЗначений);
    Для ИндексЭлемента = 0 По Множество.Количество() - 1 Цикл
        Для ИндексВарианта = 0 По Ответ.Количество() - 1 Цикл
            Ответ.Добавить(Ответ[ИндексВарианта].Скопировать());
            Ответ[ИндексВарианта].Добавить(Множество[ИндексЭлемента])
        КонецЦикла
    КонецЦикла;
    Возврат Ответ
КонецФункции
```
Поиск кратчайших путей по алгоритму Флойда-Уоршолла
Теги: 1С,Минимализмы,Задачи

Данное решение иллюстрирует использование соответствия при решении задач на графах. Благодаря этому достигается существенный выигрыш по быстродействию.
С другой стороны, и алгоритм Флойда и алгоритм матричного умножения относятся к классу задач "All Pairs Shortest Paths (APSP) problem", то есть для определения расстояния между парой вершин являются избыточными.  В данной задаче (для заданной пары вершин) лучше использовать алгоритм Дейкстры.

# Код реализации

```1c
Функция КратчайшийПутьФлойд(Откуда, Куда, Дуги) Экспорт
    // загрузка графа в "соответствие соответствий" так, что Пути[Откуда][Куда] = Длина
    Пути = Новый Соответствие;
    Для каждого Дуга Из Дуги Цикл
        Пути[Дуга.Откуда] = ?(Пути[Дуга.Откуда] = Неопределено, Новый Соответствие, Пути[Дуга.Откуда]);
        Пути[Дуга.Откуда][Дуга.Куда] = Дуга.Длина
    КонецЦикла;
    // три вложенных цикла по узлам графа
    Для каждого Узел1 Из Пути Цикл // тогда Узел.Ключ - это одна вершина из полного множества вершин
        Для каждого Узел2 Из Пути Цикл
            Если Пути[Узел2.Ключ][Узел1.Ключ] <> Неопределено Тогда
                Для каждого Узел3 Из Узел1.Значение Цикл // здесь только вершины, связанные с Узел1.Ключ
                    Длина = Пути[Узел2.Ключ][Узел3.Ключ];
                    Обход = Пути[Узел2.Ключ][Узел1.Ключ] + Узел3.Значение; // Узел3.Значение == Пути[Узел1.Ключ][Узел3.Ключ]
                    Пути[Узел2.Ключ][Узел3.Ключ] = ?(Длина = Неопределено, Обход, Мин(Длина, Обход))
                КонецЦикла
            КонецЕсли
        КонецЦикла
    КонецЦикла;
    // восстановление пути
    Путь = Дуги.СкопироватьКолонки("Куда, Длина");
    Путь.Добавить().Куда = Откуда;
    Путь.Добавить().Куда = Куда;
    Путь[1].Длина = Пути[Откуда][Куда];
    Для каждого Узел Из Пути Цикл
        Если Пути[Откуда][Узел.Ключ] <> Неопределено И Пути[Узел.Ключ][Куда] <> Неопределено
            И Пути[Откуда][Узел.Ключ] + Пути[Узел.Ключ][Куда] = Пути[Откуда][Куда] Тогда
            ЗаполнитьЗначенияСвойств(Путь.Добавить(), Новый Структура("Куда, Длина", Узел.Ключ, Пути[Откуда][Узел.Ключ]))
        КонецЕсли
    КонецЦикла;
    Путь.Сортировать("Длина");
    Возврат Путь
КонецФункции // КратчайшийПуть()
```
Определение длины строки в запросе методом половинного деления
Теги: 1С,Минимализмы,Задачи,Строка

В исходной статье был продемонстрирован оригинальный алгоритм определения длины строки в запросе. Однако при высокой скорости вычислений выражение для получения длины строки получается чрезвычайно громозким. На каждую возможную длину строки требуется записать вариант "ТОГДА". В приведенном ниже решении этот недостаток устранен:

# Код реализации

```1c
ВЫБРАТЬ
    Стр, Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -   0, 512) = "" ТОГДА Х -   1 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -   1, 512) = "" ТОГДА Х -   2 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -   3, 512) = "" ТОГДА Х -   4 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -   7, 512) = "" ТОГДА Х -   8 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -  15, 512) = "" ТОГДА Х -  16 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -  31, 512) = "" ТОГДА Х -  32 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -  63, 512) = "" ТОГДА Х -  64 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 127, 512) = "" ТОГДА Х - 128 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 255, 512) = "" ТОГДА Х - 256 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 511, 512) = "" ТОГДА Х - 512 ИНАЧЕ Х КОНЕЦ КАК Х
ИЗ    Дано КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ

//Для строки длиной до 1024 символов используется система из 10-ти вложенных запросов. Исходная таблица, кроме самой строки, должна содержать начальное значение поиска Х, равное 1024.

//Данный вариант не учитывает в длине строки концевые пробелы. Если это действительно требуется, то придется использовать вот такой вариант:

ВЫБРАТЬ
    Стр, Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -   0, 1) + "!" = "!" ТОГДА Х -   1 ИНАЧЕ Х КОНЕЦ Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -   1, 1) + "!" = "!" ТОГДА Х -   2 ИНАЧЕ Х КОНЕЦ Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -   3, 1) + "!" = "!" ТОГДА Х -   4 ИНАЧЕ Х КОНЕЦ Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -   7, 1) + "!" = "!" ТОГДА Х -   8 ИНАЧЕ Х КОНЕЦ Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -  15, 1) + "!" = "!" ТОГДА Х -  16 ИНАЧЕ Х КОНЕЦ Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -  31, 1) + "!" = "!" ТОГДА Х -  32 ИНАЧЕ Х КОНЕЦ Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х -  63, 1) + "!" = "!" ТОГДА Х -  64 ИНАЧЕ Х КОНЕЦ Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 127, 1) + "!" = "!" ТОГДА Х - 128 ИНАЧЕ Х КОНЕЦ Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 255, 1) + "!" = "!" ТОГДА Х - 256 ИНАЧЕ Х КОНЕЦ Х
ИЗ    (ВЫБРАТЬ Стр, ВЫБОР КОГДА ПОДСТРОКА(Стр, Х - 511, 1) + "!" = "!" ТОГДА Х - 512 ИНАЧЕ Х КОНЕЦ Х
ИЗ    Дано КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ) КАК ВЗ
```
Движения периодического регистра сведений без повторов
Теги: 1С,РегистрСведений,Регистр сведений

Часто бывает так, что одно и то же значение устанавливается в периодическом регистре сведений несколько раз подряд. На примере таблицы дат и цен следующий запрос позволяет избавиться от ненужных повторов:

# Код реализации

```1c
ВЫБРАТЬ
    Дано.Дата КАК Дата,
    Дано.Цена
ИЗ
    Дано КАК Дано
        ЛЕВОЕ СОЕДИНЕНИЕ Дано КАК Слева
        ПО (Слева.Дата < Дано.Дата)
СГРУППИРОВАТЬ ПО
    Дано.Дата,
    Дано.Цена
ИМЕЮЩИЕ
    ЕСТЬNULL(МАКСИМУМ(Слева.Дата), 0) <> ЕСТЬNULL(МАКСИМУМ(ВЫБОР Слева.Цена КОГДА Дано.Цена ТОГДА Слева.Дата КОНЕЦ), 1)

//Или вот еще решение через коррелированный запрос (всегда требуется тестировать производительность таких вариантов!)

ВЫБРАТЬ
    Дано.Дата КАК Дата,
    Дано.Цена
ИЗ
    Дано КАК Дано
ГДЕ
    НЕ Дано.Цена В
                (ВЫБРАТЬ ПЕРВЫЕ 1
                    Слева.Цена
                ИЗ
                    Дано КАК Слева
                ГДЕ
                    Слева.Дата < Дано.Дата
                УПОРЯДОЧИТЬ ПО
                    Слева.Дата УБЫВ)
```
Округление в большую сторону
Теги: 1С,Минимализмы,Задачи

Этот прием ранее уже применялся в минимализмах, как часть другого решения, но его можно показать и отдельно, поскольку такие задачи встречаются.

Для округления числа Ч в бОльшую сторону можно применять выражение:

# Код реализации

```1c
М - Цел(М - Ч)
//где М = 999999999 или больше, при необходимости.

//В качестве дополнения красивый прием, взятый из чужого кода. Абсолютное значение числа Ч:

Макс(Ч, -Ч)
```
Сравнение двух массивов
Теги: 1С,Минимализмы,Задачи,Массив

Задача заключается в том, чтобы сравнить два массива и вывести те их элементы, которые не встречаются в обоих массивах, то есть выполнить операцию исключающего ИЛИ для массивов. С использованием соответствия функция сравнения получается достаточно простой:

# Код реализации

```1c
Функция ИсключающееИЛИ(Массив1, Массив2)
    Результат = Новый Массив;
    Повтор = Новый Соответствие;
    Для каждого Элемент Из Массив1 Цикл
        Повтор[Элемент] = ?(Повтор[Элемент] = Неопределено, Ложь, Истина)
    КонецЦикла;
    Для каждого Элемент Из Массив2 Цикл
        Повтор[Элемент] = ?(Повтор[Элемент] = Неопределено, Ложь, Истина)
    КонецЦикла;
    Для каждого Элемент Из Повтор Цикл
        Если НЕ Элемент.Значение Тогда
            Результат.Добавить(Элемент.Ключ)
        КонецЕсли
    КонецЦикла;
    Возврат Результат
КонецФункции

//Если в массиве могут быть только даты (в исходной задаче было так), то можно использовать другой принцип, сократив один цикл:

Функция ИсключающееИЛИ1(Массив1, Массив2)
    Результат = Новый Массив;
    Строка1 = ЗначениеВСтрокуВнутр(Массив1);
    Строка2 = ЗначениеВСтрокуВнутр(Массив2);
    Для каждого Элемент Из Массив1 Цикл
        Если НЕ Найти(Строка2, Формат(Элемент,"ДФ=ггггММддЧЧммсс")) Тогда
            Результат.Добавить(Элемент)
        КонецЕсли
    КонецЦикла;
    Для каждого Элемент Из Массив2 Цикл
        Если НЕ Найти(Строка1, Формат(Элемент,"ДФ=ггггММддЧЧммсс")) Тогда
            Результат.Добавить(Элемент)
        КонецЕсли
    КонецЦикла;
    Возврат Результат
КонецФункции
```
Оптимизация подбора кусков заданного суммарного метража методом ветвей и границ
Теги: 1С,Минимализмы,Задачи

Имеется таблица "Метраж", содержащая информацию о количестве кусков и их метраже: индекс куска, количество кусков, размер куска, общий метраж индекса. Требуется при вводе заданного метража подобрать куски, оптимально составляющие заданный метраж. Желательно использовать минимум кусков вообще и минимум разных кусков.

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

Решение представляет собой две функции. В первой производится подготовка, а во второй рекурсивной функции - собственно решение:

# Код реализации

```1c
Процедура КнопкаСформироватьНажатие(Кнопка)
    РабочаяТаблица = Метраж.Выгрузить();
    РабочаяТаблица.ЗаполнитьЗначения(Метраж.Итог("Имеется"), "НужноВзять");
    Метраж.ЗагрузитьКолонку(РабочаяТаблица.ВыгрузитьКолонку("НужноВзять"), "НужноВзять");
    РабочаяТаблица.ЗаполнитьЗначения(0, "НужноВзять");
    РабочаяТаблица.Сортировать("Коэффициент Убыв");
    ПодборКусков(РабочаяТаблица, РабочаяТаблица.Количество() - 1, Требуется)
КонецПроцедуры

Процедура ПодборКусков(РабочаяТаблица, ВГраница, ЗаданнаяСумма, УжеВзяли = 0) Экспорт
    Если ВГраница < 0 ИЛИ ЗаданнаяСумма < 0 ИЛИ УжеВзяли >= Метраж.Итог("НужноВзять") Тогда //промах
        Возврат
    ИначеЕсли ЗаданнаяСумма = 0 Тогда //фиксируем решение
        Ответ = РабочаяТаблица.Скопировать( , "НомерСтроки, НужноВзять");
        Ответ.Сортировать("НомерСтроки");
        Метраж.ЗагрузитьКолонку(Ответ.ВыгрузитьКолонку("НужноВзять"), "НужноВзять")
    КонецЕсли;
    Курсор = РабочаяТаблица[ВГраница];
    Для НужноВзять = 0 По Курсор.Имеется Цикл
        Курсор.НужноВзять = НужноВзять;
        ПодборКусков(РабочаяТаблица, ВГраница - 1, ЗаданнаяСумма - НужноВзять * Курсор.Коэффициент, УжеВзяли + НужноВзять);
        Курсор.НужноВзять = 0
    КонецЦикла
КонецПроцедуры // ПодборКусков()
```
Объединение данных двух периодических регистров
Теги: 1С,Минимализмы,Задачи

Есть два периодических регистра. Первый содержит количества на дату (РегистрКоличество), а второй - состояния на дату (РегистрСостояние). Даты двух регистров независимы друг от друга. Требуется запросом построить третий "регистр", являющийся объединением первых двух, чтобы показывались соответствующие друг другу даты, количества и состояния.
Вот короткое решение с использованием коррелированных запросов (ахтунг!):

# Код реализации

```1c
ВЫБРАТЬ
    ВЫБОР
        КОГДА ТаблицаКоличества.Дата > ТаблицаСостояний.Дата
            ТОГДА ТаблицаКоличества.Дата
        ИНАЧЕ ТаблицаСостояний.Дата
    КОНЕЦ КАК Дата,
    ТаблицаКоличества.Количество КАК Количество,
    ТаблицаСостояний.Состояние КАК Состояние
ИЗ
    ТаблицаКоличества КАК ТаблицаКоличества
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТаблицаСостояний КАК ТаблицаСостояний
        ПО (ТаблицаСостояний.Дата В
                    (ВЫБРАТЬ
                        МАКСИМУМ(ТаблицаСостояний.Дата)
                    ИЗ
                        ТаблицаСостояний КАК ТаблицаСостояний
                    ГДЕ
                        ТаблицаСостояний.Дата <= ТаблицаКоличества.Дата)
                ИЛИ ТаблицаКоличества.Дата В
                    (ВЫБРАТЬ
                        МАКСИМУМ(ТаблицаКоличества.Дата)
                    ИЗ
                        ТаблицаКоличества КАК ТаблицаКоличества
                    ГДЕ
                        ТаблицаКоличества.Дата <= ТаблицаСостояний.Дата))
```
Определение длины строки в запросе
Теги: 1С,Строка

# Код реализации

```1c
ВЫБРАТЬ
    Дано.НомерСтроки,
    Дано.Строка
ПОМЕСТИТЬ Дано
ИЗ
    &Дано КАК Дано
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    0 КАК ё
ПОМЕСТИТЬ Р0

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    1
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    2 * Р1.ё + Р0.ё КАК ё
ПОМЕСТИТЬ Р10
ИЗ
    Р0 КАК Р1,
    Р0 КАК Р0
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    4 * Р32.ё + Р10.ё КАК ё
ПОМЕСТИТЬ Р3210
ИЗ
    Р10 КАК Р32,
    Р10 КАК Р10
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    16 * Р54.ё + Р3210.ё + 1 КАК ё
ПОМЕСТИТЬ Р543210
ИЗ
    Р10 КАК Р54,
    Р3210 КАК Р3210
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Дано.НомерСтроки,
    Дано.Строка,
    МАКСИМУМ(Р543210.ё) КАК ДлинаСтроки
ИЗ
    Дано КАК Дано,
    Р543210 КАК Р543210
ГДЕ
    ПОДСТРОКА(Дано.Строка, Р543210.ё, 1) + "!" <> "!"

СГРУППИРОВАТЬ ПО
    Дано.НомерСтроки,
    Дано.Строка
```