3
\$\begingroup\$

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;
}
\$\endgroup\$
3
\$\begingroup\$

Two things stand out:

  1. In your Bomb constructor, you do this:

    Wire current_wire(wire);
    

    This is creating a locally scoped variable current_wire and setting its value to wire, it's not updating the member variable of the class.

  2. You are keeping track of more information than you need to. You only need know the previous wire to know if the current wire is going to cause an explosion. You are however keeping track of every wire in previous_cuts, although you're not using the value anyway. Generally, you're better off not having redundant code, so if you're not going to use it, get rid of it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.