Ответ в теме: Распределение актеров по ролям на Prolog

      Комментарии к записи Ответ в теме: Распределение актеров по ролям на Prolog отключены
#2638

Для начала надо описать типы данных – имя актера будет строкой, а тип актера будет представлять собой структуру (набор значений) из имени, роста, возраста, пола. Кроме того, т.к. роль должна содержать диапазоны допустимых параметров – нужно описать тип для таких диапазонов:

domains
	name_d = string
	sex_d = male;female
	growth_d = integer
	age_d = integer
	
	growth_range_d = range(growth_d, growth_d)
	age_range_d = range(age_d, age_d)
	
	role_d = role(name_d, sex_d, growth_range_d, age_range_d)
	actor_d = actor(name_d, sex_d, growth_d, age_d)
	
	actors_d = actor_d*
	roles_d = role_d*
	
	play_d = play(actor_d, role_d)
	plays_d = play_d*

Для проверки принадлежности числа диапазону нужно применить функцию in_range.
Мы будем перебирать актеров и роли таким образом, чтобы актер подошел на роль. При этом не важно имя актера или роли, но нужно проверить чтобы совпадал пол (если не задан – то успешно выполнится инициализация любым значением) и диапазоны роста и возраста были в требуемых пределах:

matching(actor(_, Sex, Growth, Age), role(_, Sex, GrowthRange, AgeRange)):-
  in_range(Growth, GrowthRange), 
  in_range(Age, AgeRange).

При переборе актеров и ролей мы должны удалять отобранные варианты из списка (иначе выйдет так, что один актер сможет играть все роли), поэтому мы применим функцию select:

matching(_Actors, [], []).
matching(Actors, Roles, [play(Actor, Role)|OtherPlays]):-
  select(Actor, Actors, OtherActors),
  select(Role, Roles, OtherRoles),
  matching(Actor, Role),
  matching(OtherActors, OtherRoles, OtherPlays).

Если список ролей кончился – функция возвращает пустой список. В остальных случаях функция выбирает (select) такого актера и роль, что они подходят друг другу, а остальные элемент обрабатывает рекурсивно. К результату рекурсивного вызова дописывается play(Actor, Role).

Возьмем, например, пьесу “Балаган” из трех действующих лиц и предположим, что у нас есть 5 актеров. Программа выведет нам все варианты распределения актеров по ролям:

goal
	Actors = [
		actor("Victor", male, 176, 23),
		actor("Iosif", male, 163, 18),
		actor("Vladimir", male, 200, 64),
		actor("Petr", male, 204, 56),
		actor("Alla", female, 140, 32),
		actor("Natalia", female, 156, 19)
	],
	
	Roles = [
		role("kolombina", female, range(150, 170), range(18, 30)),
		role("umnik", _, range(150, 190), range(20, 40)),
		role("durak", male, _, range(18, 30))
	],
	
	matching(Actors, Roles, Match),
	write(Match), nl, fail; !.