S
volkard schrieb:
cooky451 schrieb:
Ich habe mir letztes Jahr mal schnell was zusammen gefrickelt was meine Hausaufgaben gelöst hat, vielleicht hilft's ja:
#include <cctype>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <iostream>
class statement_table
{
typedef std::string::const_iterator iterator;
std::map<char, bool> statements_;
std::vector<bool> solutions_;
enum class binary_operator
{
end,
conjunction,
disjunction,
exclusion,
implication,
equivalence,
};
friend std::ostream& operator << (std::ostream& stream, const statement_table& table);
public:
statement_table(const std::string& statement)
{
for (auto c : statement)
{
if (std::isalpha(c))
statements_[c] = false;
}
do {
auto begin = statement.begin();
solutions_.push_back(parse(begin, statement.end()));
} while (next_permutation(statements_.begin(), statements_.end()));
}
private:
bool parse_expression(iterator& begin, iterator end)
{
const auto is_space = [](char c) { return std::isspace(c); };
if ((begin = std::find_if_not(begin, end, is_space)) != end)
{
if (std::isalpha(*begin))
return statements_[*begin++];
if (*begin == '(')
return parse(++begin, end);
if (*begin == '~' && ++begin != end)
{
if (std::isalpha(*begin))
return !statements_[*begin++];
if (*begin == '(')
return !parse(++begin, end);
}
}
throw std::runtime_error("Unexpected end/character found at: " + std::string(begin, end));
}
binary_operator parse_operator(iterator& begin, iterator end)
{
const auto is_space = [](char c) { return std::isspace(c); };
if ((begin = std::find_if_not(begin, end, is_space)) != end)
{
switch (*begin++)
{
default:
break;
case ')':
return binary_operator::end;
case '&':
return binary_operator::conjunction;
case '|':
return binary_operator::disjunction;
case '^':
return binary_operator::exclusion;
case '-':
if (begin != end && *begin++ == '>')
return binary_operator::implication;
break;
case '<':
if (begin != end && *begin++ == '-' && begin != end && *begin++ == '>')
return binary_operator::equivalence;
break;
}
throw std::runtime_error("Unexpected end/character found at: " + std::string(--begin, end));
}
return binary_operator::end;
}
bool parse(iterator& begin, iterator end)
{
bool lop = parse_expression(begin, end);
binary_operator op;
while ((op = parse_operator(begin, end)) != binary_operator::end)
{
bool rop = parse_expression(begin, end);
switch (op)
{
default:
throw std::logic_error("Unknown operator.");
case binary_operator::conjunction:
lop = lop && rop;
break;
case binary_operator::disjunction:
lop = lop || rop;
break;
case binary_operator::exclusion:
lop = lop != rop;
break;
case binary_operator::implication:
lop = !(lop && !rop);
break;
case binary_operator::equivalence:
lop = lop == rop;
break;
}
}
return lop;
}
template <typename Iterator>
static bool next_permutation(Iterator begin, Iterator end)
{
for (; begin != end; ++begin)
{
if (begin->second)
begin->second = false;
else
return begin->second = true;
}
return false;
}
};
std::ostream& operator << (std::ostream& stream, const statement_table& table)
{
auto statements = table.statements_;
std::size_t i = 0;
do {
for (auto p : statements)
{
stream << p.first << " = " << p.second << ' ';
}
stream << (table.solutions_[i++] ? "true" : "false") << '\n';
} while (statement_table::next_permutation(statements.begin(), statements.end()));
return stream;
}
int main()
{
std::string s;
while (std::cout << "Statement: " && std::getline(std::cin, s))
{
try
{
std::cout << statement_table(s) << '\n';
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << '\n';
}
}
}
Das kann dir für beliebige Ausdrücke eine Tabelle erstellen. Nicht sonderlich hübsch, aber funktioniert. Für deinen Ausdruck wäre das dann ~a|b|c.
Das macht mich traurig.
Das macht mich traurig....
Also, dass da keine Begründung geliefert wird.