Решение алгоритмических задач на базе 1С:Предприятие | Новый выпуск Algo1C

07.10.24

Разработка - Математика и алгоритмы

Решаем новые задачи по программированию на 1С!

Добро пожаловать на новый выпуск рубрики "Algo1C", в которой я стараюсь регулярно решать новые задачи по программированию и делиться своими решениями с вами!

Цель рубрики заключается в тренировке практик по применению различных алгоритмов и в поддержании навыка "Писать код" в тонусе!


Что было раньше:

В предыдущей части (нажмите на строку) мы решили:

В этой части вас ждут еще более интересные алгоритмические задачи. Давайте, приступим!

Перед началом чтения решения задачи, хочу призвать каждого к самостоятельному решению задачи, чтобы после вы могли сравнить своё решение с моим и обсудить это в комментариях. Буду рад послушать ваше мнение!


Решение новых задач:

 
 Задача 1

 Платформа: CodeWars

 Название задачи: Move 10 (Передвиньте на 10)

 Ссылка на задачу: https://www.codewars.com/kata/57cf50a7eca2603de0000090 (Нажмите на строку)

 Сложность: 7 kyu (7 / 8)

 Тэги: Фундаментальные, Строки, Массивы

 Оригинальное описание задачи:

Move every letter in the provided string forward 10 letters through the alphabet. If it goes past 'z', start again at 'a'. Input will be a string with length > 0.

Пояснение:

Суть задачи заключается в том чтобы заменить каждую букву в данной строке на символ, который находится на 10 элементов впереди. Например если дана буква "A" то заменить её строит на "K", следуя порядку английского алфавита. По своему принципу это напоминает "Шифр Цезаря", он же "Шифр Сдвига", где каждая буква заменялась на буквы X-позиций левее или правее. Думаю всё понятно, давайте приступим к решению!


Решение:

Для начала соберем все буквы английского алфавита в массив, чтобы в дальнейшем было удобно искать буквы. Далее пишем цикл для перебора всех элементов исходной строки и в каждой итерации получаем индекс текущей буквы в массиве с алфавитом. Далее пишем условие, в котором проверяем не вылезает ли новый индекс (Текущий индекс + смещение) за границу массива. Если нет то просто получаем этот элемент по новому индексу и записываем. Если выходит за границу то получаем букву уже с начала алфавита и также записываем. Вполне себе простой принципе. Вот как это будет выглядеть в коде:

 ИсходнаяСтрока = "Infostart";
Смещение = 10;
//
АнглАлфавит = СтрРазделить("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"," ",Ложь);
//
Вывод = "";
Для НомерЭлемента = 1 По СтрДлина(ИсходнаяСтрока) Цикл
  ТекПозиция = АнглАлфавит.Найти(ВРег(Сред(ИсходнаяСтрока,НомерЭлемента,1)));  
  Если ТекПозиция+Смещение < АнглАлфавит.Количество()-1 Тогда
    Вывод = Вывод + АнглАлфавит[ТекПозиция+Смещение];
  Иначе
    Вывод = Вывод + АнглАлфавит[Смещение - ((АнглАлфавит.Количество())-ТекПозиция)];
  КонецЕсли;        
КонецЦикла;

Результат:

SXPYCDKBD

Очень занимательная задача. Криптография всегда была одной из интереснейших тем для изучения!

 
 Задача 2

 Платформа: CodeWars

 Название задачи: No oddities here (Тут нет "нечетностей")

 Ссылка на задачу: https://www.codewars.com/kata/51fd6bc82bc150b28e0000ce (Нажмите на строку)

 Сложность: 7 kyu (7 / 8)

 Тэги: Массивы, Фундаментальные

 Оригинальное описание задачи:

Write a small function that returns the values of an array that are not odd. All values in the array will be integers. Return the good values in the order they are given.

Пояснение:

Цель задачи заключается в том чтобы из исходного массива получить все четные числа. Описание короткое, также же каким будет и решение. Давайте приступим!


Решение:

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

 ИсходныйМассив = Новый Массив;
ИсходныйМассив.Добавить(1);
ИсходныйМассив.Добавить(2);
ИсходныйМассив.Добавить(3);
ИсходныйМассив.Добавить(4);
ИсходныйМассив.Добавить(5);
//
Вывод = Новый Массив;
Для Каждого Стр Из ИсходныйМассив Цикл
  Если Стр%2 = 0 Тогда
    Вывод.Добавить(Стр);
  КонецЕсли;
КонецЦикла;
Вывод = СтрСоединить(Вывод,",");

Результат:

2,4

Получилась простая и короткая задача, годится в качестве разминки!

 
 Задача 3

 Платформа: CodeWars

 Название задачи: The 'spiraling' box ("Спиралевидная" коробка)

 Ссылка на задачу: https://www.codewars.com/kata/63b84f54693cb10065687ae5 (Нажмите на строку)

 Сложность: 7 kyu (7 / 8)

 Тэги: Массивы, Фундаментальные

 Оригинальное описание задачи:

Given two positive integers m (width) and n (height), fill a two-dimensional list (or array) of size m-by-n in the following way:
(1) All the elements in the first and last row and column are 1.
(2) All the elements in the second and second-last row and column are 2, excluding the elements from step 1.
(3) All the elements in the third and third-last row and column are 3, excluding the elements from the previous steps.
And so on ...

Examples Given m = 5, n = 8, your function should return
[[1, 1, 1, 1, 1],
[1, 2, 2, 2, 1],
[1, 2, 3, 2, 1],
[1, 2, 3, 2, 1],
[1, 2, 3, 2, 1],
[1, 2, 3, 2, 1],
[1, 2, 2, 2, 1],
[1, 1, 1, 1, 1]]

Given m = 10, n = 9, your function should return
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 2, 2, 2, 2, 2, 2, 2, 1],
[1, 2, 3, 3, 3, 3, 3, 3, 2, 1],
[1, 2, 3, 4, 4, 4, 4, 3, 2, 1],
[1, 2, 3, 4, 5, 5, 4, 3, 2, 1],
[1, 2, 3, 4, 4, 4, 4, 3, 2, 1],
[1, 2, 3, 3, 3, 3, 3, 3, 2, 1],
[1, 2, 2, 2, 2, 2, 2, 2, 2, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

Пояснение:

По условию задачи нам дана ширина и высота двумерного массива. Нам необходимо заполнить его значениями, следуя следующий правилам:
1) Все элементы первой строки и первой колонки равны 1
2) Все элементы второй строки и второй колонки равны 2, за исключением элементов предыдущего правила
3) Все элементы третьей строки и третьей колонки равны 3, за исключением элементов предыдущего правила
4) И так далее до бесконечности

Например дана ширина 5 и высота 8, в итоге должен получиться следующий массив:
[[1, 1, 1, 1, 1],
[1, 2, 2, 2, 1],
[1, 2, 3, 2, 1],
[1, 2, 3, 2, 1],
[1, 2, 3, 2, 1],
[1, 2, 3, 2, 1],
[1, 2, 2, 2, 1],
[1, 1, 1, 1, 1]]

Если приглядеться то визуально суть более чем понятна. Мы имеем короб со вложенными коробами, нам лишь нужно выделить каждый короб разными числами. Давайте попробуем решить:


Решение:

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

 ИсходнаяШирина = 10;
ИсходнаяВысота = 9;
//
КонечныйМассив = Новый Массив;
Для НомерЭлемента = 1 По ИсходнаяВысота Цикл
  ТекущийМассив = Новый Массив;  
  Для НомерПодЭлемента = 1 По ИсходнаяШирина Цикл
    ТекущийМассив.Добавить(0);
  КонецЦикла;
  КонечныйМассив.Добавить(ТекущийМассив);  
КонецЦикла;
//
Для НомерЭлемента = 1 По ИсходнаяВысота Цикл
  Для Счетчик = 1 По ИсходнаяШирина Цикл
    Для НомерПодЭлемента = 1 По ИсходнаяШирина Цикл  
      Если КонечныйМассив[НомерЭлемента-1][НомерПодЭлемента-1]  = 0 Тогда
        Если НомерЭлемента = Счетчик Или НомерЭлемента = ИсходнаяВысота-(Счетчик-1) Или НомерПодЭлемента = Счетчик Или НомерПодЭлемента = ИсходнаяШирина-(Счетчик-1) Тогда
          КонечныйМассив[НомерЭлемента-1][НомерПодЭлемента-1] = Счетчик;
        КонецЕсли;
      КонецЕсли;  
    КонецЦикла;
  КонецЦикла;
КонецЦикла;
//
Вывод = "";
Для Каждого Стр Из КонечныйМассив Цикл
  Вывод = Вывод + СтрСоединить(Стр,",");
  //
  Вывод = Вывод + Символы.ПС;
КонецЦикла;

Результат:

1,1,1,1,1,1,1,1,1,1
1,2,2,2,2,2,2,2,2,1
1,2,3,3,3,3,3,3,2,1
1,2,3,4,4,4,4,3,2,1
1,2,3,4,5,5,4,3,2,1
1,2,3,4,4,4,4,3,2,1
1,2,3,3,3,3,3,3,2,1
1,2,2,2,2,2,2,2,2,1
1,1,1,1,1,1,1,1,1,1

Очень интересная получилась задача, надеюсь в будущем встречу еще больше подобных!

 
 Задача 4

 Платформа: CodeWars

 Название задачи: Count the divisors of a number (Посчитай количество делителей числа)

 Ссылка на задачу: https://www.codewars.com/kata/542c0f198e077084c0000c2e (Нажмите на строку)

 Сложность: 7 kyu (7 / 8)

 Тэги: Теория чисел, Математика, Фундаментальные

 Оригинальное описание задачи:

Count the number of divisors of a positive integer n. Random tests go up to n = 500000, but fixed tests go higher.

Examples (input --> output) 4 --> 3 // we have 3 divisors - 1, 2 and 4
5 --> 2 // we have 2 divisors - 1 and 5
12 --> 6 // we have 6 divisors - 1, 2, 3, 4, 6 and 12
30 --> 8 // we have 8 divisors - 1, 2, 3, 5, 6, 10, 15 and 30

Note you should only return a number, the count of divisors. The numbers between parentheses are shown only for you to see which numbers are counted in each case.

Пояснение:

Суть задачи заключается в том чтобы найти количество всех делителей исходного числа. Например если дано число 4, нам необходимо вернуть число 3, так как у числа 4 только 3 делители, то есть 1, 2 и 4. Звучит просто, давайте попробуем решить задачу:


Решение:

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

 ИсходноеЧисло = 30;
//
Вывод = 0;
Для НомерЭлемента = 1 По ИсходноеЧисло Цикл
  Если ИсходноеЧисло%НомерЭлемента=0 Тогда
    Вывод = Вывод + 1;
  КонецЕсли;
КонецЦикла;

Результат:

8

Получилась простая задача с небольшим решением!

 
 Задача 5

 Платформа: CodeWars

 Название задачи: T.T.T. #9: Peaks and valleys (Вершины и Долины)

 Ссылка на задачу: https://www.codewars.com/kata/5769e0db6a3efea1b1000010 (Нажмите на строку)

 Сложность: 7 kyu (7 / 8)

 Тэги: Головоломки, Игры

 Оригинальное описание задачи:

Give you an array arr that contains some number elements, find out the peaks and valleys in the array, and return them. What do the peaks and valleys mean? If an element is larger than the three one on the left and larger than the three one on the right, we call it a peak. In contrast, an element is smaller than the value of the three elements(left and right), we call it a valley.

an example:
[10,20,30,40,30,20,10,11,12,13,14,15,16,15,14,13] In the example above, peaks and valleys are: [10,20,30,40,30,20,10,11,12,13,14,15,16,15,14,13] [ 40 , 10 , 16 ]

Some examples:
peakAndValley([10,20,30,40,30,20,10,11,12,13,14,15,16,15,14,13]) should return [40,10,16] peakAndValley([50,84,49,47,80,87,87,53,76,30,10]) should return [47]
peakAndValley([45,94,41,76,29,96,28,13,84,69,25]) should return [96,13]
peakAndValley([1,16,63,78,53,78,42,39,46,88,49,96,58,82]) should return [39] peakAndValley([45,75,47,44,93,95,31,99,49,48,76,2,92,23,26,19,60,45,51]) should return [31,99,2,92,19] peakAndValley([49,97,76,56,96,88,65,20,14,93,32]) should return []

Пояснение:

Цель задачи заключается в том чтобы из данного массива найти "Вершины" и "Долины". Что это значит? Под вершинами в этой задаче подразумевается значение, которое больше трёх предыдущих и трёх последующих значений. Обратно от этой логики работают "Долины", то есть значение должно быть меньше трёх значений с двух сторон.

Например в массиве:
[10,20,30,40,30,20,10,11,12,13,14,15,16,15,14,13]
Долинами и вершинами будут [40,10,16]
Принцип думаю понятен. Давайте попробуем решить:


Решение:

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

 ИсходныйМассив = Новый Массив;
ИсходныйМассив.Добавить(10);
ИсходныйМассив.Добавить(20);
ИсходныйМассив.Добавить(30);
ИсходныйМассив.Добавить(40);
ИсходныйМассив.Добавить(30);
ИсходныйМассив.Добавить(20);
ИсходныйМассив.Добавить(10);
ИсходныйМассив.Добавить(11);
ИсходныйМассив.Добавить(12);
ИсходныйМассив.Добавить(13);
ИсходныйМассив.Добавить(14);
ИсходныйМассив.Добавить(15);
ИсходныйМассив.Добавить(16);
ИсходныйМассив.Добавить(15);
ИсходныйМассив.Добавить(14);
ИсходныйМассив.Добавить(13);
//
ВершиныИДолины = Новый Массив;
//
Для НомерЭлемента = 0 По ИсходныйМассив.Количество()-1 Цикл
  Долина = Истина;
  Вершина = Истина;
  //
  Для НомерПодЭлемента = 1 По 3 Цикл
    Попытка
      Если ИсходныйМассив[НомерЭлемента] < ИсходныйМассив[НомерЭлемента-НомерПодЭлемента] Тогда
        Вершина = Ложь;
      КонецЕсли;
    Исключение
      Вершина = Ложь;
    КонецПопытки;
    //
    Попытка
      Если ИсходныйМассив[НомерЭлемента] < ИсходныйМассив[НомерЭлемента+НомерПодЭлемента] Тогда
        Вершина = Ложь;
      КонецЕсли;
    Исключение
      Вершина = Ложь;
    КонецПопытки;
  КонецЦикла;
  //
  Для НомерПодЭлемента = 1 По 3 Цикл
    Попытка
      Если ИсходныйМассив[НомерЭлемента] > ИсходныйМассив[НомерЭлемента-НомерПодЭлемента] Тогда
        Долина = Ложь;
      КонецЕсли;
    Исключение
      Долина = Ложь;
    КонецПопытки;
    //
    Попытка
      Если ИсходныйМассив[НомерЭлемента] > ИсходныйМассив[НомерЭлемента+НомерПодЭлемента] Тогда
        Долина = Ложь;
      КонецЕсли;
    Исключение
      Долина = Ложь;
    КонецПопытки;
  КонецЦикла;
  //
  Если Долина Или Вершина Тогда
    ВершиныИДолины.Добавить(ИсходныйМассив[НомерЭлемента]);
  КонецЕсли;
КонецЦикла;
//
Вывод = СтрСоединить(ВершиныИДолины,",");

Результат:

40,10,16

Получилась интересная и занимательная задача!

 
 Новое в конфигурации Algo1C:

Заключение:

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

Алгоритмы Математика CodeWars LeetCode Algo1C Задачи

См. также

Математика и алгоритмы Программист Платформа 1C v8.2 Конфигурации 1cv8 Россия Абонемент ($m)

На написание данной работы меня вдохновила работа @glassman «Переход на ClickHouse для анализа метрик». Автор анализирует большой объем данных, много миллионов строк, и убедительно доказывает, что ClickHouse справляется лучше PostgreSQL. Я же покажу как можно сократить объем данных в 49.9 раз при этом: 1. Сохранить значения локальных экстремумов 2. Отклонения от реальных значений имеют наперед заданную допустимую погрешность.

1 стартмани

30.01.2024    3154    stopa85    12    

38

Математика и алгоритмы Бесплатно (free)

Разработка алгоритма, построенного на модели симплекс-метода, для нахождения оптимального раскроя.

19.10.2023    7541    user1959478    51    

36

Математика и алгоритмы Разное Платформа 1С v8.3 Конфигурации 1cv8 Россия Абонемент ($m)

Расширение (+ обработка) представляют собою математический тренажер. Ваш ребенок сможет проверить свои знание на математические вычисление до 100.

2 стартмани

29.09.2023    3101    maksa2005    8    

26

Математика и алгоритмы Инструментарий разработчика Программист Платформа 1С v8.3 Мобильная платформа Россия Абонемент ($m)

Что ж... лучше поздно, чем никогда. Подсистема 1С для работы с регулярными выражениями: разбор выражения, проверка на соответствие шаблону, поиск вхождений в тексте.

1 стартмани

09.06.2023    10893    7    SpaceOfMyHead    18    

61

Математика и алгоритмы Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Три задачи - три идеи - три решения. Мало кода, много смысла. Мини-статья.

03.04.2023    4353    RustIG    9    

25

Механизмы платформы 1С Математика и алгоритмы Программист Платформа 1С v8.3 Россия Бесплатно (free)

В статье анализируются средства платформы для решения системы линейных уравнений в 1С. Приводятся доводы в пользу некорректной работы встроенных алгоритмов, а значит потенциально некорректного расчета себестоимости в типовых конфигурациях.

23.11.2022    3517    gzharkoj    14    

25

Математика и алгоритмы Программист Платформа 1С v8.3 Россия Абонемент ($m)

Обычно под распределением понимают определение сумм пропорционально коэффициентам. Предлагаю включить сюда также распределение по порядку (FIFO, LIFO) и повысить уровень размерности до 2-х. 1-ое означает, что распределение может быть не только пропорциональным, но и по порядку, а 2-ое - это вариант реализации матричного распределения: по строкам и столбцам. Возможно вас заинтересует также необычное решение этой задачи через создание DSL на базе реализации текучего интерфейса

1 стартмани

21.03.2022    9038    7    kalyaka    11    

44
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. RustIG 1747 07.10.24 13:42 Сейчас в теме
(0) Добрый день! для алгоритмов с матрицами можете воспользоваться алгоритмами из статьи https://infostart.ru/1c/tools/1984471/
TheNabiulla; +1 Ответить
3. TheNabiulla 78 07.10.24 17:33 Сейчас в теме
(1) Добрый. Принял, обязательно посмотрю, благодарю!
2. b2bro 10 07.10.24 14:02 Сейчас в теме
Добрый день. А почему в первой задаче просто не использовать коды символов ? перешагнули за код("Z"), начали с код("А") плюс остаток ?
никаких массивов не надо

В задаче про двумерный массив не совсем корректен перевод:
первая и последняя строки и колонки заполняются 1
вторая с начала и вторая с конца строки и колонки заполняются 2 (кроме первого правила)
ну и так далее
(вы не перевели, что с конца строки и колонки в правилах присутствуют)
TheNabiulla; +1 Ответить
4. TheNabiulla 78 07.10.24 17:34 Сейчас в теме
(2) Добрый. Отличная мысль с кодами, обязательно попробую альтернативу! Также благодарю что указали на ошибку!
Оставьте свое сообщение