Dreiwertige Logik (Kleinprojekte)
Die allermeisten Programmiersprachen stellen Boole?sche Variablen und Operatoren zu deren Verknüpfung zur Verfügung. Eine Boole?sche Variable ist binär, also 1 oder 0, true oder false.
Die gängigen Operatoren sind:
- Negation (logisches »Nicht«; NOT oder !),
- Konjunktion (logisches »Und«; AND oder &&),
- Disjunktion (logisches »Oder«; OR oder ||).
Die klassische Aussagenlogik kennt darüber hinaus
- Inklusion (»wenn… dann«) und die
- Äquivalenz (»wenn und nur wenn… dann…«).
Dabei gilt:
Für die Inklusion (A → B):
(A → B) == ((NOT A) or B)
Für die Äquivalenz A ↔ B:
(A ↔ B) == (A → B) AND (B → A)
Andere Modelle der Logik benutzen, neben falsch oder wahr, einen dritten Wahrheitswert, nämlich »unbestimmt«, »nicht bekannt«, »unklar«; oder, näher an der Boole?schen Algebra: ½.
Für diesen dritten Wahrheitswert (hier dark) gilt:
(NOT dark) == dark
true AND dark == dark
false AND dark == false
dark AND dark == dark
true OR dark == true
false OR dark == dark
dark OR dark == dark
Ihre Aufgabe:
Legen Sie eine kleine Programmbibliothek an, die Ausdrücke einer dreiwertigen Logik berechnen kann. Definieren Sie die Grundoperationen NOT, AND, OR für die binären und den dritten Wahrheitswert und leiten Sie Inklusion und Äquivalenz von diesen ab.
Sie müssen hierfür keinen Parser für Ausdrücke bauen. Verschachtelbare Funktionen/Subroutinen reichen vollkommen aus.
Außerdem können Sie frei über Ausdrücke ihrer Programmiersprache verfügen, falls vorhanden. Auch die benutzten Begriffe dienen allein der Anschauung und sind nicht 1:1 umzusetzen. Die Begrifflichkeit unterliegt allein ihrem Planmodell und ihrer Kreativität.
0 Kommentare
6 Lösung(en)
# frozen-string-literal: false
$dark = 'dark'
def tfd_and(a, b)
return false if a == false || b == false
$dark
end
def tfd_or(a, b)
return true if a == true || b == true
$dark
end
def tfd_not(a)
return true if a == false
return false if a == true
$dark
end
def tfd_incl(a, b)
tfd_or(tfd_not(a), b)
end
def tfd_equi(a, b)
tfd_and(tfd_incl(a, b), tfd_incl(b, a))
end
# Verifikation / Checksumme:
puts 'w or (not u):'
puts tfd_or(true, tfd_not($dark))
puts 'u -> w:'
puts tfd_incl($dark, true)
puts '(u or f) ? (u ? (f and (not u))):'
puts tfd_equi(tfd_or($dark, false), tfd_incl($dark, tfd_and(false, tfd_not($dark))))
Lösung von: Ich Bins (tubs)
// NET Core 3.x; C# 8.x
using System;
namespace CS_MDL_CORE_Dreiwertige_Logik
{
enum Bool
{
False, True, Dark
}
class Program
{
static void Main(string[] args)
{
var w = Bool.True;
var f = Bool.False;
var u = Bool.Dark;
Console.WriteLine(OR(w, NOT(u))); // w OR (NOT u) |> True
Console.WriteLine(INCL(u, w)); // u -> w |> True
Console.WriteLine(EQUI(OR(u, f), INCL(u, AND(f, NOT(u))))); // (u OR f) <-> (u -> (f AND (NOT u))) |> Dark
}
static Bool AND(Bool a, Bool b) => (a, b) switch
{
_ when a == Bool.False || b == Bool.False => Bool.False,
_ when a == Bool.True && b == Bool.True => Bool.True,
_ => Bool.Dark
};
static Bool OR(Bool a, Bool b) => (a, b) switch
{
_ when a == Bool.True || b == Bool.True => Bool.True,
_ when a == Bool.False && b == Bool.False => Bool.False,
_ => Bool.Dark
};
static Bool NOT(Bool a) => a switch { Bool.True => Bool.False, Bool.False => Bool.True, _ => Bool.Dark };
static Bool INCL(Bool a, Bool b) => OR(NOT(a), b);
static Bool EQUI(Bool a, Bool b) => AND(INCL(a, b), INCL(b, a));
}
}
Lösung von: Jens Kelm (@JKooP)
// NET Core 3.x
// Achtung: F#
open System
type Bool =
|False = 0
|True = 1
|Dark = 2
let AND a b = if (a = Bool.False || b = Bool.False) then Bool.False else Bool.Dark
let OR a b = if (a = Bool.True || b = Bool.True) then Bool.True else Bool.Dark
let NOT a = match a with |Bool.True -> Bool.False |Bool.False -> Bool.True |_ -> Bool.Dark
let INCL a b = OR (NOT a) b
let EQUI a b = AND (INCL a b) (INCL b a)
[<EntryPoint>]
let main argv =
let w = Bool.True
let f = Bool.False
let u = Bool.Dark
printfn "%A" (OR w (NOT u))
printfn "%A" (INCL u w)
printfn "%A" (EQUI (OR u f) (INCL u (AND f (NOT u))))
0
Lösung von: Jens Kelm (@JKooP)
// NET Core 3.x; C# 8.x
// Lösung mittels Operatorüberladung
using System;
namespace CS_MDL_CORE_Dreiwertige_Logic_Operatorueberladung
{
enum Bool
{
True, False, Dark
}
class Program
{
static void Main(string[] args)
{
var w = new Logic(Bool.True);
var f = new Logic(Bool.False);
var u = new Logic(Bool.Dark);
// w OR (NOT u) |> True
Console.WriteLine(w | !u);
// u -> w |> True
Console.WriteLine(u != w);
// (u OR f) <-> (u -> (f AND (NOT u))) |> Dark
Console.WriteLine(u | f == u != f & !u);
}
}
class Logic
{
public Logic(Bool x) => X = x;
private Bool X { get; }
public override string ToString() => X.ToString();
public override bool Equals(object obj) => obj is Logic logic && X == logic.X;
public override int GetHashCode() => HashCode.Combine(X);
public static Logic operator &(Logic a, Logic b) => (a, b) switch
{
_ when a.X == Bool.False || b.X == Bool.False => new Logic(Bool.False),
_ when a.X == Bool.True && b.X == Bool.True => new Logic(Bool.True),
_ => new Logic(Bool.Dark)
};
public static Logic operator |(Logic a, Logic b) => (a, b) switch
{
_ when a.X == Bool.True || b.X == Bool.True => new Logic(Bool.True),
_ when a.X == Bool.False && b.X == Bool.False => new Logic(Bool.False),
_ => new Logic(Bool.Dark)
};
public static Logic operator !(Logic a) => a.X switch
{
Bool.True => new Logic(Bool.False),
Bool.False => new Logic(Bool.True),
_ => new Logic(Bool.Dark)
};
public static Logic operator !=(Logic a, Logic b) => !a | b; // Inklusion (a -> b)
public static Logic operator ==(Logic a, Logic b) => a != b & b != a; // Äquivalenz (a <-> b)
}
}
Lösung von: Jens Kelm (@JKooP)
/********************************************************\
| In javaScript gibt es den primitiven wert *undefined*, |
| der sich nützlicherweise in kombination mit boolean- |
| variablen wie gewünscht verhält. Naja, fast. |
| Hier der test: |
|========================================================|
| AND: |
| true && undefined // undefined :-) |
| false && undefined // false :-) |
| undefined && undefined // undefined :-) |
| |
| OR: |
| true || undefined // true :-) |
| |
| false || undefined // undefined :-) ABER: |
| undefined || false // false %-( |
| |
| undefined || undefined // undefined :-) |
| |
| NOT: |
| !undefined // true :-( |
|========================================================|
| Das kann uns tatsächlich einige typtests |
| ersparen, zumindest was AND angeht. |
| |
| /!\ WARNUNG: NSFW! /!\ |
| Das willkürliche manipulieren und die unkontrollierte |
| übernahme von *undefined* in funktionen kann in |
| komplexeren systemen saarlandgroße löcher ins |
| programmiererknie schießen. |
| Aber hier, als demonstration, funktioniert es erstmal |
| hinlänglich. |
\********************************************************/
let L3 = {
not: function(a) {
return typeof a == 'boolean' ? !a : undefined; // s. o.
},
and: function(a, b) { return a && b; },
// hier der spielverderber (s. o.)
or: function(a, b) {
if (a == true || b == true) return true;
if (a == false && b == false) return false;
return undefined;
},
// implikation
if: function(a, b) {
return this.or(this.not(a), b);
},
// äquivalenz
iff: function(a, b) {
return this.and(this.if(a, b), this.if(b, a));
}
};
// ausgabe
let w = true, f = false, u = undefined;
// w OR (NOT u)
console.log( L3.or(w, L3.not(u)) );
// u -> w
console.log( L3.if(u, w) );
// (u OR f) <=> (u -> [f AND {NOT u}])
console.log(
L3.iff(L3.or(u, f), L3.if(u, L3.and(f, L3.not(u))))
); // lissalanda@gmx.at
Lösung von: Lisa Salander (Heidi-Klum-Gymnasium Bottrop)
// C++ 11
// main
#include "Logic.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
auto w{ Logic(Bool::True) };
auto f{ Logic(Bool::False) };
auto u{ Logic(Bool::Dark) };
// w OR (NOT u) |> True
cout << (w | !u) << endl;
// u -> w | > True
cout << (u != w) << endl;
// (u OR f) <-> (u -> (f AND (NOT u))) |> Dark
cout << (u | f == u != f & !u) << endl;
}
// Logic.h
#pragma once
#include <ostream>
using namespace std;
enum class Bool
{
True, False, Dark
};
class Logic
{
private:
Bool X;
public:
Logic(Bool x) { X = x; };
friend Logic operator&(Logic const&, Logic const&);
friend Logic operator|(Logic const&, Logic const&);
friend Logic operator!(Logic const&);
friend Logic operator!=(Logic const&, Logic const&);
friend Logic operator==(Logic const&, Logic const&);
friend ostream& operator<<(ostream&, Logic const&);
};
// Logic.cpp
#include "Logic.h"
string get_bool(Bool b) {
switch (b) {
case Bool::True: return "True"; break;
case Bool::False: return "False"; break;
default: return "Dark";
}
}
Logic operator&(Logic const& a, Logic const& b) {
if (a.X == Bool::False || b.X == Bool::False) return Logic(Bool::False);
else if (a.X == Bool::True && b.X == Bool::True) return Logic(Bool::True);
else return Logic(Bool::Dark);
}
Logic operator|(Logic const& a, Logic const& b) {
if (a.X == Bool::True|| b.X == Bool::True) return Logic(Bool::True);
else if (a.X == Bool::False && b.X == Bool::False) return Logic(Bool::False);
else return Logic(Bool::Dark);
}
Logic operator!(Logic const& a) {
switch (a.X) {
case Bool::True: return Logic(Bool::False);
case Bool::False: return Logic(Bool::True);
default: return Logic(Bool::Dark);
}
}
Logic operator!=(Logic const& a, Logic const& b) {
return Logic(!a | b);
}
Logic operator==(Logic const& a, Logic const& b) {
return Logic(a != b & b != a);
}
ostream& operator<<(ostream& o, Logic const& v) {
return o << get_bool(v.X);
}
Lösung von: Jens Kelm (@JKooP)
Verifikation/Checksumme:
w := true;
f := false;
u := dark;
w OR (NOT u)
(== true)
u → w
(== true)
(u OR f) ↔ (u → (f AND (NOT u)))
(== dark)
Aktionen
Neue Lösung hinzufügen
Bewertung
Durchschnittliche Bewertung: