Гуру тест про порядок элементов в иерархии

1. fixin 4282 23.12.24 21:27 Сейчас в теме
Есть красивая задача с элегантным решением. Делюсь, разомните мозги. Первый, кто решит еще и 1СМ получит в качестве награды за интеллект..

Есть некоторый иерархический справочник, иерархия элементов. У каждого элемента есть поле «Позиция» (может быть дробным и отрицательным). Элементы в пределах одного родителя должны быть пронумерованы в поле «Позиция» по порядку с единицы с шагом один: 1, 2, … N

Таким образом, например, чтобы поменять порядок элементов с позициями 2 и 3 мы можем элементу с позицией 2 установить позицию 2,5 и вызвать процедуру исправления порядка.

Не буду давать подсказки и наводящие мысли, просто жду от вас идей оптимальной реализации алгоритма проверки и изменения порядка. Это гуру-тест, который, кстати, можно давать на собеседованиях.

Пример: в группе с названием Алкоголь есть элементы с позициями:

Пиво 1
Водка 2
Эль 3
Я меняю:

Пиво 2.5
Водка 2
Эль 3
Система должна пересчитать по всей номенклатуре и сделать:

Водка 1
Пиво 2
Эль 3
Причем найти отклонения и сделать изменения максимально эффективно.

По сути можно упростить вопрос — как запросом найти группы, где порядок 1, 2, … N нарушен?

Вот еще пример:

Есть группа Алкоголь 1, в ней элементы:
Водка 2
Пиво 2.5
Эль 3
Есть группа Мясное 2, в ней элементы:
Сосиски 3
Ветчина 5
Есть группа Напитки 3, в ней элементы:
Квас 1
Сок 2

Нужно по этому пример найти запросом группы, где нарушен порядок 1, 2, N.
Правильный ответ: Алкоголь, Мясное.
Неправильные ответы: Напитки, Корень.
По теме из базы знаний
Вознаграждение за ответ
Показать полностью
Найденные решения
5. fixin 4282 24.12.24 13:42 Сейчас в теме +1 $m
Задачу уже решили на Мисте.
Потому снимаю вознаграждение.
Вот решение:
Функция УточнитьПорядокЗадач()
	З = Новый Запрос(
	"ВЫБРАТЬ
	|	Т.Родитель КАК Родитель,
	|	КОЛИЧЕСТВО(*) КАК Количество,
	|	СУММА(Т.Позиция) КАК СуммаПозиции
	|ПОМЕСТИТЬ ТГруппы
	|ИЗ
	|	Справочник.БС_Задачи КАК Т
	|
	|СГРУППИРОВАТЬ ПО
	|	Т.Родитель
	|
	|ИМЕЮЩИЕ
	|	(1 + КОЛИЧЕСТВО(*)) * КОЛИЧЕСТВО(*) / 2 <> СУММА(Т.Позиция)
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	Т.Ссылка КАК Ссылка,
	|	Т.Ссылка.Позиция КАК Позиция,
	|	Т.Родитель КАК Родитель
	|ИЗ
	|	Справочник.БС_Задачи КАК Т
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТГруппы КАК ТГРуппы
	|		ПО Т.Родитель = ТГРуппы.Родитель
	|
	|УПОРЯДОЧИТЬ ПО
	|	Позиция
	|ИТОГИ ПО
	|	Родитель");
	Выборка = З.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
	Пока Выборка.Следующий() Цикл
		ВыборкаПозиций = Выборка.Выбрать();
		Позиция = 0;
		;//Сообщить("Проверем группу: " + Выборка.Родитель);
		Пока ВыборкаПозиций.Следующий() Цикл
			Позиция = Позиция + 1;
			//Если позиция поменялась, тогда записываем
			Если ВыборкаПозиций.Позиция <> Позиция Тогда
				;//Сообщить("" + ВыборкаПозиций.Ссылка + ":  "+ ВыборкаПозиций.Позиция + " -> " + Позиция);
				ОО = ВыборкаПозиций.Ссылка.ПолучитьОбъект();
				ОО.Позиция = Позиция;
				ОО.Записать();
			КонецЕсли;
	КонецЦикла;
		
	
	КонецЦикла;
КонецФункции

Показать
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. Fox-trot 164 23.12.24 21:47 Сейчас в теме
этот алгоритм есть в каждом коммунальном биллинге с маршрутами раздачи квитанций
3. fixin 4282 23.12.24 21:50 Сейчас в теме
(2) не нужно лишних аналогий. Просто озвучьте принцип.
4. пользователь 23.12.24 23:01
Сообщение было скрыто модератором.
...
5. fixin 4282 24.12.24 13:42 Сейчас в теме +1 $m
Задачу уже решили на Мисте.
Потому снимаю вознаграждение.
Вот решение:
Функция УточнитьПорядокЗадач()
	З = Новый Запрос(
	"ВЫБРАТЬ
	|	Т.Родитель КАК Родитель,
	|	КОЛИЧЕСТВО(*) КАК Количество,
	|	СУММА(Т.Позиция) КАК СуммаПозиции
	|ПОМЕСТИТЬ ТГруппы
	|ИЗ
	|	Справочник.БС_Задачи КАК Т
	|
	|СГРУППИРОВАТЬ ПО
	|	Т.Родитель
	|
	|ИМЕЮЩИЕ
	|	(1 + КОЛИЧЕСТВО(*)) * КОЛИЧЕСТВО(*) / 2 <> СУММА(Т.Позиция)
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	Т.Ссылка КАК Ссылка,
	|	Т.Ссылка.Позиция КАК Позиция,
	|	Т.Родитель КАК Родитель
	|ИЗ
	|	Справочник.БС_Задачи КАК Т
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТГруппы КАК ТГРуппы
	|		ПО Т.Родитель = ТГРуппы.Родитель
	|
	|УПОРЯДОЧИТЬ ПО
	|	Позиция
	|ИТОГИ ПО
	|	Родитель");
	Выборка = З.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
	Пока Выборка.Следующий() Цикл
		ВыборкаПозиций = Выборка.Выбрать();
		Позиция = 0;
		;//Сообщить("Проверем группу: " + Выборка.Родитель);
		Пока ВыборкаПозиций.Следующий() Цикл
			Позиция = Позиция + 1;
			//Если позиция поменялась, тогда записываем
			Если ВыборкаПозиций.Позиция <> Позиция Тогда
				;//Сообщить("" + ВыборкаПозиций.Ссылка + ":  "+ ВыборкаПозиций.Позиция + " -> " + Позиция);
				ОО = ВыборкаПозиций.Ссылка.ПолучитьОбъект();
				ОО.Позиция = Позиция;
				ОО.Записать();
			КонецЕсли;
	КонецЦикла;
		
	
	КонецЦикла;
КонецФункции

Показать
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот