This code is a solution for /r/daily_programmer #293.
The idea of this challenge is, you are given input in the form of colored wires:
red wire
green wire
blue wire
...
and you are then to determine if cutting the input wires in the order they are listed will cause the "bomb" to detonate or defuse.
What causes the detonation is determined by the previous wire cut. The challenge lists a pre-determined set of colored wires for which the previous wire is not allowed to be followed by a cut of that color or the bomb will detonate.
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
#define ERROR(msg) \
do { \
cout << msg; \
exit(1); \
} while(1) \
/*
* WHITE :: !WHITE, !BLACK
* RED :: !WHITE, !RED, !BLACK !ORANGE, !PURPLE
* BLACK :: !WHITE, !GREEN, !ORANGE
* ORANGE :: !WHITE, !ORANGE, !GREEN, !PURPLE
* GREEN :: !RED, !BLACK, !GREEN, !PURPLE
* PURPLE :: !PURPLE, !GREEN, !WHITE, !ORANGE
*/
string color_names[] = { "white",
"red",
"black",
"orange",
"green",
"purple" };
#define WHITE 1 << 0
#define RED 1 << 1
#define BLACK 1 << 2
#define ORANGE 1 << 3
#define GREEN 1 << 4
#define PURPLE 1 << 5
#define COLORS 6
int color_values[] { WHITE,
RED,
BLACK,
ORANGE,
GREEN,
PURPLE };
int conflicts[COLORS] = { WHITE | BLACK,
WHITE | RED | BLACK | ORANGE | PURPLE,
WHITE | GREEN | ORANGE,
WHITE | ORANGE | GREEN | PURPLE,
RED | BLACK | GREEN | PURPLE,
PURPLE | GREEN | WHITE | ORANGE };
class Wire {
private:
int color_value;
int color_conflicts;
public:
Wire();
Wire(string color);
string color_name;
int is_conflicted(Wire wire);
};
Wire::Wire(void)
{}
Wire::Wire(string color)
{
for (int i=0; i < COLORS; i++)
if (!color.compare(color_names[i])) {
color_name = color_names[i];
color_value = color_values[i];
color_conflicts = conflicts[i];
}
}
int Wire::is_conflicted(Wire wire)
{
return color_conflicts & wire.color_value;
}
class Bomb {
private:
Wire current_wire;
int explode(void);
vector<Wire> previous_cuts;
public:
Bomb(string initial_wire);
int cut_wire(string wire);
vector<Wire> get_previous_cuts();
};
Bomb::Bomb(string initial_wire)
{
string wire(initial_wire);
Wire current_wire(wire);
previous_cuts.push_back(current_wire);
}
int Bomb::cut_wire(string wire)
{
Wire new_wire(wire);
previous_cuts.push_back(new_wire);
if (current_wire.is_conflicted(new_wire))
return explode();
current_wire = new_wire;
return 0;
}
int Bomb::explode(void)
{
cout << "Bomb explodes\n";
return -1;
}
int main(int argc, char *argv[])
{
if (argc < 2)
ERROR("Error Usage: ./bomb_defuse_challenge <input>\n");
string bomb_fname(argv[1]);
ifstream bomb_fh(bomb_fname);
if (!bomb_fh.is_open())
ERROR("Error reading bomb input\n");
string input_wire_color;
getline(bomb_fh, input_wire_color);
Bomb bomb(input_wire_color);
while (getline(bomb_fh, input_wire_color)) {
if (bomb.cut_wire(input_wire_color) < 0)
return 0;
}
cout << "Bomb defused\n";
return 0;
}