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

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

В этой теме 1 ответ, 2 участника, последнее обновление  Васильев Владимир Сергеевич 1 год назад.

  • Автор
    Сообщения
  • #2634

    questioner
    Участник

    Нужно решить логическую задачу на visual 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; !.

Для ответа в этой теме необходимо авторизоваться.