Ternary logic: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Java}}: Marked incorrect as MAYBE AND FALSE is FALSE)
(→‎{{header|C}}: Corrected lookup table. Demo all operators.)
Line 413: Line 413:


=={{header|C}}==
=={{header|C}}==
{{incorrect|C|MAYBE AND FALSE is FALSE.}}
Implementing logic using lookup tables.
Implementing logic using lookup tables.
<lang c>#include <stdio.h>
<lang c>#include <stdio.h>

typedef enum {
typedef enum {
TRITTRUE, /* In this enum, equivalent to integer value 0 */
TRITTRUE,
TRITMAYBE, /* In this enum, equivalent to integer value 1 */
TRITMAYBE,
TRITFALSE /* In this enum, equivalent to integer value 2 */
TRITFALSE
} trit;
} trit;

/* We can trivially find the result of the operation by passing
const char* tritString[3] = {"TRUE", "MAYBE", "FALSE"};
the trinary values as indeces into the lookup tables' arrays. */

trit tritNot[3] = {TRITFALSE , TRITMAYBE, TRITTRUE};
trit tritNot[3] = {TRITFALSE , TRITMAYBE, TRITTRUE};
trit tritAnd[3][3] = { {TRITTRUE, TRITMAYBE, TRITFALSE},
trit tritAnd[3][3] = { {TRITTRUE, TRITMAYBE, TRITFALSE},
{TRITMAYBE, TRITMAYBE, TRITMAYBE},
{TRITMAYBE, TRITMAYBE, TRITFALSE},
{TRITFALSE, TRITFALSE, TRITFALSE} };
{TRITFALSE, TRITFALSE, TRITFALSE} };

trit tritOr[3][3] = { {TRITTRUE, TRITTRUE, TRITTRUE},
trit tritOr[3][3] = { {TRITTRUE, TRITTRUE, TRITTRUE},
{TRITTRUE, TRITMAYBE, TRITMAYBE},
{TRITTRUE, TRITMAYBE, TRITMAYBE},
{TRITTRUE, TRITMAYBE, TRITFALSE} };
{TRITTRUE, TRITMAYBE, TRITFALSE} };

trit tritThen[3][3] = { { TRITTRUE, TRITMAYBE, TRITFALSE},
trit tritThen[3][3] = { { TRITTRUE, TRITMAYBE, TRITFALSE},
{ TRITTRUE, TRITMAYBE, TRITMAYBE},
{ TRITTRUE, TRITMAYBE, TRITMAYBE},
{ TRITTRUE, TRITTRUE, TRITTRUE } };
{ TRITTRUE, TRITTRUE, TRITTRUE } };

trit tritEquiv[3][3] = { { TRITTRUE, TRITMAYBE, TRITFALSE},
trit tritEquiv[3][3] = { { TRITTRUE, TRITMAYBE, TRITFALSE},
{ TRITMAYBE, TRITMAYBE, TRITMAYBE},
{ TRITMAYBE, TRITMAYBE, TRITMAYBE},
{ TRITFALSE, TRITMAYBE, TRITTRUE } };
{ TRITFALSE, TRITMAYBE, TRITTRUE } };
int main()
{
trit op1 = TRITTRUE; /* Declare. Initialize for CYA */
trit op2 = TRITTRUE; /* Declare. Initialize for CYA */


/* Everything beyond here is just demonstration */
/* Demo 'not' */

for( op1 = TRITTRUE; op1 <= TRITFALSE; ++op1 )
const char* tritString[3] = {"T", "?", "F"};
{

printf("Not %s: %s\n", tritString[op1], tritString[tritNot[op1]]);
void demo_binary_op(trit operator[3][3], char* name)
}
{
trit operand1 = TRITTRUE; /* Declare. Initialize for CYA */
trit operand2 = TRITTRUE; /* Declare. Initialize for CYA */


/* Blank line */
/* Blank line */
printf("\n");
printf("\n");


/* Demo And */
/* Demo this operator */
for( op1 = TRITTRUE; op1 <= TRITFALSE; ++op1 )
for( operand1 = TRITTRUE; operand1 <= TRITFALSE; ++operand1 )
{
{
for( op2 = TRITTRUE; op2 <= TRITFALSE; ++op2 )
for( operand2 = TRITTRUE; operand2 <= TRITFALSE; ++operand2 )
{
{
printf("%s AND %s: %s\n", tritString[op1], tritString[op2], tritString[tritAnd[op1][op2]]);
printf("%s %s %s: %s\n", tritString[operand1],
name,
tritString[operand2],
tritString[operator[operand1][operand2]]);
}
}
}
}


}

int main()
{
trit op1 = TRITTRUE; /* Declare. Initialize for CYA */
trit op2 = TRITTRUE; /* Declare. Initialize for CYA */
/* Demo 'not' */
for( op1 = TRITTRUE; op1 <= TRITFALSE; ++op1 )
{
printf("Not %s: %s\n", tritString[op1], tritString[tritNot[op1]]);
}
demo_binary_op(tritAnd, "And");
demo_binary_op(tritOr, "Or");
demo_binary_op(tritThen, "Then");
demo_binary_op(tritEquiv, "Equiv");

return 0;
return 0;
}</lang>
}</lang>


Output:
Output:
<lang text>Not TRUE: FALSE
<lang text>Not T: F
Not MAYBE: MAYBE
Not ?: ?
Not FALSE: TRUE
Not F: T

T And T: T
T And ?: ?
T And F: F
? And T: ?
? And ?: ?
? And F: F
F And T: F
F And ?: F
F And F: F

T Or T: T
T Or ?: T
T Or F: T
? Or T: T
? Or ?: ?
? Or F: ?
F Or T: T
F Or ?: ?
F Or F: F

T Then T: T
T Then ?: ?
T Then F: F
? Then T: T
? Then ?: ?
? Then F: ?
F Then T: T
F Then ?: T
F Then F: T


T Equiv T: T
TRUE AND TRUE: TRUE
T Equiv ?: ?
TRUE AND MAYBE: MAYBE
T Equiv F: F
TRUE AND FALSE: FALSE
? Equiv T: ?
MAYBE AND TRUE: MAYBE
? Equiv ?: ?
MAYBE AND MAYBE: MAYBE
? Equiv F: ?
MAYBE AND FALSE: MAYBE
F Equiv T: F
FALSE AND TRUE: FALSE
F Equiv ?: ?
FALSE AND MAYBE: FALSE
FALSE AND FALSE: FALSE</lang>
F Equiv F: T</lang>


=={{header|J}}==
=={{header|J}}==

Revision as of 14:07, 27 August 2011

Ternary logic is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
This page uses content from Wikipedia. The original article was at Ternary logic. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)

In logic, a three-valued logic (also trivalent, ternary, or trinary logic, sometimes abbreviated 3VL) is any of several many-valued logic systems in which there are three truth values indicating true, false and some indeterminate third value. This is contrasted with the more commonly known bivalent logics (such as classical sentential or boolean logic) which provide only for true and false. Conceptual form and basic ideas were initially created by Łukasiewicz, Lewis and Sulski. These were then re-formulated by Grigore Moisil in an axiomatic algebraic form, and also extended to n-valued logics in 1945.

Example Ternary Logic Operators in Truth Tables:
not a
¬
True False
Maybe Maybe
False True
a and b
True Maybe False
True True Maybe False
Maybe Maybe Maybe False
False False False False
a or b
True Maybe False
True True True True
Maybe True Maybe Maybe
False True Maybe False
if a then b
True Maybe False
True True Maybe False
Maybe True Maybe Maybe
False True True True
a is equivalent to b
True Maybe False
True True Maybe False
Maybe Maybe Maybe Maybe
False False Maybe True

Task:

  • Define a new type that emulates ternary logic by storing data trits.
  • Given all the binary logic operators of the original programming language, reimplement these operators for the new Ternary logic type trit.
  • Generate a sampling of results using trit variables.
  • Kudos (κῦδος) for actually thinking up a test case algorithm where ternary logic is intrinsically useful, optimises the test case algorithm and is preferable to binary logic.

Note: Setun (Сетунь) was a balanced ternary computer developed in 1958 at Moscow State University. The device was built under the lead of Sergei Sobolev and Nikolay Brusentsov. It was the only modern ternary computer, using three-valued ternary logic

ALGOL 68

Works with: ALGOL 68 version Revision 1 - no extensions to language used.
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny.

File: Ternary_logic.a68 <lang algol68># -*- coding: utf-8 -*- #

MODE TRIT = STRUCT(BITS trit); INT trit width = 1, trit base = 3; FORMAT trit fmt = $c("⌊","⌈","?" #|"~"#)$;

  1. These values treated are as per "Balanced ternary" #
  2. eg true=1, maybe=0, false=-1 #

TRIT true =INITTRIT 4r1 #⌈#, maybe=INITTRIT 4r0 #?#,

    false=INITTRIT 4r2 #⌊#;

TRIT flip=true, flop=false, flap=maybe;

OP REPR = (TRIT t)STRING:

 IF   t = false THEN "⌊"
 ELIF t = maybe THEN "?"
 ELIF t = true  THEN "⌈"
 ELSE raise value error(("invalid TRIT value",INITINT t));~
 FI;
  1. Define some OPerators for coercing MODES #

OP INITTRIT = (BOOL in)TRIT:

 (in|true|false);

OP B = (TRIT in)BOOL:

 (in=true|TRUE|:in=false|FALSE|
   raise value error(("invalid TRIT to BOOL coercion: """, REPR in,""""));~
 );
  1. These values treated are as per "Balanced ternary" #
  2. n.b true=1, maybe=0, false=-1 #
  3. Warning: BOOL ABS FALSE (0) is not the same as TRIT ABS false (-1) #

OP INITINT = (TRIT t)INT:

 IF   t=true  THEN 1
 ELIF t=maybe THEN 0
 ELIF t=false THEN -1
 ELSE raise value error(("invalid TRIT value",REPR t));~
 FI;

OP INITTRIT = (INT in)TRIT: (

 TRIT out;
 trit OF out:= trit OF
   IF   in= 1 THEN true
   ELIF in= 0 THEN maybe
   ELIF in=-1 THEN false
   ELSE raise value error(("invalid TRIT value",in));~
   FI;
 out

);

OP INITTRIT = (BITS b)TRIT:

 (TRIT out; trit OF out:=b; out);
  1. Define the OPerators for the TRIT MODE #
  1. These can be optimised by peekng at the binary value #
  2. These operators are as per "Balanced ternary" #
  3. Warning: "both" is ignored as it isn't Ternary #

OP LT = (TRIT a,b)BOOL: a EQ false AND b NE false OR a EQ maybe AND b EQ true,

  LE = (TRIT a,b)BOOL: a EQ b OR a LT b,
  EQ = (TRIT a,b)BOOL: trit OF a = trit OF b,
  NE = (TRIT a,b)BOOL: NOT (a EQ b),
  GE = (TRIT a,b)BOOL: NOT (a LT b),
  GT = (TRIT a,b)BOOL: NOT (a LE b);
  1. A solo, unique and rather confusing CMP OPerator #

PRIO CMP = 5; OP CMP = (TRIT a,b)TRIT:

 IF a < b THEN false
 ELIF a = b THEN maybe
 ELIF a > b THEN true
 FI;
  1. ASCII OPerators #

OP < = (TRIT a,b)BOOL: a LT b,

  <= = (TRIT a,b)BOOL: a LE b,
   = = (TRIT a,b)BOOL: a EQ b,
  /= = (TRIT a,b)BOOL: a NE b,
  >= = (TRIT a,b)BOOL: a GE b,
  >  = (TRIT a,b)BOOL: a GT b;
  1. Non ASCII OPerators

OP ≤ = (TRIT a,b)BOOL: a LE b,

  ≠ = (TRIT a,b)BOOL: a NE b,
  ≥ = (TRIT a,b)BOOL: a GE b;

OP - = (TRIT t)TRIT:

 IF   t=maybe THEN maybe
 ELIF t=true THEN false
 ELIF t=false THEN true
 ELSE raise value error(("invalid TRIT value",REPR t)); ~
 FI;
  1. Warning: This routine ASSIGNS "out" AND returns "carry" #

OP +:= = (REF TRIT out, TRIT arg)TRIT:

 IF   out = maybe THEN out :=  arg; maybe
 ELIF arg = maybe THEN # out:= out# arg
 ELIF out =  arg THEN out := -out; arg
 ELIF out = -arg THEN out:=maybe; maybe
 ELSE raise value error((REPR out," + ",REPR arg)); ~
 FI;

OP + = (TRIT a, b)TRIT:

 (TRIT out:=a; VOID(out+:=b); out);

OP - = (TRIT a, b)TRIT:

 a + -b;

OP * = (TRIT a, b)TRIT:

 IF   a = maybe OR b = maybe THEN maybe
 ELIF a = b THEN true
 ELSE false
 FI;

OP ODD = (TRIT t)BOOL:

 t /= maybe;

COMMENT

 Kleene logic truth tables:

END COMMENT

OP AND = (TRIT a,b)TRIT: (

 [,]TRIT(
   # ∧      maybe, true,  false,  #
   #maybe# (maybe, maybe, false),
   #true#  (maybe, true,  false),
   #false# (false, false, false)
 )[@0,@0][ABS trit OF a, ABS trit OF b]

);

OP OR = (TRIT a,b)TRIT: (

 [,]TRIT(
   # ∨      maybe, true, false,  #
   #maybe# (maybe, true, maybe),
   #true#  (true,  true, true),
   #false# (maybe, true, false)
 )[@0,@0][ABS trit OF a, ABS trit OF b]

);

PRIO IMPLIES = 1; # 1.9 # OP IMPLIES = (TRIT a,b)TRIT: (

 [,]TRIT(
   # ⊃      maybe, true, false, #
   #maybe# (maybe, true, maybe),
   #true#  (maybe, true, false),
   #false# (true,  true, true)
 )[@0,@0][ABS trit OF a, ABS trit OF b]

);

PRIO EQV = 1; # 1.8 # OP EQV = (TRIT a,b)TRIT: (

 [,]TRIT(
   # ≡      maybe, true,  false, #
   #maybe# (maybe, maybe, maybe),
   #true#  (maybe, true,  false),
   #false# (maybe, false, true)
 )[@0,@0][ABS trit OF a, ABS trit OF b]

);

  1. Non ASCII OPerators

OP ¬ = (TRIT a)TRIT: NOT b,

  ∨ = (TRIT a,b)TRIT: a OR b,
  ∧ = (TRIT a,b)TRIT: a AND b,
  & = (TRIT a,b)TRIT: a AND b,
  ⊃ = (TRIT a,b)TRIT: a IMPLIES b,
  ≡ = (TRIT a,b)TRIT: a EQV b;
  1. </lang>File: test_Ternary_logic.a68

<lang algol68>#!/usr/local/bin/a68g --script #

  1. -*- coding: utf-8 -*- #

PR READ "prelude/general.a68" PR PR READ "Ternary_logic.a68" PR

[]TRIT trits = (false, maybe, true);

FORMAT col fmt = $" "g" "$; FORMAT row fmt = $l3(f(col fmt)"|")f(col fmt)$; FORMAT row sep fmt = $l3("---+")"---"l$;

PROC row sep = VOID:

 printf(row sep fmt);

PROC title = (UTF op)VOID:(

 print(("Operator: ",op));
 printf((row fmt," ",REPR false, REPR maybe, REPR true))

);


PROC print bool op table = (STRING op name, PROC(TRIT,TRIT)BOOL op)VOID: (

 title(op name);
 FOR i FROM LWB trits TO UPB trits DO
   row sep;
   TRIT ti = trits[i];
   printf((col fmt, REPR ti));
   FOR j FROM LWB trits TO UPB trits DO
     TRIT tj = trits[j];
     printf(($"|"$, col fmt, op(ti,tj)))
   OD
 OD;
 print(new line)

);

PROC print trit op table = (STRING op name, PROC(TRIT,TRIT)TRIT op)VOID: (

 title(op name);
 FOR i FROM LWB trits TO UPB trits DO
   row sep;
   TRIT ti = trits[i];
   printf((col fmt, REPR ti));
   FOR j FROM LWB trits TO UPB trits DO
     TRIT tj = trits[j];
     printf(($"|"$, col fmt, REPR op(ti,tj)))
   OD
 OD;
 print(new line)

);

printf((

 $"Comparitive table of coercions:"l$,
 $"  TRIT BOOL         INT"l$

));

FOR it FROM LWB trits TO UPB trits DO

 TRIT t = trits[it];
 IF t = maybe THEN
   printf(($"  "g"  "$, REPR t, " ", INITINT t, $l$))
 ELSE
   printf(($"  "g"  "$, REPR t, B    t, INITINT t, $l$))
 FI

OD;

printf((

 $l"Specific test of the IMPLIES operator:"l$,
 $"  "g" implies "g" is "b("not ","")"a contradiction!"l$,
   B false,    B false,    B(false IMPLIES false),
   B false,    B true,     B(false IMPLIES true),
   B false,    REPR maybe, B(false IMPLIES maybe),
   B true,     B false,    B(true  IMPLIES false),
   B true,     B true,     B(true  IMPLIES true),
   REPR maybe, Btrue,      B(maybe IMPLIES true),
 $"  "g" implies "g" is "g" a contradiction!"l$,
   B true,     REPR maybe, REPR (true  IMPLIES maybe),
   REPR maybe, B false,    REPR (maybe IMPLIES false),
   REPR maybe, REPR maybe, REPR (maybe IMPLIES maybe),
 $l$

));

printf($l"Kleene logic truth table samples:"l$);

print trit op table("CMP", (TRIT a,b)TRIT: a CMP b); print trit op table("EQV", (TRIT a,b)TRIT: a EQV b); print trit op table("IMPLIES", (TRIT a,b)TRIT: a IMPLIES b); print trit op table("AND", (TRIT a,b)TRIT: a AND b); print trit op table("OR", (TRIT a,b)TRIT: a OR b) CO; print trit op table("+", (TRIT a,b)TRIT: a + b); print trit op table("-", (TRIT a,b)TRIT: a - b); print trit op table("*", (TRIT a,b)TRIT: a * b); print bool op table("EQ", (TRIT a,b)BOOL: a EQ b); print bool op table("<=", (TRIT a,b)BOOL: a <= b) END CO</lang> Output:

Comparitive table of coercions:
  TRIT BOOL         INT
  ⌊    F             -1  
  ?                  +0  
  ⌈    T             +1  

Specific test of the IMPLIES operator:
  F implies F is not a contradiction!
  F implies T is not a contradiction!
  F implies ? is not a contradiction!
  T implies F is a contradiction!
  T implies T is not a contradiction!
  ? implies T is not a contradiction!
  T implies ? is ? a contradiction!
  ? implies F is ? a contradiction!
  ? implies ? is ? a contradiction!


Kleene logic truth table samples:
Operator: CMP
   | ⌊ | ? | ⌈ 
---+---+---+---
 ⌊ | ? | ⌊ | ⌊ 
---+---+---+---
 ? | ⌈ | ? | ⌊ 
---+---+---+---
 ⌈ | ⌈ | ⌈ | ? 
Operator: EQV
   | ⌊ | ? | ⌈ 
---+---+---+---
 ⌊ | ⌈ | ? | ⌊ 
---+---+---+---
 ? | ? | ? | ? 
---+---+---+---
 ⌈ | ⌊ | ? | ⌈ 
Operator: IMPLIES
   | ⌊ | ? | ⌈ 
---+---+---+---
 ⌊ | ⌈ | ⌈ | ⌈ 
---+---+---+---
 ? | ? | ? | ⌈ 
---+---+---+---
 ⌈ | ⌊ | ? | ⌈ 
Operator: AND
   | ⌊ | ? | ⌈ 
---+---+---+---
 ⌊ | ⌊ | ⌊ | ⌊ 
---+---+---+---
 ? | ⌊ | ? | ? 
---+---+---+---
 ⌈ | ⌊ | ? | ⌈ 
Operator: OR
   | ⌊ | ? | ⌈ 
---+---+---+---
 ⌊ | ⌊ | ? | ⌈ 
---+---+---+---
 ? | ? | ? | ⌈ 
---+---+---+---
 ⌈ | ⌈ | ⌈ | ⌈ 

C

Implementing logic using lookup tables. <lang c>#include <stdio.h>

typedef enum {

 TRITTRUE,  /* In this enum, equivalent to integer value 0 */
 TRITMAYBE, /* In this enum, equivalent to integer value 1 */
 TRITFALSE  /* In this enum, equivalent to integer value 2 */

} trit;

/* We can trivially find the result of the operation by passing

  the trinary values as indeces into the lookup tables' arrays. */

trit tritNot[3] = {TRITFALSE , TRITMAYBE, TRITTRUE}; trit tritAnd[3][3] = { {TRITTRUE, TRITMAYBE, TRITFALSE},

                      {TRITMAYBE, TRITMAYBE, TRITFALSE},
                      {TRITFALSE, TRITFALSE, TRITFALSE} };

trit tritOr[3][3] = { {TRITTRUE, TRITTRUE, TRITTRUE},

                     {TRITTRUE, TRITMAYBE, TRITMAYBE},
                     {TRITTRUE, TRITMAYBE, TRITFALSE} };

trit tritThen[3][3] = { { TRITTRUE, TRITMAYBE, TRITFALSE},

                       { TRITTRUE, TRITMAYBE, TRITMAYBE},
                       { TRITTRUE, TRITTRUE, TRITTRUE } };

trit tritEquiv[3][3] = { { TRITTRUE, TRITMAYBE, TRITFALSE},

                        { TRITMAYBE, TRITMAYBE, TRITMAYBE},
                        { TRITFALSE, TRITMAYBE, TRITTRUE } };

/* Everything beyond here is just demonstration */

const char* tritString[3] = {"T", "?", "F"};

void demo_binary_op(trit operator[3][3], char* name) {

 trit operand1 = TRITTRUE; /* Declare. Initialize for CYA */
 trit operand2 = TRITTRUE; /* Declare. Initialize for CYA */
 /* Blank line */
 printf("\n");
 /* Demo this operator */
 for( operand1 = TRITTRUE; operand1 <= TRITFALSE; ++operand1 )
 {
   for( operand2 = TRITTRUE; operand2 <= TRITFALSE; ++operand2 )
   {
     printf("%s %s %s: %s\n", tritString[operand1],
                              name,
                              tritString[operand2],
                              tritString[operator[operand1][operand2]]);
   }
 }

}

int main() {

 trit op1 = TRITTRUE; /* Declare. Initialize for CYA */
 trit op2 = TRITTRUE; /* Declare. Initialize for CYA */

 /* Demo 'not' */
 for( op1 = TRITTRUE; op1 <= TRITFALSE; ++op1 )
 {
   printf("Not %s: %s\n", tritString[op1], tritString[tritNot[op1]]);
 }
 demo_binary_op(tritAnd, "And");
 demo_binary_op(tritOr, "Or");
 demo_binary_op(tritThen, "Then");
 demo_binary_op(tritEquiv, "Equiv");


 return 0;

}</lang>

Output: <lang text>Not T: F Not ?: ? Not F: T

T And T: T T And ?: ? T And F: F ? And T: ? ? And ?: ? ? And F: F F And T: F F And ?: F F And F: F

T Or T: T T Or ?: T T Or F: T ? Or T: T ? Or ?: ? ? Or F: ? F Or T: T F Or ?: ? F Or F: F

T Then T: T T Then ?: ? T Then F: F ? Then T: T ? Then ?: ? ? Then F: ? F Then T: T F Then ?: T F Then F: T

T Equiv T: T T Equiv ?: ? T Equiv F: F ? Equiv T: ? ? Equiv ?: ? ? Equiv F: ? F Equiv T: F F Equiv ?: ? F Equiv F: T</lang>

J

The designers of J felt that user defined types were harmful, so that part of the task will not be supported here.

Instead:

true: 1 false: 0 maybe: 0.5

<lang j>not=: -. and=: <. or =: >. if =: (-.@[ >. ])"0 eq =: (1 - -:@(= -.) >. |@-)"0</lang>

Example use:

<lang j> not 0 0.5 1 1 0.5 0

  0 0.5 1 and/ 0 0.5 1

0 0 0 0 0.5 0.5 0 0.5 1

  0 0.5 1 or/ 0 0.5 1
 0 0.5 1

0.5 0.5 1

 1   1 1
  0 0.5 1 if/ 0 0.5 1
 1   1 1

0.5 0.5 1

 0 0.5 1
  0 0.5 1 eq/ 0 0.5 1
 1 0.5   0

0.5 0.5 0.5

 0 0.5   1</lang>

Note that this implementation is a special case of "fuzzy logic" (using a limited set of values).

Java

This example is incorrect. Please fix the code and remove this message.

Details: MAYBE AND FALSE is FALSE.

Works with: Java version 1.5+

<lang java5>public class Logic{ public static enum Trit{ TRUE, MAYBE, FALSE;

public Trit and(Trit other){ if(this == TRUE){ return other; }else if(this == MAYBE){ return MAYBE; }else{ return FALSE; } }

public Trit or(Trit other){ if(this == TRUE){ return TRUE; }else if(this == MAYBE){ return (other == TRUE) ? TRUE : MAYBE; }else{ return other; } }

public Trit tIf(Trit other){ if(this == TRUE){ return other; }else if(this == MAYBE){ return (other == TRUE) ? TRUE : MAYBE; }else{ return TRUE; } }

public Trit not(){ if(this == TRUE){ return FALSE; }else if(this == MAYBE){ return MAYBE; }else{ return TRUE; } }

public Trit equals(Trit other){ if(this == TRUE){ return other; }else if(this == MAYBE){ return MAYBE; }else{ return other.not(); } } } public static void main(String[] args){ for(Trit a:Trit.values()){ System.out.println("not " + a + ": " + a.not()); } for(Trit a:Trit.values()){ for(Trit b:Trit.values()){ System.out.println(a+" and "+b+": "+a.and(b)+ "\t "+a+" or "+b+": "+a.or(b)+ "\t "+a+" implies "+b+": "+a.tIf(b)+ "\t "+a+" = "+b+": "+a.equals(b)); } } } }</lang> Output:

not TRUE: FALSE
not MAYBE: MAYBE
not FALSE: TRUE
TRUE and TRUE: TRUE	 TRUE or TRUE: TRUE	 TRUE implies TRUE: TRUE	 TRUE = TRUE: TRUE
TRUE and MAYBE: MAYBE	 TRUE or MAYBE: TRUE	 TRUE implies MAYBE: MAYBE	 TRUE = MAYBE: MAYBE
TRUE and FALSE: FALSE	 TRUE or FALSE: TRUE	 TRUE implies FALSE: FALSE	 TRUE = FALSE: FALSE
MAYBE and TRUE: MAYBE	 MAYBE or TRUE: TRUE	 MAYBE implies TRUE: TRUE	 MAYBE = TRUE: MAYBE
MAYBE and MAYBE: MAYBE	 MAYBE or MAYBE: MAYBE	 MAYBE implies MAYBE: MAYBE	 MAYBE = MAYBE: MAYBE
MAYBE and FALSE: MAYBE	 MAYBE or FALSE: MAYBE	 MAYBE implies FALSE: MAYBE	 MAYBE = FALSE: MAYBE
FALSE and TRUE: FALSE	 FALSE or TRUE: TRUE	 FALSE implies TRUE: TRUE	 FALSE = TRUE: FALSE
FALSE and MAYBE: FALSE	 FALSE or MAYBE: MAYBE	 FALSE implies MAYBE: TRUE	 FALSE = MAYBE: MAYBE
FALSE and FALSE: FALSE	 FALSE or FALSE: FALSE	 FALSE implies FALSE: TRUE	 FALSE = FALSE: TRUE

Perl 6

Works with: niecza

<lang perl6>enum Trit <Foo Moo Too>;

multi prefix:<¬> ($a) { Trit(1-($a-1)) }

multi infix:<∧> ($a,$b) { $a min $b } multi infix:<∨> ($a,$b) { $a max $b }

multi infix:<→> ($a,$b) { ¬$a max $b } multi infix:<≡> ($a,$b) { Trit(1 + ($a-1) * ($b-1)) }

say '¬'; say "Too {¬Too}"; say "Moo {¬Moo}"; say "Foo {¬Foo}";

sub tbl (&op,$name) {

   say ;
   say "$name   Too Moo Foo";
   say "   ╔═══════════";
   say "Too║{op Too,Too} {op Too,Moo} {op Too,Foo}";
   say "Moo║{op Moo,Too} {op Moo,Moo} {op Moo,Foo}";
   say "Foo║{op Foo,Too} {op Foo,Moo} {op Foo,Foo}";

}

tbl(&infix:<∧>, '∧'); tbl(&infix:<∨>, '∨'); tbl(&infix:<→>, '→'); tbl(&infix:<≡>, '≡');</lang> Output:

¬
Too Foo
Moo Moo
Foo Too

∧   Too Moo Foo
   ╔═══════════
Too║Too Moo Foo
Moo║Moo Moo Foo
Foo║Foo Foo Foo

∨   Too Moo Foo
   ╔═══════════
Too║Too Too Too
Moo║Too Moo Moo
Foo║Too Moo Foo

→   Too Moo Foo
   ╔═══════════
Too║Too Moo Foo
Moo║Too Moo Moo
Foo║Too Too Too

≡   Too Moo Foo
   ╔═══════════
Too║Too Moo Foo
Moo║Moo Moo Moo
Foo║Foo Moo Too

Python

In Python, the keywords 'and', 'not', and 'or' are coerced to always work as boolean operators. I have therefore overloaded the boolean bitwise operators &, |, ^ to provide the required functionality. <lang python>class Trit(int):

   def __new__(cls, value):
       if value == 'TRUE':
           value = 1
       elif value == 'FALSE':
           value = 0
       elif value == 'MAYBE':
           value = -1
       return super(Trit, cls).__new__(cls, value // (abs(value) or 1)) 
   def __repr__(self):
       if self > 0:
           return 'TRUE'
       elif self == 0:
           return 'FALSE'
       return 'MAYBE'
   def __str__(self):
       return repr(self)
   def __bool__(self):
       if self > 0:
           return True
       elif self == 0:
           return False
       else:
           raise ValueError("invalid literal for bool(): '%s'" % self)
   def __or__(self, other):
       if isinstance(other, Trit):
           return _ttable[(self, other)][1]
       else:
           try:
               return _ttable[(self, Trit(bool(other)))][1]
           except:
               return NotImplemented
   def __ror__(self, other):
       if isinstance(other, Trit):
           return _ttable[(self, other)][1]
       else:
           try:
               return _ttable[(self, Trit(bool(other)))][1]
           except:
               return NotImplemented
   def __and__(self, other):
       if isinstance(other, Trit):
           return _ttable[(self, other)][0]
       else:
           try:
               return _ttable[(self, Trit(bool(other)))][0]
           except:
               return NotImplemented
   def __rand__(self, other):
       if isinstance(other, Trit):
           return _ttable[(self, other)][0]
       else:
           try:
               return _ttable[(self, Trit(bool(other)))][0]
           except:
               return NotImplemented
   def __xor__(self, other):
       if isinstance(other, Trit):
           return _ttable[(self, other)][2]
       else:
           try:
               return _ttable[(self, Trit(bool(other)))][2]
           except:
               return NotImplemented
   def __rxor__(self, other):
       if isinstance(other, Trit):
           return _ttable[(self, other)][2]
       else:
           try:
               return _ttable[(self, Trit(bool(other)))][2]
           except:
               return NotImplemented
   def __invert__(self):
       return _ttable[self]
   
   def __getattr__(self, name):
       if name in ('_n', 'flip'):
           # So you can do x._n == x.flip; the inverse of x
           # In Python 'not' is strictly boolean so we can't write `not x`
           # Same applies to keywords 'and' and 'or'.
           return _ttable[self]
       else:
           raise AttributeError 


TRUE, FALSE, MAYBE = Trit(1), Trit(0), Trit(-1)

_ttable = {

   #    A: -> flip_A
        TRUE: FALSE,
       FALSE:  TRUE,
       MAYBE: MAYBE,
   #     (A, B): -> (A_and_B, A_or_B, A_xor_B)
       (MAYBE, MAYBE): (MAYBE, MAYBE, MAYBE),
       (MAYBE, FALSE): (FALSE, MAYBE, MAYBE),
       (MAYBE,  TRUE): (MAYBE,  TRUE, MAYBE),
       (FALSE, MAYBE): (FALSE, MAYBE, MAYBE),
       (FALSE, FALSE): (FALSE, FALSE, FALSE),
       (FALSE,  TRUE): (FALSE,  TRUE,  TRUE),
       ( TRUE, MAYBE): (MAYBE,  TRUE, MAYBE),
       ( TRUE, FALSE): (FALSE,  TRUE,  TRUE),
       ( TRUE,  TRUE): ( TRUE,  TRUE, FALSE),
   }


values = ('FALSE', 'TRUE ', 'MAYBE')

print("\nTrit logical inverse, '~'") for a in values:

   expr = '~%s' % a
   print('  %s = %s' % (expr, eval(expr)))

for op, ophelp in (('&', 'and'), ('|', 'or'), ('^', 'exclusive-or')):

   print("\nTrit logical %s, '%s'" % (ophelp, op))
   for a in values:
       for b in values:
           expr = '%s %s %s' % (a, op, b)
           print('  %s = %s' % (expr, eval(expr)))</lang>
Output
Trit logical inverse, '~'
  ~FALSE = TRUE
  ~TRUE  = FALSE
  ~MAYBE = MAYBE

Trit logical and, '&'
  FALSE & FALSE = FALSE
  FALSE & TRUE  = FALSE
  FALSE & MAYBE = FALSE
  TRUE  & FALSE = FALSE
  TRUE  & TRUE  = TRUE
  TRUE  & MAYBE = MAYBE
  MAYBE & FALSE = FALSE
  MAYBE & TRUE  = MAYBE
  MAYBE & MAYBE = MAYBE

Trit logical or, '|'
  FALSE | FALSE = FALSE
  FALSE | TRUE  = TRUE
  FALSE | MAYBE = MAYBE
  TRUE  | FALSE = TRUE
  TRUE  | TRUE  = TRUE
  TRUE  | MAYBE = TRUE
  MAYBE | FALSE = MAYBE
  MAYBE | TRUE  = TRUE
  MAYBE | MAYBE = MAYBE

Trit logical exclusive-or, '^'
  FALSE ^ FALSE = FALSE
  FALSE ^ TRUE  = TRUE
  FALSE ^ MAYBE = MAYBE
  TRUE  ^ FALSE = TRUE
  TRUE  ^ TRUE  = FALSE
  TRUE  ^ MAYBE = MAYBE
  MAYBE ^ FALSE = MAYBE
  MAYBE ^ TRUE  = MAYBE
  MAYBE ^ MAYBE = MAYBE
Extra doodling in the Python shell
>>> values = (TRUE, FALSE, MAYBE)
>>> for a in values:
	for b in values:
		assert (a & ~b) | (b & ~a) == a ^ b

		
>>> 

Ruby

Ruby, like Smalltalk, has two boolean classes: TrueClass for true and FalseClass for false. We add a third class, MaybeClass for MAYBE, and define ternary logic for all three classes.

We keep !a, a & b and so on for binary logic. We add !a.trit, a.trit & b and so on for ternary logic. The code for !a.trit uses def !, which works with Ruby 1.9, but fails as a syntax error with Ruby 1.8.

Works with: Ruby version 1.9

<lang ruby># trit.rb - ternary logic

  1. http://rosettacode.org/wiki/Ternary_logic

require 'singleton'

  1. MAYBE, the only instance of MaybeClass, enables a system of ternary
  2. logic using TrueClass#trit, MaybeClass#trit and FalseClass#trit.
  3. !a.trit # ternary not
  4. a.trit & b # ternary and
  5. a.trit | b # ternary or
  6. a.trit ^ b # ternary exclusive or
  7. a.trit == b # ternary equal
  8. Though +true+ and +false+ are internal Ruby values, +MAYBE+ is not.
  9. Programs may want to assign +maybe = MAYBE+ in scopes that use
  10. ternary logic. Then programs can use +true+, +maybe+ and +false+.

class MaybeClass

 include Singleton
 #  maybe.to_s  # => "maybe"
 def to_s; "maybe"; end

end

MAYBE = MaybeClass.instance

class TrueClass

 TritMagic = Object.new
 class << TritMagic
   def index; 0; end
   def !; false; end
   def & other; other; end
   def | other; true; end
   def ^ other; [false, MAYBE, true][other.trit.index]; end
   def == other; other; end
 end
 # Performs ternary logic. See MaybeClass.
 #  !true.trit        # => false
 #  true.trit & obj   # => obj
 #  true.trit | obj   # => true
 #  true.trit ^ obj   # => false, maybe or true
 #  true.trit == obj  # => obj
 def trit; TritMagic; end

end

class MaybeClass

 TritMagic = Object.new
 class << TritMagic
   def index; 1; end
   def !; MAYBE; end
   def & other; [MAYBE, MAYBE, false][other.trit.index]; end
   def | other; [true, MAYBE, MAYBE][other.trit.index]; end
   def ^ other; MAYBE; end
   def == other; MAYBE; end
 end
 # Performs ternary logic. See MaybeClass.
 #  !maybe.trit        # => maybe
 #  maybe.trit & obj   # => maybe or false
 #  maybe.trit | obj   # => true or maybe
 #  maybe.trit ^ obj   # => maybe
 #  maybe.trit == obj  # => maybe
 def trit; TritMagic; end

end

class FalseClass

 TritMagic = Object.new
 class << TritMagic
   def index; 2; end
   def !; true; end
   def & other; false; end
   def | other; other; end
   def ^ other; other; end
   def == other; [false, MAYBE, true][other.trit.index]; end
 end
 # Performs ternary logic. See MaybeClass.
 #  !false.trit        # => true
 #  false.trit & obj   # => false
 #  false.trit | obj   # => obj
 #  false.trit ^ obj   # => obj
 #  false.trit == obj  # => false, maybe or true
 def trit; TritMagic; end

end</lang>

This IRB session shows ternary not, and, or, equal.

<lang ruby>$ irb irb(main):001:0> require './trit' => true irb(main):002:0> maybe = MAYBE => maybe irb(main):003:0> !true.trit => false irb(main):004:0> !maybe.trit => maybe irb(main):005:0> maybe.trit & false => false irb(main):006:0> maybe.trit | true => true irb(main):007:0> false.trit == true => false irb(main):008:0> false.trit == maybe => maybe</lang>

This program shows all 9 outcomes from a.trit ^ b.

<lang ruby>require 'trit' maybe = MAYBE

[true, maybe, false].each do |a|

 [true, maybe, false].each do |b|
   printf "%5s ^ %5s => %5s\n", a, b, a.trit ^ b
 end

end</lang>

$ ruby -I. trit-xor.rb
 true ^  true => false
 true ^ maybe => maybe
 true ^ false =>  true
maybe ^  true => maybe
maybe ^ maybe => maybe
maybe ^ false => maybe
false ^  true =>  true
false ^ maybe => maybe
false ^ false => false