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

08.10.24

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

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

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

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


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

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

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

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


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

 
 Задача 1

 Платформа: CodeWars

 Название задачи: Mumbling (Бормотание)

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

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

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

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

This time no story, no theory. The examples below show you how to write function accum:
Examples:
accum("abcd") -> "A-Bb-Ccc-Dddd"
accum("RqaEzty") -> "R-Qq-Aaa-Eeee-Zzzzz-Tttttt-Yyyyyyy"
accum("cwAt") -> "C-Ww-Aaa-Tttt"
The parameter of accum is a string which includes only letters from a..z and A..Z.

Пояснение:

Суть задачи заключается в том чтобы их исходной строки построить строку, похожую на бормотание. Под такой строкой подразумевается строка, где каждый символ исходной строки встречается несколько раз. Количество вхождений увеличивается с каждым разом по мере прохождения по исходной строке. Последовательности каждой буквы разделяются с помощью дефиса. Также каждая последовательность должна начинаться с большой буквы. Например строка "abcd" должна в итоге преобразоваться в строку "A-Bb-Ccc-Dddd". Думаю суть понятна, давайте приступим к решению:


Решение:

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

 ИсходнаяСтрока = "RqaEzty";
//
Вывод = "";
КоличествоЭлементов = 1;
Для НомерЭлемента = 1 По СтрДлина(ИсходнаяСтрока) Цикл
  Для НомерПодЭлемента = 1 По КоличествоЭлементов Цикл
    Если НомерПодЭлемента = 1 Тогда  
      Вывод = Вывод + ВРег(Сред(ИсходнаяСтрока,НомерЭлемента,1));
    Иначе
      Вывод = Вывод + Сред(ИсходнаяСтрока,НомерЭлемента,1);
    КонецЕсли;
  КонецЦикла;
  Если НомерЭлемента <> СтрДлина(ИсходнаяСтрока) Тогда
    Вывод = Вывод + "-";
  КонецЕсли;
  //
  КоличествоЭлементов = КоличествоЭлементов + 1;  
КонецЦикла;

Результат:

R-Qq-Aaa-EEEE-Zzzzz-Tttttt-Yyyyyyy

Интересная получилась задача. Думаю решение тоже неплохое!

 
 Задача 2

 Платформа: CodeWars

 Название задачи: How Many Streets? (Сколько улиц?)

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

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

 Тэги: Массивы, Поиск, Производительность

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

The longest street in the world, MAX_STREET, is crossed by many other streets and driven by many drivers. Determine how many streets each driver crosses. Inputs (1) A list of streets that intersect MAX_STREET. (2) A list of drivers. Each driver is represented by a pair of streets. The first element of the pair is the street where they enter MAX_STREET; the second is the street they exit. The driver crosses all the streets between those two streets. Output A list showing how many streets each driver crosses.

Example
count_streets(["first", "second", "third", "fourth", "fifth", "sixth", "seventh"], [("first", "second"), ("second", "seventh"), ("sixth", "fourth")]) should return [0,4,1].

Details: (1) Each street name is a non-empty word of no more than 10 letters. There are no duplicate street names. (2) The entry and exit streets for each driver are distinct. They are guaranteed to come from the list of streets. (3) The number of streets n satisfies 2 ≤ n ≤ 105. The number of drivers d satisfies 1 ≤ d ≤ 105. So efficiency is important. Source: International Collegiate Programming Contest, North Central North American Regional, 2022.

Пояснение:

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

Например:
Большая улица: ["first", "second", "third", "fourth", "fifth", "sixth", "seventh"]
Водители: [("first", "second"), ("second", "seventh"), ("sixth", "fourth")]
Первый водитель начал путь с улицы "First" и затем завернул на улицу "second", он пересёк 0 улиц. По такому же принципу получаем 4 у второго водителя и 1 у третьего водителя.
Итого вывод: 0,4,1
Думаю суть понятна, давайте попробуем решить:


Решение:

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

 ИсходныйМассивУлиц = Новый Массив;
ИсходныйМассивУлиц.Добавить("first");
ИсходныйМассивУлиц.Добавить("second");
ИсходныйМассивУлиц.Добавить("third");
ИсходныйМассивУлиц.Добавить("fourth");
ИсходныйМассивУлиц.Добавить("fifth");
ИсходныйМассивУлиц.Добавить("sixth");
ИсходныйМассивУлиц.Добавить("seventh");
//
ИсходныйМассивВодителей = Новый Массив;
ПервыйВодитель = Новый Массив;
ПервыйВодитель.Добавить("first");
ПервыйВодитель.Добавить("second");
ВторойВодитель = Новый Массив;
ВторойВодитель.Добавить("second");
ВторойВодитель.Добавить("seventh");
ТретийВодитель = Новый Массив;
ТретийВодитель.Добавить("sixth");
ТретийВодитель.Добавить("fourth");
ИсходныйМассивВодителей.Добавить(ПервыйВодитель);
ИсходныйМассивВодителей.Добавить(ВторойВодитель);
ИсходныйМассивВодителей.Добавить(ТретийВодитель);
//
Вывод = Новый Массив;
Для Каждого Стр Из ИсходныйМассивВодителей Цикл
  Вывод.Добавить((Макс(ИсходныйМассивУлиц.Найти(Стр[0]),ИсходныйМассивУлиц.Найти(Стр[1]))-1) - Мин(ИсходныйМассивУлиц.Найти(Стр[0]),ИсходныйМассивУлиц.Найти(Стр[1])));    
КонецЦикла;
Вывод = СтрСоединить(Вывод,",");

Результат:

0,4,1

Вполне себе неплохая задача. Интересный факт: В описании задачи написано что она была на ICPC 2022

 
 Задача 3

 Платформа: CodeWars

 Название задачи: Odder Than the Rest (Более нечетный чем остальные)

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

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

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

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

Create a method that takes an array/list as an input, and outputs the index at which the sole odd number is located. This method should work with arrays with negative numbers. If there are no odd numbers in the array, then the method should output -1.

Examples:
odd_one([2,4,6,7,10]) # => 3
odd_one([2,16,98,10,13,78]) # => 4
odd_one([4,-8,98,-12,-7,90,100]) # => 4
odd_one([2,4,6,8]) # => -1

Пояснение:

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


Решение:

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

 ИсходныйМассив = Новый Массив;
ИсходныйМассив.Добавить(2);
ИсходныйМассив.Добавить(4);
ИсходныйМассив.Добавить(6);
ИсходныйМассив.Добавить(7);
ИсходныйМассив.Добавить(10);
//
Вывод = -1;
Для НомерЭлемента = 0 По ИсходныйМассив.Количество()-1 Цикл
  Если Макс(ИсходныйМассив[НомерЭлемента],-ИсходныйМассив[НомерЭлемента])% 2 <> 0 Тогда
    Вывод = НомерЭлемента;
  КонецЕсли;
КонецЦикла;

Результат:

3

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

 
 Задача 4

 Платформа: CodeWars

 Название задачи: Channelling power of Primes into a new Number (Преобразование силы простых чисел в новое число)

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

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

 Тэги: Математика

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

Let's look on natural numbers
(counting from 1 =( ) and mark each number as 1 if it is prime and 0 otherwise. 1 2 3 4 5 6 7 8 ... 0 1 1 0 1 0 1 0 ...
For given number n output an integer whose bits are exactly bits of sequence above up to (including) n.
Consider little-endian order. n <= 10 000.

Example
Let n be 9.
1 2 3 4 5 6 7 8 9 - naturals
0 1 1 0 1 0 1 0 0 - "prime" bits
1 2 4 8 16 32 64 128 256 - corresponding powers of two
 So channelling_powers(9) equals 2 + 4 + 16 + 64 = 86.

Пояснение:

Суть задачи заключается в двух шагах. Для начала нам необходимо из исходного числа получить последовательность нулей и единиц. Каждый элемент нового массива соответствует числу внутри диапазона исходного числа. Ноль будем записывать если число не является простым, и наоборот с единицей. Например дано число 9, внутри девятки всего 9 натуральных чисел, то есть 1 2 3 4 5 6 7 8 9 Далее проверяем каждое число на простоту и получаем следующую последовательность: 0 1 1 0 1 0 1 0 0 Теперь приступаем ко второму шагу. Нам необходимо получить все степени двойки. Количество степеней будет равно количеству элементов предыдущей последовательность. Далее необходимо сопоставить последовательность со степенями, в итоге получится: 0 1 1 0 1 0 1 0 0 1 2 4 8 16 32 64 128 256 Ну и затем отберем только те степени, которые соответствуют числу 1, то есть простому числу в исходных данных. Ну и затем прибавим друг к другу все отобранные числа и вернем в качестве результата: 2 + 4 + 16 + 64 = 86 Вполне себе понятно, давайте попробуем решить:


Решение:

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

 ИсходноеЧисло = 9;
//
ПростыеЧисла = Новый Массив;
Для НомерЭлемента = 1 По ИсходноеЧисло Цикл
  Если НомерЭлемента <= 9 Тогда
    КоличествоДелителей = 0;
    Если НомерЭлемента = 1 Тогда
      ПростыеЧисла.Добавить(0);
    Иначе
      Для НомерПодЭлемента = 1 По НомерЭлемента Цикл
        Если НомерЭлемента%НомерПодЭлемента=0 Тогда
          КоличествоДелителей = КоличествоДелителей + 1;
        КонецЕсли;
      КонецЦикла;
      //
      Если КоличествоДелителей <> 1 И КоличествоДелителей > 2 Тогда
        ПростыеЧисла.Добавить(0);
      Иначе
        ПростыеЧисла.Добавить(1);
      КонецЕсли;  
    КонецЕсли;
  КонецЕсли;
КонецЦикла;
//
Вывод = 0;
Для НомерЭлемента = 0 По ПростыеЧисла.Количество()-1 Цикл
  Если ПростыеЧисла[НомерЭлемента] = 1 Тогда
    Вывод = Вывод + Pow(2,НомерЭлемента);
  КонецЕсли;
КонецЦикла;

Результат:

86

Весьма занимательная задача. Я думаю решение тоже получилось неплохим!

 
 Задача 5

 Платформа: CodeWars

 Название задачи: Simple string characters (Простые строковые символы)

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

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

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

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

In this Kata, you will be given a string and your task will be to return a list of ints detailing the count of uppercase letters, lowercase, numbers and special characters, as follows.
Solve("*'&ABCDabcde12345") = [4,5,5,3].
--the order is: uppercase letters, lowercase, numbers and special characters. More examples in the test cases. Good luck!

Пояснение:

Цель задачи заключается в том чтобы посчитать количество символов в строке. Нам нужно узнать сколько символов в верхнем регистре, нижнем регистре, сколько чисел и сколько специальных символов. Например в строке *'&ABCDabcde12345 мы получим четыре символа в верхнем регистре, пять в нижнем, пять цифр и три спецсимвола. Итого вернем массив [4,5,5,3] Звучит просто, давайте попробуем решить:


Решение:

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

 ИсходнаяСтрока = "*'&ABCDabcde12345";
//
Вывод = Новый Массив;
Вывод.Добавить(0);
Вывод.Добавить(0);
Вывод.Добавить(0);
Вывод.Добавить(0);
//
Для НомерЭлемента = 1 По СтрДлина(ИсходнаяСтрока) Цикл
  ТекущийСимвол = Сред(ИсходнаяСтрока,НомерЭлемента,1);
  Если СтрРазделить("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"," ",Ложь).Найти(ВРег(ТекущийСимвол)) <> Неопределено Тогда
    Если ТекущийСимвол = ВРег(ТекущийСимвол) Тогда
      Вывод[0] = Вывод[0] + 1;
    Иначе
      Вывод[1] = Вывод[1] + 1;
    КонецЕсли;
  ИначеЕсли СтрРазделить("1 2 3 4 5 6 7 8 9 0"," ",Ложь).Найти(ТекущийСимвол) <> Неопределено Тогда
    Вывод[2] = Вывод[2] + 1;
  Иначе
    Вывод[3] = Вывод[3] + 1;
  КонецЕсли; 
КонецЦикла;
//
Вывод = СтрСоединить(Вывод,",");

Результат:

4,5,5,3

Небольшая но зато весьма интересная задача!

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

Заключение:

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

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

См. также

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

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

1 стартмани

30.01.2024    3205    stopa85    12    

38

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

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

19.10.2023    7614    user1959478    52    

36

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

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

2 стартмани

29.09.2023    3144    maksa2005    8    

26

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

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

1 стартмани

09.06.2023    10927    7    SpaceOfMyHead    18    

61

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

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

03.04.2023    4398    RustIG    9    

25

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

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

23.11.2022    3563    gzharkoj    14    

25

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

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

1 стартмани

21.03.2022    9050    7    kalyaka    11    

44
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. n_mezentsev 57 09.10.24 10:41 Сейчас в теме
Вот вам задачка на 8 kyu (из моего вчерашнего): дана последовательность слов, разделенных пробелами. Нужно составить все их возможные комбинации (магистр Йода говорит;)). Решение нашлось (самостоятельно), но оно больше похоже на магию, а ведь наверняка есть общепринятые алгоритмы...
2. scientes 295 10.10.24 09:41 Сейчас в теме
(1) Добрый день. Могу предложить рекурсию. Вот общий код. У вас есть переменная массив, которая содержит исходный набор слов.

Функция  Рекурсия(массив,ответ)
        если массив.Количество()=0 тогда
             //можно предусмотреть массив для хранения результатов 
             // и делать проверку на отсутствие найденного набора
            // для случая, когда есть повторяющиеся слова
            сообщить(ответ);
           возврат 1;
        конецесли;  
        для н=0 по массив.ВГраница() цикл
               слово=массив[н];
               массив.Удалить(н);
                   Рекурсия(массив,ответ+?(ответ="",слово," "+слово);
               массив.Вставить(н,слово);
       конеццикла;
конецфункции
Показать

Вызов функции Рекурсия(массив,"");
3. n_mezentsev 57 10.10.24 11:15 Сейчас в теме
(2) Тоже первым делом подумал про рекурсию, но с выходом из нее проблемы были, а потом само собой получилось, что и без нее два цикла прекрасно справляются, хоть и с остаточными включениями, а ваш алгоритм четко-дружно работает. Класс!
Н-да, из-за особенностей хранения в памяти ссылочных переменных 1С пришлось немного извернуться, но в целом да, ваш алгоритм работает и с массивом в качестве корзины для сбора последовательности:
Процедура ВсеВозможныеКомбинации(массив, ВсеКомбинации, Знач Комбинация = Неопределено)
	Если массив.Количество()=0 Тогда
		//можно предусмотреть массив для хранения результатов 
		// и делать проверку на отсутствие найденного набора
		// для случая, когда есть повторяющиеся слова
		ВсеКомбинации.Добавить(Комбинация);
		Возврат;
	КонецЕсли;  
	Для н=0 По массив.ВГраница() Цикл
		слово=массив[н];
		массив.Удалить(н);
		Если Комбинация = Неопределено Тогда
			Комбинация =  Новый Массив;
		КонецЕсли;
		НоваяКомбинация = Новый Массив;
		Для Каждого Запись Из Комбинация Цикл
			НоваяКомбинация.Добавить(Запись);
		КонецЦикла;
		НоваяКомбинация.Добавить(слово);
		ВсеВозможныеКомбинации(массив, ВсеКомбинации, НоваяКомбинация);
		массив.Вставить(н,слово);
	КонецЦикла;
КонецПроцедуры
Показать
4. scientes 295 14.10.24 18:09 Сейчас в теме
Задача № 5.
Количество символов в ВЕРХНЕМ регистре. СтрДлина(СтрСоединить(СтрРазделить(ИсходнаяСтрока,нрег(ИсходнаяСтрока))))
Оставьте свое сообщение