Ternary logic: Difference between revisions

No edit summary
(20 intermediate revisions by 9 users not shown)
Line 933:
MAYBE EQV TRUE = MAYBE
TRUE EQV TRUE = TRUE
</pre>
 
=={{header|Bruijn}}==
Direct translations of the truth tables to lambda calculus. The operators could be golfed significantly. If you do so, please add them here!
 
For applications of Ternary logic, see bruijn's [[Balanced_ternary#Bruijn|balanced ternary]] implementation.
<syntaxhighlight lang="bruijn">
true [[[0]]]
 
maybe [[[1]]]
 
false [[[2]]]
 
¬‣ [0 true maybe false]
 
…⋀… [[1 (0 1 1 1) (0 0 0 1) (0 0 0 0)]]
 
…⋁… [[1 (0 0 0 0) (0 1 0 0) (0 1 1 1)]]
 
…⊃… [[1 (0 true 0 1) (0 true 1 1) (0 1 1 1)]]
 
…≡… [[1 (0 true 0 1) (0 1 1 1) (0 0 0 0)]]
 
# --- result samples ---
 
:import std/List .
 
main [[inp <> "=" <> !res ++ "\n"] <++> (cross3 ops trits trits)]
!‣ [0 "false" "maybe" "true"]
…<>… [[1 ++ " " ++ 0]]
inp 0 [[~1 <> (0 [[!1 <> (0 [[!1]])]])]]
res ^(^0) ^(~0) ^(~(~0))
ops (…⋀… : "and") : ((…⋁… : "or") : ((…⊃… : "if") : {}(…≡… : "equiv")))
trits true : (maybe : {}false)
</syntaxhighlight>
 
{{out}}
<pre>
and true true = true
and true maybe = maybe
and true false = false
and maybe true = maybe
and maybe maybe = maybe
and maybe false = false
and false true = false
and false maybe = false
and false false = false
or true true = true
or true maybe = true
or true false = true
or maybe true = true
or maybe maybe = maybe
or maybe false = maybe
or false true = true
or false maybe = maybe
or false false = false
if true true = true
if true maybe = true
if true false = true
if maybe true = maybe
if maybe maybe = maybe
if maybe false = true
if false true = false
if false maybe = maybe
if false false = true
equiv true true = true
equiv true maybe = maybe
equiv true false = false
equiv maybe true = maybe
equiv maybe maybe = maybe
equiv maybe false = maybe
equiv false true = false
equiv false maybe = maybe
equiv false false = true
</pre>
 
Line 1,646 ⟶ 1,720:
That's no real fun, but lookup can then be done with
<syntaxhighlight lang="delphi">Result := tvl_and[A, B];</syntaxhighlight>
 
=={{header|EasyLang}}==
{{trans|FreeBASIC}}
<syntaxhighlight>
sym$[] = [ "F" "?" "T" ]
arrbase sym$[] -1
#
func tnot x .
return -x
.
func tand x y .
if x > y
return tand y x
.
return x
.
func tor x y .
if x < y
return tor y x
.
return x
.
func teqv x y .
return x * y
.
func timp x y .
if -y > x
return -y
.
return x
.
print " (AND) ( OR) (EQV) (IMP) (NOT)"
print " F ? T F ? T F ? T F ? T "
print " -----------------------------------------"
for i = -1 to 1
o$ = " " & sym$[i] & " | "
o$ &= sym$[tand -1 i] & " " & sym$[tand 0 i] & " " & sym$[tand 1 i]
o$ &= " "
o$ &= sym$[tor -1 i] & " " & sym$[tor 0 i] & " " & sym$[tor 1 i]
o$ &= " "
o$ &= sym$[timp -1 i] & " " & sym$[timp 0 i] & " " & sym$[timp 1 i]
o$ &= " "
o$ &= sym$[timp -1 i] & " " & sym$[timp 0 i] & " " & sym$[timp 1 i]
o$ &= " " & sym$[tnot i]
print o$
.
</syntaxhighlight>
 
=={{header|Elena}}==
ELENA 56.0x :
<syntaxhighlight lang="elena">import extensions;
import system'routines;
Line 1,655 ⟶ 1,776:
sealed class Trit
{
bool _value;
bool cast() = _value;
constructor(object v)
{
if (v != nil)
{
_value := cast bool(v);
}
}
Trit equivalent(b)
{
= _value.equal(cast bool(b)) \ back:nilValue;
var val2 := cast bool(b) \ back(nil);
 
if (val2 != nil && _value != nil)
{
^ _value.equal(val2)
};
 
^ nilValue;
}
Trit Inverted
= _value.Inverted \ back:(nilValue);
Trit and(b)
{
if (nil == _value)
{
^ b.and:(nil) \ back:(nilValue)
}
else
{
^ _value.and((lazy:cast bool(b))) \ back:(nilValue)
}
}
Trit or(b)
{
if (nil == _value)
{
^ b.or:(nilValue) \ back:(nilValue)
}
else
{
^ _value.or((lazy:cast bool(b))) \ back:(nilValue)
}
}
Trit implies(b)
= self.Inverted.or(b);
string toPrintable() = _value.toPrintable() \ back:("maybe");
}
Line 1,706 ⟶ 1,836:
{
List<Trit> values := new Trit[]{true, nilValue, false};
values.forEach::(left)
{
console.printLine("¬",left," = ", left.Inverted);
values.forEach::(right)
{
console.printLine(left, " & ", right, " = ", left && right);
console.printLine(left, " | ", right, " = ", left || right);
console.printLine(left, " → ", right, " = ", left.implies:(right));
console.printLine(left, " ≡ ", right, " = ", left.equivalent:(right))
}
}
Line 3,334 ⟶ 3,464:
=={{header|langur}}==
{{trans|Go}}
{{works with|langur|0.6.12}}
 
<syntaxhighlight lang="langur"># borrowing null for "maybe"
val .trSet = [false, null, true]
 
val .and = ffn given.a, .b: switch[and] .a, .b {
case true, null:
case null, true:
Line 3,346 ⟶ 3,474:
}
 
val .or = ffn given.a, .b: switch[and] .a, .b {
case false, null:
case null, false:
Line 3,353 ⟶ 3,481:
}
 
val .imply = ffn .a, .b: if(.a nor .b: not? .a; .b)
 
# formatting function for the result values
# replacing null with "maybe"
# using left alignment of 5 code points
val .F = ffn .r: $"\{{nn [.r, "maybe"]:-5}}"
 
writeln "a not a"
for .a in .trSet {
writeln $"\{{.a:.fn F;}} \({{not? .a:.fn F)}}"
}
 
Line 3,368 ⟶ 3,496:
for .a in .trSet {
for .b in .trSet {
writeln $"\{{.a:.fn F;}} \{{.b:.fn F;}} \{{.and(.a, .b):.fn F;}}"
}
}
Line 3,375 ⟶ 3,503:
for .a in .trSet {
for .b in .trSet {
writeln $"\{{.a:.fn F;}} \{{.b:.fn F;}} \{{.or(.a, .b):.fn F;}}"
}
}
Line 3,382 ⟶ 3,510:
for .a in .trSet {
for .b in .trSet {
writeln $"\{{.a:.fn F;}} \{{.b:.fn F;}} \{{.imply(.a, .b):.fn F;}}"
}
}
Line 3,389 ⟶ 3,517:
for .a in .trSet {
for .b in .trSet {
writeln $"\{{.a:.fn F;}} \{{.b:.fn F;}} \{{.a ==? .b:.fn F;}}"
}
}
}</syntaxhighlight>
</syntaxhighlight>
 
{{out}}
Line 3,541 ⟶ 3,670:
T ? ? T ? ?
T T T T T F
</pre>
 
=={{header|M2000 Interpreter}}==
 
<syntaxhighlight lang="m2000 interpreter">module Ternary_logic {
class trit {
private:
variant val
function copy() {
m=this
m.trit
=m
}
public:
enum ternary {
True="True"
Maybe="Maybe"
False="False"
}
function true() {
=.copy(.True)
}
function maybe() {
=.copy(.Maybe)
}
function false() {
=.copy(.False)
}
operator "==" (k as trit) {
push .val=k.val
}
operator "^^" (k as trit) {
select enum .val
case .True
.val<=k.val
case .False
.val<=.False
case else
if k.val=.False then .val<=.False else .val<=.Maybe
end select
}
operator "^|" (k as trit) {
select enum .val
case .True
.val<=k.val
case .False
.val<=.True
case else
if k.val=.True then .val<=.True else .val<=.Maybe
end select
}
operator "||" (k as trit) {
select enum .val
case .False
.val<=k.val
case .True
.val<=.True
case else
if k.val=.True then .val<=.True else .val<=.Maybe
end select
}
operator "~~" (k as trit) {
select enum .val
case .True
.val<=k.val
case .False
if k.val=.True then .val<=.False else.if k.val=.False then .val<=.True else .val<=k.val
case else
.val<=.Maybe
end select
}
operator unary {
select enum .val
case .True
.val<=.False
case .False
.val<=.True
end select
}
group value {
value {
link parent val to val
=val
}
}
module trit {
if empty or not isnum then
read s as .ternary=.Maybe
.val<=s
else.if isnum then
read what
if what then
.val<=.True
else
.val<=.False
end if
end if
}
}
function enum2array(t) {
m=each(t)
while m {data eval(m)}
=array([])
}
string out, nl={
}
q=trit()
m=trit()
k=enum2array(q.ternary)
out ="not a" + nl
a=each(k)
while a
q=trit(array(a))
z=-q
out +=" ternary_not "+(q.value) + " = " + (z.value) + nl
end while
out +="a and b" + nl
a=each(k)
while a
b=each(k)
while b
q=trit(array(a))
m=trit(array(b))
z=q ^^ m
out += " " + (q.value) + " ternary_and " + (m.value) + " = " + (z.value) + nl
end while
end while
out +="a or b" + nl
a=each(k)
while a
b=each(k)
while b
q=trit(array(a))
m=trit(array(b))
z=q || m
out += " " + (q.value) + " ternary_or " + (m.value) + " = " + (z.value) + nl
end while
end while
out +="if a then b" + nl
a=each(k)
while a
b=each(k)
while b
q=trit(array(a))
m=trit(array(b))
z=q ^| m
out += " if " + (q.value) + " then " + (m.value) + " = " + (z.value) + nl
end while
end while
out +="a is equivalent to b" + nl
a=each(k)
while a
b=each(k)
while b
q=trit(array(a))
m=trit(array(b))
z=q ~~ m
out += " "+(q.value) + " is equivalent to " + (m.value) + " = " + (z.value) + nl
end while
end while
report out
clipboard out
}
Ternary_logic
</syntaxhighlight>
{{out}}
<pre>not a
ternary_not True = False
ternary_not Maybe = Maybe
ternary_not False = True
a and b
True ternary_and True = True
True ternary_and Maybe = Maybe
True ternary_and False = False
Maybe ternary_and True = Maybe
Maybe ternary_and Maybe = Maybe
Maybe ternary_and False = False
False ternary_and True = False
False ternary_and Maybe = False
False ternary_and False = False
a or b
True ternary_or True = True
True ternary_or Maybe = True
True ternary_or False = True
Maybe ternary_or True = True
Maybe ternary_or Maybe = Maybe
Maybe ternary_or False = Maybe
False ternary_or True = True
False ternary_or Maybe = Maybe
False ternary_or False = False
if a then b
if True then True = True
if True then Maybe = Maybe
if True then False = False
if Maybe then True = True
if Maybe then Maybe = Maybe
if Maybe then False = Maybe
if False then True = True
if False then Maybe = True
if False then False = True
a is equivalent to b
True is equivalent to True = True
True is equivalent to Maybe = Maybe
True is equivalent to False = False
Maybe is equivalent to True = Maybe
Maybe is equivalent to Maybe = Maybe
Maybe is equivalent to False = Maybe
False is equivalent to True = False
False is equivalent to Maybe = Maybe
False is equivalent to False = True
</pre>
 
Line 4,269 ⟶ 4,608:
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">use v5.36;
File <TT>Trit.pm</TT>:
<syntaxhighlight lang="perl">package Trit;
 
package Trit;
# -1 = false ; 0 = maybe ; 1 = true
use List::Util qw(min max);
 
our @ISA = qw(Exporter);
use Exporter 'import';
our @EXPORT = qw(%E);
 
my %E = (true => 1, false => -1, maybe => 0);
our @EXPORT_OK = qw(TRUE FALSE MAYBE is_true is_false is_maybe);
our %EXPORT_TAGS = (
all => \@EXPORT_OK,
const => [qw(TRUE FALSE MAYBE)],
bool => [qw(is_true is_false is_maybe)],
);
 
use List::Util qw(min max);
 
use overload
'<=>' => sub ($a,$b) { $_[0]a->clonecmp($b) },
'<=>cmp' => sub ($a,$b) { $_[0]a->cmp($_[1]b) },
'cmp==' => sub ($a,$b,$) { $_[0]->cmp($_[1])a == $$b },
'==eq' => sub { (${a,$_[0]}b,$) == ${ $a->equiv($_[1]}b) },
'eq>' => sub ($a,$b,$) { $_[0]-$a >equiv( $_[1])E{$b} },
'><' => sub ($a,$b,$) { ${$_[0]}a < > $E{$_[1]b} },
'<>=' => sub ($a,$b,$) { ${$_[0]}a <>= ${$_[1]}b },
'><=' => sub ($a,$b,$) { ${$_[0]}a ><= ${$_[1]}b },
'<=|' => sub { (${a,$_[0]}b,$,$,$) <={ ${a->or($_[1]}b) },
'|&' => sub ($a,$b,$,$,$) { $_[0]a->orand($_[1]b) },
'&!' => sub ($a,$,$) { $_[0]a->andnot($_[1]) },
'!~' => sub ($a,$,$,$,$) { $_[0]a->not() },
'~neg' => sub ($a,$,$) { $_[0]->not()$$a },
'""' => sub ($a,$,$) { $_[0]a->tostr() },
'0+' => sub ($a,$,$) { $_[0]a->tonum() },
;
 
sub neweqv ($a,$b) {
$$a == $E{maybe} || $E{$b} == $E{maybe} ? $E{maybe} : # either arg 'maybe', return 'maybe'
{
$$a == $E{false} && $E{$b} == $E{false} ? $E{true} : # both args 'false', return 'true'
my ($class, $v) = @_;
min $$a, $E{$b} # either arg 'false', return 'false', otherwise 'true'
my $ret =
!defined($v) ? 0 :
$v eq 'true' ? 1 :
$v eq 'false'? -1 :
$v eq 'maybe'? 0 :
$v > 0 ? 1 :
$v < 0 ? -1 :
0;
return bless \$ret, $class;
}
 
# do tests in a manner that avoids overloaded operators
sub TRUE() { new Trit( 1) }
sub FALSE() { new Trit(-1$class, $v) }{
my $value =
sub MAYBE() { new Trit( 0) }
! defined $v ? $E{maybe} :
 
$v =~ /true/ ? $E{true} :
sub clone
$v =~ /false/ ? $E{false} :
{
my $retv =~ /maybe/ ? $E{$_[0]maybe}; :
$v gt $E{maybe} ? $E{true} :
return bless \$ret, ref($_[0]);
$v lt $E{maybe} ? $E{false} :
$E{maybe} ;
bless \$value, $class;
}
 
sub tostr ($a) { ${$_[0]}a > 0$E{maybe} ? "'true"' : ${$_[0]}a < 0$E{maybe} ? "'false"' : "'maybe"' }
sub tonum ($a) { ${$_[0]}a }
 
sub is_truenot { ($a) {$_[0]} Trit->new( -$a 0) }
sub is_falsecmp { ($a,$b) { Trit->new( $_[0]}a <=> $b 0) }
sub is_maybeand { ($a,$b) { Trit->new( min $_[0]}a, ==$b 0) }
sub or ($a,$b) { Trit->new( max $a, $b ) }
sub equiv ($a,$b) { Trit->new( eqv $a, $b ) }
 
package main;
sub cmp { ${$_[0]} <=> ${$_[1]} }
Trit->import;
sub not { new Trit(-${$_[0]}) }
sub and { new Trit(min(${$_[0]}, ${$_[1]}) ) }
sub or { new Trit(max(${$_[0]}, ${$_[1]}) ) }
 
my @a = ( Trit->new($E{true}), Trit->new($E{maybe}), Trit->new($E{false}) );
sub equiv { new Trit( ${$_[0]} * ${$_[1]} ) }</syntaxhighlight>
printf "Codes for logic values: %6s = %d %6s = %d %6s = %d\n", @a[0, 0, 1, 1, 2, 2];
File <TT>test.pl</TT>:
<syntaxhighlight lang="perl">use Trit ':all';
 
# prefix ! (not) ['~' also can be used]
my @a = (TRUE(), MAYBE(), FALSE());
say "\na\tNOT a";
print "$_\t".(!$_)."\n" for @a;
 
# infix & (and)
print "\na\tNOT a\n";
say "\nAND\t" . join("\t",@a);
print "$_\t".(!$_)."\n" for @a; # Example of use of prefix operator NOT. Tilde ~ also can be used.
for my $a (@a) { print $a; print "\t" . ($a & $_) for @a; say '' }
 
# infix | (or)
say "\nOR\t" . join("\t",@a);
for my $a (@a) { print $a; print "\t" . ($a | $_) for @a; say '' }
 
# infix eq (equivalence)
print "\nAND\t".join("\t",@a)."\n";
forsay my"\nEQV\t" $a. join("\t",@a) {;
for my $a (@a) { print $a; print "\t" . ($a eq $_) for @a; say '' }
print $a;
for my $b (@a) {
print "\t".($a & $b); # Example of use of infix & (and)
}
print "\n";
}
 
# infix == (equality)
print "\nOR\t".join("\t",@a)."\n";
forsay my"\n==\t" $a. join("\t",@a) {;
for my $a (@a) { print $a; print "\t" . ($a == $_) for @a; say '' }</syntaxhighlight>
print $a;
{{out}}
for my $b (@a) {
<pre>Codes for logic values: true = 1 maybe = 0 false = -1
print "\t".($a | $b); # Example of use of infix | (or)
}
print "\n";
}
 
a NOT a
print "\nEQV\t".join("\t",@a)."\n";
for my $a (@a) {
print $a;
for my $b (@a) {
print "\t".($a eq $b); # Example of use of infix eq (equivalence)
}
print "\n";
}
 
print "\n==\t".join("\t",@a)."\n";
for my $a (@a) {
print $a;
for my $b (@a) {
print "\t".($a == $b); # Example of use of infix == (equality)
}
print "\n";
}</syntaxhighlight>
{{out}}
<pre>a NOT a
true false
maybe maybe
Line 5,688 ⟶ 5,995:
maybe maybe ────► maybe
</pre>
 
=={{header|RPL}}==
Ternary logic can be considered as a simplified version of Zadeh's fuzzy logic. In this paradigm, boolean values turn into floating-point ones going from 0 (completely false) to 1 (completely true):
AND(a,b), OR(a,b) and NOT(a) are resp. redefined as MIN(a,b), MAX(a,b) and (1-a). Other boolean operators can then be built by combining these 3 atoms. A specific word is also needed to display results as ternary constants instead of numbers.
{{works with|Halcyon Calc|4.2.7}}
≪ 2 * CEIL 1 + { ‘FALSE’ ‘MAYBE’ ‘TRUE’ } SWAP GET ≫ ''''TELL'''’ STO
≪ OR EVAL '''TELL''' ≫ ''''TAND'''’ STO
≪ AND EVAL '''TELL''' ≫ ''''TOR'''’ STO
≪ 1 SWAP - EVAL '''TELL''' ≫ ''''TNOT'''’ STO
≪ SWAP '''TNOT TOR''' EVAL '''TELL''' ≫ ''''TIMPLY'''’ STO
≪ DUP2 '''TNOT TAND''' ROT '''TNOT''' ROT '''TAND TOR''' EVAL '''TELL''' ≫ ''''TXOR'''’ STO
1 ''''TRUE'''' STO 0.5 ''''MAYBE'''' STO 0 ''''FALSE'''' STO
 
FALSE MAYBE '''TXOR'''
1: ‘TRUE’
Only the Soviets could understand such a logic...
 
=={{header|Ruby}}==
Line 6,206 ⟶ 6,529:
end func;
 
$ syntax expr: .().xor.() is -> 15;
const func trit: (in trit: aTrit1) xor (in trit: aTrit2) is
return tritImplies[succ(ord(aTrit1))][succ(ord(aTrit2))];
Line 6,213 ⟶ 6,536:
return tritImplies[succ(ord(aTrit1))][succ(ord(aTrit2))];
 
syntax expr: .(). == .() is <-> 12;
const func trit: (in trit: aTrit1) == (in trit: aTrit2) is
return tritEquiv[succ(ord(aTrit1))][succ(ord(aTrit2))];
 
const func trit: rand (in trit: low, in trit: high) is
return trit conv (rand(ord(low), ord(high)));
 
# Begin of test code
Line 6,705 ⟶ 7,026:
 
=={{header|Wren}}==
<syntaxhighlight lang="ecmascriptwren">var False = -1
var Maybe = 0
var True = 1
890

edits