#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
struct Rule { // правило:
string part1 = ""; // условная часть
string part2 = ""; // исполняемая часть
bool use = true; // флаг использования
};
const char chAnd = ','; // разделитель "И"
Rule Rules[100]; // база правил
string WorkMem[100]; // рабочая память
string Goals[100]; // цели для обратного вывода
int nf = 0; // счетчик фактов в памяти
int nr = 0; // счетчик правил
int ng = 0; // счетчик целей для обратного вывода
////////////////////////////////////////////////////////////////
// Вспомогательные функции //
////////////////////////////////////////////////////////////////
string Trim(string s) // Обрезка пробелов в начале и конце
{
while (s.length() > 0 && s[0] == ' ') s = s.erase(0, 1);
while (s.length() > 0 && s[s.length() - 1] == ' ')
s = s.erase(s.length() - 1, 1);
return s;
}
string GetFact(string& s) // Выделение факта из списка
{
string v; // выделенный факт
int j = s.find(chAnd);
if (j < 0) {
v = s; s = "";
}
else {
v.assign(s, 0, j); s = s.erase(0, j + 1);
}
return v;
}

7

////////////////////////////////////////////////////////////////
// Функции работы с рабочей памятью //
////////////////////////////////////////////////////////////////
bool IsFact(string s) // Проверка наличия факта в рабочей памяти
{
s = Trim(s);
bool res = false; // результат
for (int i = 0; i < nf; i++)
if (WorkMem[i] == s) res = true;
return res;
}
bool IsTrue(string s) // Проверка истинности выражения
{
bool res = false; // результат
bool first = true; // флаг первого факта
while (s != "") {
// проверка истинности текущего факта
bool tres = IsFact(GetFact(s));
// накопление результата
if (first) {
res = tres; first = false;
}
else res = res && tres;
}
return res;
}
void AddFact(string sf) // Добавление факта
{
sf = Trim(sf);
if (!IsFact(sf)) {
WorkMem[nf] = sf; nf++;
}
}
void AddFacts() // Добавление фактов
{
bool fNext = true; // флаг продолжения ввода
string sf; // новый факт
cin.ignore();
do {
cout << ">> "; getline(cin, sf);
if (sf != "") {
fNext = true; AddFact(sf);
}
else fNext = false;
} while (fNext);
}

8
void ShowFacts() // Показ рабочей памяти
{
string sf; // новый факт
cout << endl << "Состояние рабочей памяти: " << endl;
if (nf == 0) cout << "Рабочая память пуста" << endl;
else {
for (int i = 0; i < nf; i++)
cout << i + 1 << ". " << WorkMem[i] << endl;
}
cout << endl; system("pause");
}
////////////////////////////////////////////////////////////////
// Функции работы с правилами //
////////////////////////////////////////////////////////////////
void AddRules() // Добавление правил
{
bool fNext = true; // флаг продолжения ввода
string sr1 = ""; // условная часть правила
string sr2 = ""; // выполняемая часть правила
cin.ignore();
do {
cout << "ЕСЛИ "; getline(cin,sr1);
if (sr1 != "") {
cout << "ТО "; getline(cin,sr2);
fNext = true;
Rules[nr].part1 = Trim(sr1);
Rules[nr].part2 = Trim(sr2);
Rules[nr].use = true;
nr++;
}
else fNext = false;
} while (fNext);
}
void ShowRules() // Показ правил
{
string sf; // новый факт
char suse; // символ использования правила
cout << "\nПравила: \n";
if (nr == 0) cout << "Правил нет" << endl;
else {
for (int i = 0; i < nr; i++) {
if (Rules[i].use) suse = '+'; else suse = '-';
cout << i + 1 << ". " << suse << " ЕСЛИ "
<< Rules[i].part1

<< " ТО " << Rules[i].part2 << endl;

}
}
cout << endl; system("pause");
}

9

bool TestRule(int r) // Проверка исполнения правила номер r
{
bool res = false; // флаг срабатывания правила
if (Rules[r].use && IsTrue(Rules[r].part1)) {
AddFact(Rules[r].part2);
Rules[r].use = false;
res = true;
}
return res;
}
////////////////////////////////////////////////////////////////
// Функции работы с целями //
////////////////////////////////////////////////////////////////
bool IsGoal(string s) // Проверка наличия цели s
{
s = Trim(s);
bool res = false; // результат
for (int i = 0; i < ng; i++) if (Goals[i] == s) res = true;
return res;
}
void AddGoal(string s) // Добавление цели
{
s = Trim(s);
if ((s !="") && (!IsGoal(s))) {
Goals[ng] = s; ng++;
}
}
void InputGoal() // Ввод цели
{
string s = ""; // цель
ng = 0; // нет целей
cin.ignore(); cout << endl << "Цель: "; getline(cin, s);
AddGoal(s);
}
void AddGoals(string s) // Добавление новых целей
{
while (s != "") AddGoal(GetFact(s));
}
void ConfirmGoal() // Подтверждение цели
{
if (ng > 0 && Goals[0] != "") {
if (IsTrue(Goals[0])) cout << "Цель подтверждена" << endl;
else cout << "Цель не подтверждена" << endl;
cout << endl; system("pause");
}
}

10

////////////////////////////////////////////////////////////////
// Функции логического вывода //
////////////////////////////////////////////////////////////////
void Find() // Механизм прямого логического вывода
{
bool fNext; // флаг продолжения поиска
InputGoal(); // ввод цели
do {
fNext = false;
for (int r = 0; r < nr; r++)
if (TestRule(r)) fNext = true;
} while (fNext);
ConfirmGoal(); // подтверждение цели
}
void BackFind() // Механизм обратного логического вывода
{
bool fNext; // флаг продолжения поиска
InputGoal(); // ввод цели
do {
fNext = false;
for (int g = 0; g < ng; g++) {
for (int r = 0; r < nr; r++)
if (Rules[r].use && Rules[r].part2 == Goals[g]) {
// формирование новых целей
AddGoals(Rules[r].part1);
// проверка наличия новых фактов
if (TestRule(r)) fNext = true;

}
}
} while (fNext);
ConfirmGoal(); // подтверждение цели
}
char Menu() { // Выбор пункта меню
char m; // пункт меню
cout << endl << " Меню:" << endl;
cout << "1. Ввод исходных данных" << endl;
cout << "2. Вывод рабочей памяти" << endl;
cout << "3. Очистка рабочей памяти" << endl;
cout << "4. Ввод правил" << endl;
cout << "5. Вывод списка правил" << endl;
cout << "6. Очистка списка правил" << endl;
cout << "7. Прямой поиск решений (от данных к цели)" << endl;
cout << "8. Обратный поиск решений (от цели к данным)" <<
endl;
cout << "9. Выход" << endl;
cout << "Выберите пункт меню: ";
cin >> m; // выбор пункта меню
return m;
}

11

int main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
cout << "Решение логических задач" << endl;
char m; // пункт меню
do {
m = Menu(); // выбор пункта меню
if (m == '1') AddFacts(); // добавление фактов
if (m == '2') ShowFacts(); // показ рабочей памяти
if (m == '3') nf = 0; // очистка рабочей памяти
if (m == '4') AddRules(); // ввод правил
if (m == '5') ShowRules(); // показ списка правил
if (m == '6') nr = 0; // очистка списка правил
if (m == '7') Find(); // прямой поиск
if (m == '8') BackFind(); // обратный поиск
} while (m != '9');
system("pause");
return 0;
}


Задания к лабораторной работе
На основе приведенных выше примеров реализовать и отладить
программу решения логических задач в соответствии с заданным
вариантом. В случае необходимости доработать программу для разбора
сложных составных правил.

20 вариант:
На танцах. Эд, Франк, Джордж и Гарри пригласили своих жен
в вечерний клуб на танцы и для разнообразия решили, что
каждый будет танцевать с женой другого. В результате Бетти
танцевала с Эдом, Алиса – с мужем Кэрол, Дороти – с мужем
Алисы, Франк – с женой Джорджа, а Джордж – с женой Эда.
Кто на ком женат? Кто с кем танцевал?

Напиши программу на C#

вот код:
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    // Define a fact structure for clarity
    struct Fact
    {
        public string Subject;
        public string Predicate;
        public string Object;

        public Fact(string subject, string predicate, string obj)
        {
            Subject = subject;
            Predicate = predicate;
            Object = obj;
        }

        public override string ToString() => $"{Subject} {Predicate} {Object}";
    }

    static List<Fact> facts = new List<Fact>();
    static List<Fact> rules = new List<Fact>();

    static void Main()
    {
        // Initial setup
        string[] men = { "Ed", "Frank", "George", "Harry" };
        string[] women = { "Betty", "Alice", "Dorothy", "Carol" };

        // Problem's given clues as rules:
        // Betty danced with Ed
        rules.Add(new Fact("Betty", "dancedWith", "Ed"));
        // Alice danced with the husband of Carol
        rules.Add(new Fact("Alice", "dancedWithHusbandOf", "Carol"));
        // Dorothy danced with the husband of Alice
        rules.Add(new Fact("Dorothy", "dancedWithHusbandOf", "Alice"));
        // Frank danced with the wife of George
        rules.Add(new Fact("Frank", "dancedWithWifeOf", "George"));
        // George danced with the wife of Ed
        rules.Add(new Fact("George", "dancedWithWifeOf", "Ed"));

        // Attempting to assign marriages to satisfy all dancing rules
        DeduceMarriages(men, women);

        // Print results
        Console.WriteLine("Marriages:");
        foreach (var fact in facts.Where(f => f.Predicate == "marriedTo"))
            Console.WriteLine($"{fact.Subject} is married to {fact.Object}");

        Console.WriteLine("\nDancing Pairs:");
        foreach (var fact in facts.Where(f => f.Predicate == "dancedWith"))
            Console.WriteLine($"{fact.Subject} danced with {fact.Object}");
    }

    static void DeduceMarriages(string[] men, string[] women)
    {
        // Brute-force search through possible marriages
        var permutations = GetPermutations(women, women.Length);

        foreach (var permutation in permutations)
        {
            facts.Clear();  // Reset facts for each permutation
            for (int i = 0; i < men.Length; i++)
                facts.Add(new Fact(men[i], "marriedTo", permutation[i]));

            // Apply dancing rules based on current marriages
            ApplyDancingRules();

            // Check if all rules are satisfied
            if (AllRulesSatisfied())
                break;
        }
    }

    static void ApplyDancingRules()
    {
        facts.Add(new Fact("Betty", "dancedWith", "Ed"));

        string carolHusband = facts.FirstOrDefault(f => f.Object == "Carol").Subject;
        if (carolHusband != null)
            facts.Add(new Fact("Alice", "dancedWith", carolHusband));

        string aliceHusband = facts.FirstOrDefault(f => f.Object == "Alice").Subject;
        if (aliceHusband != null)
            facts.Add(new Fact("Dorothy", "dancedWith", aliceHusband));

        string georgeWife = facts.FirstOrDefault(f => f.Subject == "George").Object;
        if (georgeWife != null)
            facts.Add(new Fact("Frank", "dancedWith", georgeWife));

        string edWife = facts.FirstOrDefault(f => f.Subject == "Ed").Object;
        if (edWife != null)
            facts.Add(new Fact("George", "dancedWith", edWife));
    }

    static bool AllRulesSatisfied()
    {
        foreach (var rule in rules)
        {
            bool satisfied = rule.Predicate switch
            {
                "dancedWith" => facts.Any(f => f.Subject == rule.Subject && f.Predicate == "dancedWith" && f.Object == rule.Object),
                "dancedWithHusbandOf" => facts.Any(f => f.Subject == rule.Subject && f.Predicate == "dancedWith" && facts.Any(m => m.Subject == rule.Object && m.Predicate == "marriedTo" && m.Object == f.Object)),
                "dancedWithWifeOf" => facts.Any(f => f.Subject == rule.Subject && f.Predicate == "dancedWith" && facts.Any(m => m.Object == rule.Object && m.Predicate == "marriedTo" && m.Subject == f.Object)),
                _ => false
            };

            if (!satisfied)
                return false;
        }
        return true;
    }

    // Helper: Generate all permutations of a set
    static IEnumerable<T[]> GetPermutations<T>(T[] array, int length)
    {
        if (length == 1)
            return array.Select(t => new T[] { t });

        return GetPermutations(array, length - 1)
            .SelectMany(t => array.Where(e => !t.Contains(e)),
                        (t1, t2) => t1.Concat(new T[] { t2 }).ToArray());
    }
}
Данная прграмма выдает неправильный ответ:
Marriages:
Ed is married to Carol
Frank is married to Dorothy
George is married to Alice
Harry is married to Betty

Dancing Pairs:
Betty danced with Ed
Alice danced with Ed
Dorothy danced with George
Frank danced with Alice
George danced with Carol
но правильный ответ в задаче такой :
Эд женат на Дороти, Франк женат Кэрол, Джордж женат на
Алисе, Гарри женат на Бетти. Эд танцевал с Бетти, Франк
танцевал с Алисой, Джордж танцевал с Дороти, Гарри
танцевал с Кэрол.
исправь логику задачи, там имеются повторения людей в парах, то есть один человек танцует сразу с несколькими, возможно есть еще ошибку, исправь  их и доработай программму
Не торопись, все тчательно проанализируй
Возможно ты сам знаешь как правильно написать программу, решующую эту задачу, напиши на c#. самое задание в общем звучит так: Разработать систему на базе четной логики