Algo1C: Решение алгоритмических задач на базе 1С: Предприятие [Часть #0]

19.09.24

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

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

Йо, меня зовут Наби, мне 23 года. Заранее благодарю за чтение и желаю продуктивно провести время! Если после прочтения возникнут вопросы, пожелания или предложения, то буду рад ознакомиться со всем в комментариях!


Предисловие

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

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

И, собственно, вот так я и пришёл к решению начать эту рубрику статей, в которой я буду рассказывать о своем опыте, о новых вещах, которые сам выучил в процессе решения задач, объяснять их решения (насколько буду в состоянии это сделать). Плюс хочется, чтобы и другие смогли присоединиться ко мне, поделиться своим опытом и высказать свои мысли и идеи!


Выбор платформы с задачами

В первую очередь на глаза попалась платформа LeetCode.

Если почитать Вики, то можно понять, что основное предназначение платформы это подготовка к техническим интервью и развитие навыков программирования.

 

 

Задач огромное количество на абсолютно разные тематики, они же тут являются Тэгами

 

 

Языков программирования тоже очень много. Конкретно я использовал Python, когда тестировал платформу.

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

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

 

 

На этом в принципе всё, что-то дополнительно выделить нечего!

Вторым сервисом, который я выбрал, является CodeWars

 

 

В отличие от предыдущего сервиса, CodeWars не подразумевает подготовку к интервью. Оно также бросается в глаза, когда понимаешь отсутствие возможности фильтровать по компаниям, как это было у предыдущего сервиса.

Из примечательного стоит выделить огромное количество и разнообразие тэгов, наверное, в несколько раз больше чем у предыдущего сервиса

 

 

Ну и, конечно, самая интересная деталь это система оценки твоих навыков. Тут единицей измерения скилла является так называется Честь (Honor), на основании которой рассчитывается твой Ранг. Задача, она же проблема, тут называется по другому, интересное слово "Ката". Я полагаю, это отсылка к Дзюдо или Карате, где также используется это слово для описания уровня упражнений.

Что касаемо рангов, тут их восемь

 

 

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


Где будем решать и тестировать задачи?

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

Вот страница проекта на Github (нажмите на выделенный текст), можете заранее добавить себе в избранное, чтобы не потерять и в дальнейшем следить за обновлениями.

На данном этапе конфигурация представляет из себя обычную форму с двумя многострочными полями и кнопкой для запуска кода

 

 

Принцип работы на данном этапе максимально простой, кнопка отправляет строку из поля "Код" на серверную функцию, которая выполняет код и возвращает результат

//Код кнопки
РезультатИсполнения = РаботаСКодомСервер.ИсполнитьКод(Код);
Вывод = РезультатИсполнения.Вывод;
ВремяИсполненияСтрока = Строка((РезультатИсполнения.ВремяКонец - РезультатИсполнения.ВремяНачало)/1000) + " сек.";
ПредупреждениеАсинх(ВремяИсполненияСтрока,0,"Время исполнения");
//Функция исполнения кода в общем серверном модуле
Функция ИсполнитьКод(Код) Экспорт
	Результат = Новый Структура;
	//
	Попытка
		Результат.Вставить("ВремяНачало",ТекущаяУниверсальнаяДатаВМиллисекундах());
		//
		Вывод = Неопределено;
		Выполнить(Код);
		//
		Результат.Вставить("ВремяКонец",ТекущаяУниверсальнаяДатаВМиллисекундах());
		Результат.Вставить("Вывод",Вывод);
	Исключение
		Результат.Вставить("Вывод",ИнформацияОбОшибке().Причина.Описание);
	КонецПопытки;
	//
	Возврат Результат;
КонецФункции

Как видим, код выполняется, считается время исполнения и затем возвращается результат, который выводится на второе поле на форме. Главное - записать результат выполнения кода в переменную "Вывод".

Попробуем выполнить что-нибудь:

 

 

Как видим, цикл исполнился, последнее значения записалось в переменную "Вывод", и данные из этой переменной отправились на форму. Ну и затем вывелось предупреждение со временем исполнения. Само собой, время исполнения может быть разное относительно каждого компьютера, поэтому единственный способ оценить эффективность решения - это сравнить собственные решения на своём же компьютере. Возможно, в будущем придумаем какое-нибудь серверное решение для сравнения результатов друг друга!

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


Задачи и их решения

 
 Задача 1

Платформа: LeetCode

Название задачи: Two Sum

Ссылка на задачу: https://leetcode.com/problems/two-sum/description/


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

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

You can return the answer in any order.

 

Example 1:

Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].

Example 2:

Input: nums = [3,2,4], target = 6
Output: [1,2]

Example 3:

Input: nums = [3,3], target = 6
Output: [0,1]

 

Constraints:

    2 <= nums.length <= 104
    -109 <= nums[i] <= 109
    -109 <= target <= 109
    Only one valid answer exists.

 
Follow-up: Can you come up with an algorithm that is less than O(n2) time complexity?

В чём суть? Дан неупорядоченный массив из чисел (Nums) и одно целевое число (Target). Нужно в этом массиве найти 2 элемента, сумма которых даст целевое число. Результатом должен быть массив из двух индексов элементов оригинального массива

Решение

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

ОригинальныйМассив = Новый Массив;
ОригинальныйМассив.Добавить(3);
ОригинальныйМассив.Добавить(2);
ОригинальныйМассив.Добавить(4);
ЦелевоеЧисло = 6;
//
ПервыйИндекс = Неопределено;
ВторойИндекс = Неопределено;
//
Для НомерСтроки = 1 По ОригинальныйМассив.Количество() Цикл
	Для НомерПодСтроки = 1 По ОригинальныйМассив.Количество() Цикл
		Если НомерСтроки <> НомерПодСтроки Тогда
			Если ОригинальныйМассив[НомерСтроки-1] + ОригинальныйМассив[НомерПодСтроки-1] = ЦелевоеЧисло Тогда
				ПервыйИндекс = НомерПодСтроки-1;
				ВторойИндекс = НомерСтроки-1;
				Прервать;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
КонецЦикла;
//
Вывод = "["+Строка(ПервыйИндекс)+","+Строка(ВторойИндекс)+"]";

В итоге получился вот такой код. Все входные данные из описания успешно проходятся, ответы соответствуют ответам из примера!

Для дополнительной проверки советую попробовать с рандомными массивами!

 
 Задача 2

 

Платформа: LeetCode

Название задачи: Two Numbers

Ссылка на задачу: https://leetcode.com/problems/add-two-numbers/


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

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

 

Example 1:

Input: l1 = [2,4,3], l2 = [5,6,4]
Output: [7,0,8]
Explanation: 342 + 465 = 807.

Example 2:

Input: l1 = [0], l2 = [0]
Output: [0]

Example 3:

Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
Output: [8,9,9,9,0,0,0,1]

 

Constraints:

    The number of nodes in each linked list is in the range [1, 100].
    0 <= Node.val <= 9
    It is guaranteed that the list represents a number that does not have leading zeros.

В чём суть? Объясняю. Даны 2 числовых массива, каждый элемент массива может быть только простой цифрой от 1 до 9.

Каждый массив представляет собой перевёрнутое число разбитое на элементы. Например, если дан массив [2, 4, 3] то это означает, что изначально это было число 342. Также и со вторым массивом. Так вот, суть задачи заключается в том чтобы привести эти массивы к исходным формам, прибавить друг к другу и после выполнить те же операции с новым числом. То есть обратить его, разбить на элементы и занести в массив. Ну что ж, начнём?

Решение

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

ПервыйМассив = Новый Массив;
ПервыйМассив.Добавить(2);
ПервыйМассив.Добавить(4);
ПервыйМассив.Добавить(3);
//
ВторойМассив = Новый Массив;
ВторойМассив.Добавить(5);
ВторойМассив.Добавить(6);
ВторойМассив.Добавить(4);
//
ТретийМассив = Новый Массив;
//
ПервоеЧисло = "";
ВтороеЧисло = "";
//
Для НомерСтроки = 1 По ПервыйМассив.Количество() Цикл
	ПервоеЧисло = ПервоеЧисло + Строка(ПервыйМассив[ПервыйМассив.Количество() - НомерСтроки]);
КонецЦикла;
//
Для НомерСтроки = 1 По ВторойМассив.Количество() Цикл
	ВтороеЧисло = ВтороеЧисло + Строка(ВторойМассив[ВторойМассив.Количество() - НомерСтроки]);
КонецЦикла;
//
ТретьеЧисло = Строка(Число(ПервоеЧисло) + Число(ВтороеЧисло));
//
Для НомерСтроки = 1 По СтрДлина(ТретьеЧисло) Цикл
	ТретийМассив.Добавить(Сред(ТретьеЧисло,СтрДлина(ТретьеЧисло) - НомерСтроки+1,1));	
КонецЦикла;
//
Вывод = "[";
Для Каждого Стр Из ТретийМассив Цикл
	Вывод = Вывод + Строка(Стр) + ","; 	
КонецЦикла;
//
Вывод = Лев(Вывод,СтрДлина(Вывод)-1);
Вывод = Вывод + "]"

В итоге получился вот такой код. Все входные данные из описания успешно проходятся, ответы соответствуют ответам из примера!

Для дополнительной проверки советую попробовать с рандомными массивами!


Заключение

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

Конфигурация Алгоритмы LeetCode CodeWars

См. также

Математика и алгоритмы Программист Платформа 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. dmpas 418 19.09.24 12:12 Сейчас в теме
2. TheNabiulla 78 19.09.24 12:44 Сейчас в теме
(1) О, благодарю, обязательно гляну! Не знал что такое есть. Возможно все следующие задачки уже там буду решать!
3. Alexkonrad 20.09.24 09:47 Сейчас в теме
(1) Ого, спасибо. Не знал про этот ресурс.
TheNabiulla; +1 Ответить
4. TheNabiulla 78 20.09.24 12:42 Сейчас в теме
5. dmpas 418 22.09.24 13:42 Сейчас в теме
ну и позвольте старпёру упомянуть нашу родную классику: https://acm.timus.ru/
TheNabiulla; +1 Ответить
6. TheNabiulla 78 23.09.24 11:36 Сейчас в теме
(5) Хах, ничего себе. Да этот сайт старше меня самого XD
Обязательно возьму задачи оттуда, спасибо большое!
7. AzagTot 41 28.09.24 10:11 Сейчас в теме
Задачу № 1 можно существенно улучшить по времени.
Вместо "Для НомерПодСтроки = 1 По ОригинальныйМассив.Количество() Цикл"
я бы использовал "Для НомерПодСтроки = НомерСтроки+1 По ОригинальныйМассив.Количество()-1 Цикл"
убрал бы сравнение "Если НомерСтроки <> НомерПодСтроки Тогда"
и нумерацию в циклах начинал бы с 0, тогда при указании индекса не нужно было бы вычитать из счётчика цикла 1.
В итоге получается:
ОригинальныйМассив = Новый Массив;
ОригинальныйМассив.Добавить(3);
ОригинальныйМассив.Добавить(2);
ОригинальныйМассив.Добавить(4);
ЦелевоеЧисло = 6;
//
ПервыйИндекс = Неопределено;
ВторойИндекс = Неопределено;
//
Для НомерСтроки = 0 По ОригинальныйМассив.Количество()-1 Цикл
Для НомерПодСтроки = НомерСтроки+1 По ОригинальныйМассив.Количество()-1 Цикл
Если ОригинальныйМассив[НомерСтроки] + ОригинальныйМассив[НомерПодСтроки] = ЦелевоеЧисло Тогда
ПервыйИндекс = НомерПодСтроки;
ВторойИндекс = НомерСтроки;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
//
Вывод = "["+Строка(ПервыйИндекс)+","+Строка(ВторойИндекс)+"]";
8. AzagTot 41 28.09.24 10:57 Сейчас в теме
По второй задаче.
Наби, неужели ничего не торкнуло при прочтении условия задачи?
Это же демонстрация сложения чисел в столбик. Так детей учат считать в начальной школе.

Input: l1 = [2,4,3], l2 = [5,6,4]
Output: [7,0,8]
Explanation: 342 + 465 = 807.

Берём из первого массива первое число 2 и из второго массива первое число 5, складываем их, получаем 7. Записываем 7 в массив-результат.
Далее, вторые числа 4 + 6 = 10. Записываем 0 в результат, 1 держим в уме.
Далее, третьи числа 3 + 4 + 1 (который в уме) = 8. Записали 8 в результат.
Всё, числа в массивах закончились. Получили результат [7,0,8].

Ещё и условия неправильно перевели. Цифры в исходных массивах не от 1 до 9, а от 0 до 9. И гарантируется, что список представляет число, у которого нет начальных нулей.

Наби, вы ходили в начальную школу? Там ещё девчонок за косички дёргают и т.п. ;-)
Оставьте свое сообщение