Decision tables: Difference between revisions
(→{{header|D}}: + D) |
(→Tcl: Added implementation) |
||
Line 73: | Line 73: | ||
Ensure printer software is installed |
Ensure printer software is installed |
||
Check/replace ink</pre> |
Check/replace ink</pre> |
||
=={{header|Tcl}}== |
|||
<lang tcl>package require TclOO |
|||
#http://rosettacode.org/wiki/Keyboard_Input/Obtain_a_Y_or_N_response#Tcl |
|||
proc yesno {{message "Press Y or N to continue"}} { |
|||
fconfigure stdin -blocking 0 |
|||
exec stty raw |
|||
read stdin ; # flush |
|||
puts -nonewline "${message}: " |
|||
flush stdout |
|||
while {![eof stdin]} { |
|||
set c [string tolower [read stdin 1]] |
|||
if {$c eq "y" || $c eq "n"} break |
|||
} |
|||
puts [string toupper $c] |
|||
exec stty -raw |
|||
fconfigure stdin -blocking 1 |
|||
return [expr {$c eq "y"}] |
|||
} |
|||
oo::class create DecisionTable { |
|||
variable qlist responses |
|||
constructor {questions responseMap} { |
|||
set qlist $questions |
|||
set responses $responseMap |
|||
} |
|||
method consult {} { |
|||
set idx 0 |
|||
foreach q $qlist { |
|||
set answer [yesno "$q? \[y/n\]"] |
|||
set idx [expr {$idx*2 + (1-$answer)}] |
|||
} |
|||
foreach {msg map} $responses { |
|||
# Allow a column to be omitted; magic! |
|||
if {"0[lindex $map $idx]"} { |
|||
puts $msg |
|||
} |
|||
} |
|||
} |
|||
}</lang> |
|||
Demonstration: |
|||
<lang>DecisionTable create printerDiagnosisTable { |
|||
"Printer does not print" |
|||
"A red light is flashing" |
|||
"Printer is unrecognised" |
|||
} { |
|||
"Check the power cable" {0 0 1} |
|||
"Check the printer-computer cable" {1 0 1} |
|||
"Ensure printer software is installed" {1 0 1 0 1 0 1} |
|||
"Check/replace ink" {1 1 0 0 1 1} |
|||
"Check for paper jam" {0 1 0 1} |
|||
} |
|||
printerDiagnosisTable consult</lang> |
|||
Output: |
|||
<pre> |
|||
Printer does not print? [y/n]: N |
|||
A red light is flashing? [y/n]: Y |
|||
Printer is unrecognised? [y/n]: Y |
|||
Ensure printer software is installed |
|||
Check/replace ink |
|||
</pre> |
Revision as of 11:50, 25 January 2011
Decision Tables are a precise yet compact way to model complicated logic.
Demonstrate how your language implements decision tables. Use the example of Printer Troubleshooting given in the Wikipedia article.
D
<lang d>import std.stdio, std.algorithm, std.exception, std.string ;
struct Decision {
immutable string[] conds ; immutable string[] actions ; immutable bool[][] rules ;
this(string[] c, string[] a, bool[][] q) { assert(c.length < 32, "max 31 test conditions") ; immutable(bool)[][] r ; q.length = 2^^c.length ; // fix rules foreach(ref e ; q) r ~= e.idup ; conds = c.idup ; actions = a.idup ; rules = assumeUnique(r) ; // cast to immutable, Contract style }
string[] test(bool[] tested, string NoMatchMsg = "it is fine :)") { auto idx = reduce!"2*a+b"(map!"a?1:0"(tested.reverse)) ;// get index string[] rightActions ; foreach(i, e ; rules[idx]) if(e) rightActions ~= actions[i] ; if(rightActions.length > 0) return rightActions ; return [NoMatchMsg] ; }
void consult() { bool[] query ; string answer ; foreach(c;conds) { write(c,"? [y=yes/others=no] ") ; readf("%s\n", &answer) ; query ~= (answer.length > 0 && answer.tolower[0..1] == "y") ; } writeln(test(query).join("\n")) ; }
}
void main() {
Decision d = Decision( ["Printer is unrecognised", "A red light is flashing", "Printer does not print"], ["Check the power cable", "Check the printer-computer cable", "Ensure printer software is installed", "Check/replace ink", "Check for paper jam"], [[false], // others is _false_ , save hand-writing [false, false, true], [false, false, false, true], [false, false, true, true], [false, false, false, false, true], [true, true, true], [false, false, false, true, true], [false, true, true, true]] ) ; d.consult() ;
}</lang> Sample output:
Printer is unrecognised? [y=yes/others=no] y A red light is flashing? [y=yes/others=no] y Printer does not print? [y=yes/others=no] n Ensure printer software is installed Check/replace ink
Tcl
<lang tcl>package require TclOO
proc yesno Template:Message "Press Y or N to continue" {
fconfigure stdin -blocking 0 exec stty raw read stdin ; # flush puts -nonewline "${message}: " flush stdout while {![eof stdin]} { set c [string tolower [read stdin 1]] if {$c eq "y" || $c eq "n"} break } puts [string toupper $c] exec stty -raw fconfigure stdin -blocking 1 return [expr {$c eq "y"}]
}
oo::class create DecisionTable {
variable qlist responses constructor {questions responseMap} {
set qlist $questions set responses $responseMap
}
method consult {} {
set idx 0 foreach q $qlist { set answer [yesno "$q? \[y/n\]"] set idx [expr {$idx*2 + (1-$answer)}] } foreach {msg map} $responses { # Allow a column to be omitted; magic! if {"0[lindex $map $idx]"} { puts $msg } }
}
}</lang> Demonstration: <lang>DecisionTable create printerDiagnosisTable {
"Printer does not print" "A red light is flashing" "Printer is unrecognised"
} {
"Check the power cable" {0 0 1} "Check the printer-computer cable" {1 0 1} "Ensure printer software is installed" {1 0 1 0 1 0 1} "Check/replace ink" {1 1 0 0 1 1} "Check for paper jam" {0 1 0 1}
} printerDiagnosisTable consult</lang> Output:
Printer does not print? [y/n]: N A red light is flashing? [y/n]: Y Printer is unrecognised? [y/n]: Y Ensure printer software is installed Check/replace ink