Logik Problem: Vermeidung von if Abfragen
-
Hallo, ich habe folgendes struct:
struct FARBE { bool blue; bool green; bool black; bool white; bool red; };Zudem habe ich eine Klasse, die ein Farbobjekt als eigenschaft hat
class Klasse { public: FARBE farben; };Nun habe ich jede Menge Objekte von Klasse. Einige davon sollen aussortiert werden. Dazu gibt es eine Bedingung:
FARBE bedingung; bedingung.blue=true; bedingung.green=false; bedingung.black=true; bedingung.white=true; bedingung.red=false;In diesem Beispiel sollen nun alle Objekte der Klasse aussortiert werden, die der Bedingung (blau, schwarz, weiß) nicht gerecht werden. Die Bedingung ist genau dann erfüllt, wenn ein Objekt Blau, schwarz, weiß, Blau und schwarz, Blau und weiß, ..., Blau und schwarz und weiß ist.
Jetzt könnte ich ewig viele if Bedingungen schreiben, um jeden einzelnen Fall zu erfassen. Hat jemand eine Idee für einen algorithmus, der diese Arbeit erleichtert?
Ich hoffe ihr versteht das Problem
-
Schau mal im Tutorial deiner Wahl nach den logischen Operatoren || und &&
-
Die Operatoren sind mir natürlich bekannt.
Trotzdem wäre der Ansatz ja:
if(bedingung.blue==false && bedingung.green==false && bedingung.red==false && bedingung.white==false && bedingung.black==false) { if(objekt.farbe.blue || objekt.farbe.green || objekt.farbe.red || objekt.farbe.white || objekt.farbe.black) return false; } if(bedingung.blue && bedingung.green && bedingung.red && bedingung.white==false && bedingung.black==false) { if(objekt.farbe.blue==false || objekt.farbe.green==false || objekt.farbe.red==false || objekt.farbe.white || objekt.farbe.black) return false; }Das sind gerade mal 2 von 25 möglichen Bedingungen. Verstehst du jetzt, was ich meine?

-
Hi,
das wäre mein Ansatz, aber ich bin mir nicht sicher, ob ich die Aufgabenstellung korrekt verstanden habe.
In diesem Fall reicht es, wenn das Objekt eine der angegebenen Farben erfüllt.#include <iostream> #include <string> struct Color { bool red; bool green; bool blue; bool white; bool black; }; bool checkColor(const Color& col, const std::string& cond); int main() { Color test; test.red = false; test.green = false; test.blue = false; test.white = false; test.black = true; // Bedingung ist erfüllt, wenn das Objekt // rot (r), gelb (g), blau (b) oder schwarz (B) ist if (checkColor(test, "rgbB")) { std::cout << "Okay" << std::endl; } } bool checkColor(const Color& col, const std::string& cond) { for (unsigned int i = 0; i < cond.length(); ++i) { switch (cond[i]) { case 'r': // red if (col.red) return true; break; case 'g': // green if (col.green) return true; break; case 'b': // blue if (col.blue) return true; break; case 'w': // white if (col.white) return true; break; case 'B': // black if (col.black) return true; break; } } return false; }
-
Nicht ganz. Die Bedingung ist für das Objekt erfüllt, wenn eine oder mehrere Farben zutreffen. Jedoch nicht, wenn das Objekt eine andere Farbe besitzt.
zB:
Die Bedingung ist Rot, Blau, GrünEin Objekt mit der Farbe Rot -> Erfüllt
Ein Objekt mit den Farben Rot und Grün -> Erfüllt
Ein Objekt mit der Farbe Weiß -> Nicht erfüllt
Ein Objekt mit den Farben Rot und Weiß -> Nicht erfülltUnd es sind natürlich 32 Mögliche Bedingungen, nich 25

-
Hab mich vertan...
-
Ist das bei deinem Beispiel reiner Zufall das, wenn weiß in Spiel ist, die
Bedingung nicht erfüllt ist. Wenn ja, würde das die Sache vereinfachen.
Oder ist bei irgend einer Farbe/Zweifarbenkombi die Bedingung auf jeden erfüllt oder nicht erfüllt?Wenn da aber alle 32 = 2^5 Varianten abgefragt werden sollen, ist doch eine
andere Lösung anzudenken.MfG f.-th.
-
Enums + forschleife
-
Mach ein Bitset mit den Farben und ein Bitset mit der Bedingung und verknüpf die beiden mit den entsprechenden logischen Operatoren.
-
Schreib dir halt ein Hilfsfunktion
bool isValid(bool filter, bool value) { if( value && !filter ) return false; return true; }Und im Programm kannst du das dann auf 5 if's reduzieren:
FARBE filter; FARBE aktuell; // Farben mit Werten füllen if( isValid( filter.red, aktuell.red ) && isValid( filter.green, aktuell.green ) && isValid( filter.blue, aktuell.blue ) && isValid( filter.white, aktuell.white ) && isValid( filter.black, aktuell.black ) { // Farben OK return true; }Bitweises UND wird auch nix bringen, da eben aktuell.$COLOR false sein darf, obwohl im Filter auf true steht.
-
l'abra d'or schrieb:
Bitweises UND wird auch nix bringen, da eben aktuell.$COLOR false sein darf, obwohl im Filter auf true steht.
Habe ich auch gerade gemerkt (und schon editiert während du geantwortet hast). Die richtige Bedingung müsste, wenn ich die Aufgabenstellung richtig verstanden habe, lauten:
(farbe AND bedingung) AND (NOT (farbe AND (NOT bedingung)))Das kann man bestimmt noch irgendwie vereinfachen, aber dafür fühle ich mich gerade zu faul

-
Wenn ich das richtig verstanden habe, ist Die Bedingung genau dann erfüllt, wenn im Objekt keine anderen Farben drin sind als die, die in "bedingung" gespeichert sind. Das könnte so aussehen:
#include <iostream> const unsigned blue = 1; const unsigned green = 2; const unsigned black = 4; const unsigned white = 8; const unsigned red = 16; typedef unsigned farbe_t; inline bool has_blue (farbe_t c) {return c & blue;} inline bool has_green(farbe_t c) {return c & green;} // .... inline bool erfuellt(farbe_t objekt, farbe_t beding) { return (objekt & (~beding))==0; } int main() { farbe_t objekt = blue | red; farbe_t beding = blue | black | white; if (erfuellt(objekt,beding)) { std::cout << "Ja\n"; } else { std::cout << "Nein\n"; } }Gruß,
SP
-
Darf ich mal fragen, warum du eigentlich kein Enum benutzt?
-
Ich wollts halt als struct haben, wobei jede Farbe von nem bool Wert repräsentiert wird.
-
Logigproblem schrieb:
Ich wollts halt als struct haben, wobei jede Farbe von nem bool Wert repräsentiert wird.
das ging wahrscheinlich an Sebastian Pizer ^^
bb
-
FreakY<3Cpp schrieb:
Darf ich mal fragen, warum du eigentlich kein Enum benutzt?
Aus keinem besonderen Grund. Es war eher eine Laune. Es gibt mit
enums einen Vorteil aber auch einen Nachteil:
+ mehr Typsicherheit
- expliziter Cast nötig wenn man "Flags" zusammensetzt// Sei farbe_t ein enum // Beachte den notwendigen Cast: farbe_t objekt = farbe_t( blue | red );Denn der Ausdruck
blue|redist vom Typint, welcher sich nicht direkt einemenumzuweisen lässt. Das kann dann schon mal nerven.Gruß,
SP
-
Sebastian Pizer schrieb:
FreakY<3Cpp schrieb:
Darf ich mal fragen, warum du eigentlich kein Enum benutzt?
Denn der Ausdruck
blue|redist vom Typint, welcher sich nicht direkt einemenumzuweisen lässt. Das kann dann schon mal nerven.Achso, noch etwas: Die "Bit-Operatoren" (in diesem Fall: & | ~) sind nicht wirklich portabel bei vorzeichenbehafteten Ganzzahlen wie
int.assert( ~(-1) == 0); // gilt nicht auf jeder Maschine // nur bei denen, die das Zweierkomplement benutzenGruß,
SP
-
Weiß nicht, ob das erlaubt ist, aber man könnte die Operatoren ja für das
enumüberladen.inline Color operator | (Color left, Color right) { return static_cast <Color> (static_cast<int>(left) | right); }
-
Don06 schrieb:
Weiß nicht, ob das erlaubt ist, aber man könnte die Operatoren ja für das
enumüberladen.Ja, das ist erlaubt.
Gruß,
SP
-
Der Code von l'abra d'or funtkioniert einwandfrei! DANKE

-
Sebastian Pizer schrieb:
Aus keinem besonderen Grund. Es war eher eine Laune. Es gibt mit
enums einen Vorteil aber auch einen Nachteil:
+ mehr Typsicherheit
- expliziter Cast nötig wenn man "Flags" zusammensetztDu könntest zunächst bloß deine selbstgebastelte
unsigned const-Aufzählung in einenumändern und den Rest einfach so lassen.