Ranking (as of 2013-03-24): 138
Language: C++
/*
UVa 592 - Island of Logic
To build using Visual Studio 2008:
cl -EHsc -O2 island_of_logic.cpp
*/
/*
Details for a few cases:
1
A: I am divine.
day/night A deducible
--------------------------------
d d(ivine) o
d e(vil) o
d h(uman) x
n d x
n e o
n h o
day or night, A = divine or evil or human
1
A: I am lying.
day/night A deducible
--------------------------------
d d(ivine) x
d e(vil) x
d h(uman) x
n d x
n e x
n h x
impossible
2
D: E is human.
D: E is evil.
day/night D E deducible
--------------------------------------------
d d(ivine) d x
d d e(vil) x
d d h(uman) x
d e d o
d e e x
d e h x
d h d x
d h e x
d h h x
n d(ivine) d x
n d e(vil) x
n d h(uman) x
n e d o
n e e x
n e h x
n h d o
n h e x
n h h x
day or night, D = evil or human, E = divine
3
E: I am not human.
D: E is evil.
D: It is day.
day/night D E deducible
--------------------------------------------
d d(ivine) d x
d d e(vil) x
d d h(uman) x
d e d x
d e e x
d e h x
d h d x
d h e x
d h h x
n d(ivine) d x
n d e(vil) x
n d h(uman) x
n e d o
n e e x
n e h o
n h d o
n h e x
n h h o
night D = evil or human, E = divine or human
*/
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <cstring>
using namespace std;
const int nr_speakers_max = 'E' - 'A' + 1;
enum {unknown = -1, divine, evil, human};
enum {day, night};
enum {divine_deduced = 1 << divine, evil_deduced = 1 << evil,
human_deduced = 1 << human};
enum {day_deduced = 1 << day, night_deduced = 1 << night};
bool is_correct_statement(int day_or_night, const vector<int>& speakers,
const char* p)
{
int referrer = speakers[*p - 'A'];
p += 3;
if (*p == 'I' && *(p + 1) == 't') { // "It is ..."
p += 6;
if (!strncmp(p, "day", strlen("day")))
return day_or_night == day;
else // "night."
return day_or_night == night;
}
else {
int referred = (*p == 'I') ? referrer : speakers[*p - 'A'];
p += 5;
if (!strncmp(p, "divine", strlen("divine")))
return referred == divine;
else if (!strncmp(p, "evil", strlen("evil")))
return referred == evil;
else if (!strncmp(p, "human", strlen("human")))
return referred == human;
else if (!strncmp(p, "lying", strlen("lying")))
return referred == evil || referred == human && day_or_night == night;
else if (!strncmp(p, "not divine.", strlen("not divine")))
return referred != divine;
else if (!strncmp(p, "not evil", strlen("not evil")))
return referred != evil;
else if (!strncmp(p, "not human", strlen("not human")))
return referred != human;
else // "not lying."
return referred == divine || referred == human && day_or_night == day;
}
}
bool are_statements_deducible(int day_or_night, const vector<int>& speakers,
const vector< vector<string> >& statements)
{
for (int i = 0; i < nr_speakers_max; i++)
if (speakers[i] != -1) {
for (size_t j = 0; j < statements[i].size(); j++) {
if (speakers[i] == divine || speakers[i] == human && day_or_night == day)
{
if (!is_correct_statement(day_or_night, speakers,
statements[i][j].c_str()))
return false;
}
else {
// speakers[i] == evil || speaker[i] == human && day_or_night == night
if (is_correct_statement(day_or_night, speakers,
statements[i][j].c_str()))
return false;
}
}
}
return true;
}
void deduce_inhabitants(int day_or_night, int si, vector<int>& speakers,
const vector< vector<string> >& statements,
int& deduced_day_or_night, vector<int>& deduced_speakers)
{
while (si < nr_speakers_max && speakers[si] == -1)
si++;
if (si < nr_speakers_max) {
for (int i = divine; i <= human; i++) {
speakers[si] = i;
deduce_inhabitants(day_or_night, si + 1, speakers, statements,
deduced_day_or_night, deduced_speakers);
}
}
else {
if (are_statements_deducible(day_or_night, speakers, statements)) {
// record the deduced facts (day or night, inhabitant types)
deduced_day_or_night |= 1 << day_or_night;
for (int i = 0; i < nr_speakers_max; i++)
if (speakers[i] != -1)
deduced_speakers[i] |= 1 << speakers[i];
}
}
}
int main()
{
for (int c = 1; ; c++) {
string line;
getline(cin, line);
istringstream iss(line);
int n;
iss >> n;
iss.clear();
if (!n)
break;
vector<int> speakers(nr_speakers_max, -1);
// speakers[i] is the type of ('A' + i)-th speaker, or -1 if not appeared
vector<int> deduced_speakers(nr_speakers_max, -1);
// deduced_speakers[i] is the deduced type(s) of ('A' + i)-th speaker,
// or -1 if not appeared
vector< vector<string> > statements(nr_speakers_max);
// statements[i] is the vector of ('A' + i)-th statesments
for (int i = 0; i < n; i++) {
getline(cin, line);
int referrer = line[0] - 'A';
speakers[referrer] = deduced_speakers[referrer] = 0;
if (line[3] >= 'A' && line[3] <= 'E') {
int referred = line[3] - 'A';
speakers[referred] = deduced_speakers[referred] = 0;
}
statements[referrer].push_back(line);
}
int deduced_day_or_night = 0;
deduce_inhabitants(day, 0, speakers, statements, deduced_day_or_night,
deduced_speakers);
deduce_inhabitants(night, 0, speakers, statements, deduced_day_or_night,
deduced_speakers);
cout << "Conversation #" << c << endl;
int nr_deduced = 0, nr_facts = 0;
for (int i = 0; i < nr_speakers_max; i++) {
int referrer = deduced_speakers[i];
if (referrer != -1) {
if (referrer == divine_deduced || referrer == evil_deduced ||
referrer == human_deduced) {
nr_facts++; nr_deduced++;
cout << static_cast<char>(i + 'A') << " is " <<
((referrer == divine_deduced) ? "divine.\n" :
((referrer == evil_deduced) ? "evil.\n" : "human.\n"));
}
else if (referrer)
nr_deduced++;
}
}
if (deduced_day_or_night) {
nr_deduced++;
if (deduced_day_or_night == day_deduced ||
deduced_day_or_night == night_deduced) {
nr_facts++;
cout << "It is " <<
((deduced_day_or_night == day_deduced) ? "day.\n" : "night.\n");
}
}
if (!nr_deduced)
cout << "This is impossible.\n";
else if (!nr_facts)
cout << "No facts are deducible.\n";
cout << endl;
}
return 0;
}
No comments:
Post a Comment