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

27.01.25

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

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

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

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


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

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

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

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


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

 
 Задача 1

 Платформа: CodeWars

 Название задачи: Polish alphabet (Польский алфавит)

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

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

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

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

There are 32 letters in the Polish alphabet: 9 vowels and 23 consonants.

Your task is to change the letters with diacritics:

ą -> a,
ć -> c,
ę -> e,
ł -> l,
ń -> n,
ó -> o,
"7; -> s,
%8; -> z,
&0; -> z
For example:
"Jędrzej Błądziński"  -->  "Jedrzej Bladzinski"

Пояснение:

В условиях задачи нам объясняют как устроен польский алфавит. Он содержит 9 гласных и 23 согласных буквы. Суть задачи в другом. Некоторое буквы в польском алфавите имеют Диакритические знаки, как например ą -> a.

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

Более чем понятно, даавайте попробуем решить:


Решение:

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

 АналогиБукв = Новый Соответствие;
АналогиБукв.Вставить("ą","a");
АналогиБукв.Вставить("ć","c");
АналогиБукв.Вставить("ę","e");
АналогиБукв.Вставить("ł","l");
АналогиБукв.Вставить("ń","n");
АналогиБукв.Вставить("ó","o");
АналогиБукв.Вставить(""7;","s");
АналогиБукв.Вставить("%8;","z");
АналогиБукв.Вставить("&0;","z");
//
ИсходнаяСтрока = "Jędrzej Błądziński";
Вывод = "";

Для НомерСимвола = 1 По СтрДлина(ИсходнаяСтрока) Цикл
	ТекущийСимвол = Сред(ИсходнаяСтрока,НомерСимвола,1);	
	Если АналогиБукв.Получить(ТекущийСимвол) <> Неопределено Тогда
		ТекущийСимвол = АналогиБукв.Получить(ТекущийСимвол);
	КонецЕсли;
	Вывод = Вывод + ТекущийСимвол;
КонецЦикла;

Результат:

Jedrzej Bladzinski

Как мы можем заметить, всё работает так как мы и ожидали. Познавательная задача про специальные символы в польском языке!

 
 Задача 2

 Платформа: CodeWars

 Название задачи: Simple Maths Test (Простая математическая проверка)

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

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

 Тэги: Алгоритмы, Математика

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

Create a function which checks a number for three different properties.

  • is the number prime?
  • is the number even?
  • is the number a multiple of 10?

Each should return either true or false, which should be given as an array. Remark: The Haskell variant uses data Property.

Examples:
number_property(7)  # ==> [true,  false, false] 
number_property(10) # ==> [false, true,  true] 

The number will always be an integer, either positive or negative. Note that negative numbers cannot be primes, but they can be multiples of 10:

number_property(-7)  # ==> [false, false, false] 
number_property(-10) # ==> [false, true,  true] 

Пояснение:

Суть задачи заключается в том чтобы написать функцию, которая проверяет данное число на то является ли это число:

1) Простым

2) Четным

3) Кратным 10

Также в условиях задачи поясняется что исходное значение всегда обязательно будет числом а также может быть положительным или отрицательным.

В качестве результата мы будем возвращать массив с результатами, которые будут являться значениями типа Булево!

Звучит просто, давайте попробуем решить задачу:


Решение:

Перед началом решения давайте сначала создадим массив, в который будем собирать результаты проверок. Далее чтобы решить задачу давайте разделить её на этапы проверки.

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

Для проверки второго условия нам достаточно проверить есть ли остаток от деления нашего числа на 2. Если остатка нет, значит оно четное, все просто.

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

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

Результат:

Да Нет Нет

Как можем видеть, задача решена успешно, результат именно тот, какой мы и ожидали. Идём дальше!

 
 Задача 3

 Платформа: CodeWars

 Название задачи: So Easy: Charge time calculation (Очень просто: Вычисление времени зарядки)

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

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

 Тэги: Головоломки

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

To charge your mobile phone battery, do you know how much time it takes from 0% to 100%? It depends on your cell phone battery capacity and the power of the charger. A rough calculation method is:
0% --> 85%  (fast charge)
(battery capacity(mAh) * 85%) / power of the charger(mA)

85% --> 95% (decreasing charge)
(battery capacity(mAh) * 10%) / (power of the charger(mA) * 50%)

95% --> 100% (trickle charge)
(battery capacity(mAh) * 5%) / (power of the charger(mA) * 20%)

For example: Your battery capacity is 1000 mAh and you use a charger 500 mA, to charge your mobile phone battery from 0% to 100% needs time:

Complete function calculateTime that accepts two arguments battery and charger, return how many hours can charge the battery from 0% to 100%. The result should be a number, round to 2 decimal places (In Haskell, no need to round it).

0% --> 85%  (fast charge) 1.7 (hour)

85% --> 95% (decreasing charge) 0.4 (hour)

95% --> 100% (trickle charge) 0.5 (hour)

total times = 1.7 + 0.4 + 0.5 = 2.6 (hour)

 

Пояснение:

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

1) Время зарядки от 0 до 85

2) Время зарядки от 85 до 95

3) Время зарядки от 95 до 100

Почему 3? Это связано с особенностью типа батарей, которые сейчас везде используются. Если интересно, можете посмотреть отрывок с Илоном Маском на подкасте Джо Рогана (Нажмите на строку), где он привёл интересную аналогию и объяснил, почему так происходит. Не суть важно, идём дальше. Вычислять время будем по заранее данной формуле, которая требует от нас умножить объем батареи на текущий порог (85, 10, 5) и разделить это на произведения мощности зарядного устройства на процент эффективности зарядки (для второго и третьего этапов зярядки).

Далее суммируем все три результата времени и выводим единым числом!

Думаю всем всё понятно, давайте попробуем решить:


Решение:

Решение будет максимально простым. Всё что от нас требуется так это повторить одну и ту же формулу 3 раза и каждый раз увеличивать результат Вывода.

В итоге получился вот такой код:

 ОбъемБатареи = 1000;
МощностьЗарядногоУстройства = 500;
Вывод = 0;
//
Вывод = Вывод + ((ОбъемБатареи * 0.85)/(МощностьЗарядногоУстройства));
Вывод = Вывод + ((ОбъемБатареи * 0.10)/(МощностьЗарядногоУстройства * 0.50));
Вывод = Вывод + ((ОбъемБатареи * 0.05)/(МощностьЗарядногоУстройства * 0.20));

Результат:

2.6

Интересная и познавательная задача с простым решением!

 
 Задача 4

 Платформа: CodeWars

 Название задачи: Special Number (Special Numbers Series #5) (Особенное число: Серия задач про особенные числа, пятая задача)

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

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

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

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

Definition

A number is a Special Number if its digits only consists of 0, 1, 2, 3, 4 or 5

Given a number, determine if it is a special number or not.


Notes

  • The number passed will be positive (N > 0)

  • All single-digit numbers within the interval [1:5] are considered special numbers



Example:
2 ==> return "Special!!"
Explanation: It's a single-digit number within the interval [1:5]

9 ==> return "NOT!!"
Explanation: Although, it's a single-digit number but Outside the interval [1:5]

23 ==> return "Special!!"
Explanation: All the number's digits formed from the interval [0:5] digits

39 ==> return "NOT!!"
Explanation: Although there is a digit (3) within the interval,
             the second digit is not (Must be ALL the number's Digits)

59 ==> return "NOT!!"
Explanation: Although there is a digit (5) within the interval,
             the second digit is not (Must be ALL the number's Digits)

513 ==> return "Special!!"

709 ==> return "NOT!!"

Пояснение:

Суть задачи заключается в том чтобы выяснить является ли данном нам число "Особенным". Что это значит? По условию задачи нам дано что любое число, которое составлено лишь с использованием чисел от 0 до 5, является "Особенным".

Например:

Число 2 особенное, соответствует условиям

Число 9 не является особенным

Число 23 является особенным

И так далее...

Суть думаю ясна. Давайте попробуем решить:


Решение:

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

 ИсходноеЧисло = 23;
РезультатПроверки = Истина;
//
Для НомерЭлемента = 1 По СтрДлина(Строка(ИсходноеЧисло)) Цикл
	Если Не (Число(Сред(Строка(ИсходноеЧисло),НомерЭлемента,1)) >= 0 И Число(Сред(Строка(ИсходноеЧисло),НомерЭлемента,1)) <= 5) Тогда
		РезультатПроверки = Ложь;
	КонецЕсли;
КонецЦикла;
//
Если РезультатПроверки Тогда
	Вывод = "Особенное";
Иначе
	Вывод = "Не особенное";
КонецЕсли;

Результат:

Особенное

Простая математическая задачка. В дальнейшем обязательно решим и другие задачи из этой серии!

 
 Задача 5

 Платформа: CodeWars

 Название задачи: Century From Year (Век из года)

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

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

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

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

Introduction

The first century spans from the year 1 up to and including the year 100, the second century - from the year 101 up to and including the year 200, etc.

Task

Given a year, return the century it is in.

Examples

1705 --> 18
1900 --> 19
1601 --> 17
2000 --> 20
2742 --> 28
Note: this kata uses strict construction as shown in the description and the examples, you can read more about it here

Пояснение:

Суть задачи заключается в том чтобы из данного нам года выяснить в какой век входит этот год.

Например:

1705-й год входит в 18-й век

1900-й год входит в 19-й век

1601-й год входит в 17-й век

2000-й год входит в 20-й век

2742-й год входит в 28-й век

Думаю всё просто, давайте попробуем решить:


Решение:

Для начала давайте разделим данный нам год на 100 и посмотрим есть ли там остаток. Если там остатка нет, значит век = исходный год / 100, если же есть остаток то снова же, делим без остатка и уже прибавляем единицу.

Например если дан год 1900 то 1900/100 = 19, это 19-й век. А вот если дан год 1901 то остаток 01, сбрасываем остаток и прибавляем 1, получаем 20-й век.

Вот какой в итоге получился код:

 ИсходныйГод = 1901;
//
Если ИсходныйГод % 100 = 0 Тогда
	Вывод = ИсходныйГод / 100;
Иначе
	Вывод = Окр((ИсходныйГод/100))+1;
КонецЕсли;

Результат:

20

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

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

Заключение:

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

Подключайтесь к решению алгоритмических задач вместе со мной, делитесь вашим мнением и решениями в комментариях! Увидимся в новой статье!

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

См. также

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

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

1 стартмани

30.01.2024    4944    stopa85    12    

39

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

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

19.10.2023    9949    user1959478    54    

37

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

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

2 стартмани

29.09.2023    4788    maksa2005    8    

26

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

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

1 стартмани

09.06.2023    12512    8    SpaceOfMyHead    20    

62

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

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

03.04.2023    6038    RustIG    9    

25

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

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

23.11.2022    5148    gzharkoj    14    

25

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

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

1 стартмани

21.03.2022    9402    7    kalyaka    11    

44
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. SerVer1C 862 27.01.25 15:12 Сейчас в теме
Лучше бы разработали что-то более практичное, например, RSA алгоритм шифрования на чистом 1с - было бы гораздо больше пользы.
TheNabiulla; +1 Ответить
2. TheNabiulla 87 27.01.25 16:32 Сейчас в теме
(1) Дойду и до него)
abasovit; SerVer1C; +2 Ответить
3. Sashares 35 27.01.25 17:16 Сейчас в теме
Зачем в 1 задаче по очереди проверять каждый символ? А если во входящей строке это война и мир?
Почему не заменить сразу символы во всей строке через СтрЗаменить?
RocKeR_13; TheNabiulla; +2 Ответить
4. TheNabiulla 87 27.01.25 17:20 Сейчас в теме
(3) Не подумал об этом. Действительно, стоило учесть возможный объём исходной строки. Благодарю за совет!
5. Sashares 35 27.01.25 17:21 Сейчас в теме
Задача 2 - число N = 1000000000000. Ваш цикл будет пытаться делить с 2 по N-1. Зачем?
Если на 2 уже разделил, и результат ложь - зачем дальше делить?

В 4 - аналогично - умейте вовремя прерваться.
TheNabiulla; +1 Ответить
6. TheNabiulla 87 27.01.25 17:24 Сейчас в теме
(5) Имеете ввиду что нет смысла проверять на кратность 10 если число итак не кратно 2? Да, вы правы, надо было лишнее деление убрать. Учту в следующий раз
7. Sashares 35 27.01.25 17:27 Сейчас в теме
(6) Имею в виду что у вас цикл будет проходить каждый раз по "ИсходноеЗначение - 1".
Цикл не прерывается, если проверка сработала, и условию установилась Ложь.
Если условие сработало, зачем проверять дальше?

 Для ТекущееЧисло = 2 По ИсходноеЗначение - 1 Цикл
		Если ИсходноеЗначение % ТекущееЧисло = 0 Тогда
			Вывод[0] = Ложь;
		КонецЕсли;
	КонецЦикла;


Остальные проверки не так критичны по времени/ресурсам.
TheNabiulla; +1 Ответить
8. TheNabiulla 87 27.01.25 17:29 Сейчас в теме
(7) Ааа, теперь понял о чем вы. Да, надо было прерывание добавить
9. TheNabiulla 87 27.01.25 17:30 Сейчас в теме
(7) Благодарю за советы!
10. Sashares 35 27.01.25 17:32 Сейчас в теме
Задача 4.
ЧислоСтрокой = Формат(Число, "ЧГ=");
Массив = СтрРазделить(ЧислоСтрокой , "012345",Ложь);
РезультатПроверки = (Массив.Количество() = 0);
TheNabiulla; +1 Ответить
11. Alonarista 62 27.01.25 21:10 Сейчас в теме
Вы уж простите, но ваши решения больше вредят молодому поколению, чем учат их чему либо.
Ваше решение по простым числам - ужас и мрак для больших простых чисел.
Почитайте про решето Эратосфена и малую теорему Ферма.
RocKeR_13; SerVer1C; +2 Ответить
12. TheNabiulla 87 27.01.25 23:16 Сейчас в теме
(11) Обязательно почитаю, благодарю за подсказку. Что касаемо вреда могу сказать что каждый может думать своей головой, мои решения не обязательно должны быть эталоном и примером для кого нибудь (На том же кодварсе на одну задачу тысячи разных решений). Целью статьи изначально является общение с другими разработчиками, обмен опытом и просто забава. Вы и сами поделились со мной опытом, дали интересную наводку, другие тоже это увидят, думаю все довольны)
13. RocKeR_13 1379 28.01.25 14:16 Сейчас в теме
Прошу прощения, но кто является целевой аудиторией данных публикаций с вашей точки зрения? Задача на замену символов в строке? Задача на проверку цифр в числе? На получение остатка от деления? У вас примеры больше похожи на проверку знаний синтаксиса среды разработки/языка программирования. К тому же местами с непродуманным решением, о чем уже отписались в комментариях выше. Ну возьмите вы какой-нибудь учебник с интересными алгоритмами для других языков программирования, например. Или учебник по численным методам. Будет всяко интересно. В свое время тоже развлекался, писал аппроксимацию функции полиномом n-ой степени с решением СЛАУ методом Гаусса-Зейделя с указанной погрешностью: пользы особой не было, но было хотя бы интересно самому сделать.
14. RailMen 829 28.01.25 15:16 Сейчас в теме
Спасибо, я как раз думал как детей приучать к 1С.
Простые задачки как раз у детей вызывают интерес.
Вообще нужна рубрика "Детям" (есть "Реальные кабаны 1С" , хотелось бы и "Кабанчики 1С" :) :) :)


И небольшое замечание к строкам:
Если АналогиБукв.Получить(ТекущийСимвол) <> Неопределено Тогда
ТекущийСимвол = АналогиБукв.Получить(ТекущийСимвол);
КонецЕсли;

Дважды вызывается
АналогиБукв.Получить(ТекущийСимвол)

Вызывайте один раз и записывайте в переменную.
Оставьте свое сообщение