Logik Problem: Vermeidung von if Abfragen



  • 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


  • Mod

    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.


  • Mod

    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 enum s 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|red ist vom Typ int , welcher sich nicht direkt einem enum zuweisen 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|red ist vom Typ int , welcher sich nicht direkt einem enum zuweisen 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 benutzen
    

    Gruß,
    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 enum s einen Vorteil aber auch einen Nachteil:
    + mehr Typsicherheit
    - expliziter Cast nötig wenn man "Flags" zusammensetzt

    Du könntest zunächst bloß deine selbstgebastelte unsigned const -Aufzählung in ein enum ändern und den Rest einfach so lassen.



  • Logigproblem schrieb:

    Der Code von l'abra d'or funtkioniert einwandfrei! DANKE 😃

    Der Code von Sebastian Pizer ist aber viel kürzer.

    Will auch noch meinen Senf dazugeben:
    Wenn die Farben definiert sind als

    enum Color { blue = 1, green = 2, black = 4, red = 8, white = 16 };
    

    dann kannst du eine Bedingung folgendermaßen erstellen:

    Color condition = Color(black | white | blue);
    

    Die Überprüfung geht dann so:

    if(condition | object == condition)    // Wenn in condition keine Bits gesetzt sind, die nicht auch in condition gesetzt sind
        Farbe erfüllt die Bedingung
    

    Damit ist das Portabilitätsproblem von Sebastian Pizer auch erledigt.



  • @Michael E.: Perfect! 👍 🙂

    Naja, strenggenommen benutzt Du die Bitweise-Oder-Verknüpfung immer noch auf int und nicht unsigned int . Aber die Zahlen, mit denen da hantiert wird, sind ja eh nicht negativ und die Bitmuster für Zahlen 0...32767 müssten dann alle gleich sein, egal ob die Maschine Zweierkomplement, Einerkomplement oder Sign-Magnitude als binäre Repräsentierung nutzt. Ich weiß jetzt gerade nicht, ob C++ noch etwas anderes zulässt. Wenn ja, könnte es sein, dass es immer noch nicht 100% portabel (vermute aber mal, dass es das ist).

    Gruß,
    SP


Anmelden zum Antworten