Задача Плитки шоколада (проект 1С:Турниры)

19.08.24

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

Разбор задачи из проекта 1С:Турниры

На Infostart уже было несколько статей, посвященных платформе для решения задач на языке 1С. Я хочу разобрать задачу, которая входит в сборник заданий и называется Плитки шоколада. Условие следующее.

Шоколадная фабрика производит необычный шоколад.
Плитки шоколада выпускаются в виде длинных плиток 1 × N, состоящих из N квадратов.
На каждом квадрате изображен портрет одного из N известных кондитеров этой компании.
На разных плитках шоколада изображены одни и те же портреты N кондитеров, но в разном порядке.
 
Задача:
Напишите функцию, которая для заданного порядка портретов двух плиток шоколада определяет минимальное количество разломов,
которое нужно выполнить на первой плитке, чтобы сформировать вторую плитку, переставив сломанные части.
 
Дано:
Первая, Вторая - строка, описывающая каждую из плиток шоколада.
Состоит из массива целых чисел от 1 до N, разделенных запятой. Каждое число уникально, оно обозначает соответствующего кондитера.
 
Результат:
Целое число — минимальное количество разломов, которое нужно выполнить на первой плитке, чтобы сформировать вторую плитку, переставив и соединив сломанные части.
 
Ограничение:
Разломать плитку можно только по границам ее квадратов.
Переворачивать исходную плитку или ее части нельзя.
Порядок кондитеров в первой и второй плитке всегда отличается.
2 <= N <= 1000.
 
Пример:
Первая = "4,3,2,5,1"
Вторая = "1,2,5,3,4"
Результат = 3
 
Пояснение: первую плитку нужно разломать 3 раза на части: "1", "2,5", "3", "4".
А потом соединить полученные части, чтобы получить вторую плитку.

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

4,3,2,5,1

1,2,5,3,4

счетчик=0

После первого шага:

3,2,5,1

1,2,5,3,0

счетчик=1

После второго шага:

2,5,1

1,2,5,0,0

счетчик=2

После третьего шага:

1

1,0,0,0,0

счетчик=3

Осталась одна плитка, ничего ломать не надо. Алгоритм заканчивается. Ответ:3 Следующий программный код реализует изложенный подход.

Функция ПлиткиШоколада(Первая, Вторая)    
      Стр1=СтрРазделить(Первая,","); //преобразуем исходные строки в массивы
	Стр2=СтрРазделить(Вторая,",");
	Стр2.Добавить(0); //ограничительный элемент, чтобы не проверять размер массива Стр1 
	ответ=0;
	пока Стр1.Количество()>0 цикл
		б=Стр1[0]; //номер портрета из первой плитки
		старт=Стр2.Найти(б); // позиция этого портрета во второй плитке
		для i=старт по Стр2.ВГраница() цикл 
			если Стр2[i]=0 или Стр1[0]<>Стр2[i] тогда
		      прервать;
			иначеесли Стр1[0]=Стр2[i] тогда
				Стр1.Удалить(0); //удалим обработанную ячейку из первой плитки, чтобы не делать цикл
				Стр2[i]=0; //это можно не делать
			конецесли;	
		конеццикла;	
        //если в первой плитке остались ячейки добавляем к счетчмку 1
		ответ=ответ+(Стр1.Количество()>0); //неявное преобразование булево в число
	конеццикла;	
	возврат ответ;
КонецФункции

Можно поступить немного иначе. Исходные данные - это набор чисел от 1 до N, которые расположены в произвольном порядке. Занесем сведения по второй плитке в массив, где индекс массива это номер ячейки, а значение массива - позиция в массиве, который получается при использовании метода СтрРазделить(...). Ниже приводится соответствующий код.

словарь=новый массив(Вычислить("макс("+Вторая+")")+1);
ном=0;
для каждого запись из СтрРазделить(Вторая,",") цикл
	словарь[число(запись)]=ном;
	ном=ном+1;
конеццикла;	

Размер массива мы получаем с помощью метода Вычислить и функции макс(...). Тогда данные (1,2,5,3,4) из рассмотренного выше примера образуют следующий массив:

словарь[1]=0;
словарь[2]=1;
словарь[5]=2;
словарь[3]=3;
словарь[4]=4;

Теперь пройдемся по массиву ячеек первой плитки. 

ответ=-1;пред=ном+2;
для каждого запись из СтрРазделить(Первая,",") цикл
   тек=словарь[число(запись)];
   если (тек-пред)<>1 тогда
	 ответ=ответ+1;
   конецесли;
   пред=тек; 
конеццикла;

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

В заключении хочу порекомендовать всем, кто интересуется спортивным программированием,  присоединиться к участникам проекта 1С:Турниры. К настоящему моменту проект содержит более 460 задач различной сложности и позволяет развить навыки работы с объектами и методами языка 1С.

См. также

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

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

1 стартмани

30.01.2024    3457    stopa85    12    

38

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

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

19.10.2023    7949    user1959478    52    

36

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

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

2 стартмани

29.09.2023    3395    maksa2005    8    

26

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

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

1 стартмани

09.06.2023    11149    8    SpaceOfMyHead    19    

61

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

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

03.04.2023    4649    RustIG    9    

25

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

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

23.11.2022    3807    gzharkoj    14    

25

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

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

1 стартмани

21.03.2022    9093    7    kalyaka    11    

44
Оставьте свое сообщение