Decision tables: Difference between revisions
m (→{{header|Tcl}}: formatting) |
(→{{header|Tcl}}: Add Python solution) |
||
Line 73: | Line 73: | ||
Ensure printer software is installed |
Ensure printer software is installed |
||
Check/replace ink</pre> |
Check/replace ink</pre> |
||
=={{header|Python}}== |
|||
<lang python> |
|||
''' |
|||
Create a Decision table then use it |
|||
''' |
|||
def dt_creator(): |
|||
print("\n\nCREATING THE DECISION TABLE\n") |
|||
conditions = input("Input conditions, in order, separated by commas: ") |
|||
conditions = [c.strip() for c in conditions.split(',')] |
|||
print( ("\nThat was %s conditions:\n " % len(conditions)) |
|||
+ '\n '.join("%i: %s" % x for x in enumerate(conditions, 1)) ) |
|||
print("\nInput an action, a semicolon, then a list of tuples of rules that trigger it. End with a blank line") |
|||
action2rules, action = [], ' ' |
|||
while action: |
|||
action = input("%i: " % (len(action2rules) + 1)).strip() |
|||
if action: |
|||
name, _, rules = [x.strip() for x in action.partition(';')] |
|||
rules = eval(rules) |
|||
assert all(len(rule) == len(conditions) for rule in rules), \ |
|||
"The number of conditions in a rule to trigger this action is wrong" |
|||
action2rules.append((name, rules)) |
|||
actions = [x[0] for x in action2rules] |
|||
# Map condition to actions |
|||
rule2actions = dict((y,[]) for y in set(sum((x[1] for x in action2rules), []))) |
|||
for action, rules in action2rules: |
|||
for r in rules: |
|||
rule2actions[r].append( action ) |
|||
return conditions, rule2actions |
|||
def dt_user(dt, default=['Pray!']): |
|||
conditions, rule2actions = dt |
|||
print("\n\nUSING THE DECISION TABLE\n") |
|||
rule = tuple((int('y' == input("%s? (Answer y if statement is true or n): " % c)) for c in conditions)) |
|||
print("Try this:\n " + '\n '.join(rule2actions.get(rule, default))) |
|||
if __name__ == '__main__': |
|||
dt = dt_creator() |
|||
dt_user(dt) |
|||
dt_user(dt) |
|||
dt_user(dt)</lang> |
|||
'''Sample Run''' |
|||
<pre> |
|||
CREATING THE DECISION TABLE |
|||
Input conditions, in order, separated by commas: Printer does not print, A red light is flashing, Printer is unrecognised |
|||
That was 3 conditions: |
|||
1: Printer does not print |
|||
2: A red light is flashing |
|||
3: Printer is unrecognised |
|||
Input an action, a semicolon, then a list of tuples of rules that trigger it. End with a blank line |
|||
1: Check the power cable; [(1,0,1)] |
|||
2: Check the printer-computer cable; [(1,1,1), (1,0,1)] |
|||
3: Ensure printer software is installed; [(1,1,1), (1,0,1), (0,1,1), (0,0,1)] |
|||
4: Check/replace ink; [(1,1,1), (1,1,0), (0,1,1), (0,1,0)] |
|||
5: Check for paper jam; [(1,1,0), (1,0,0)] |
|||
6: |
|||
USING THE DECISION TABLE |
|||
Printer does not print? (Answer y if statement is true or n): n |
|||
A red light is flashing? (Answer y if statement is true or n): y |
|||
Printer is unrecognised? (Answer y if statement is true or n): y |
|||
Try this: |
|||
Ensure printer software is installed |
|||
Check/replace ink |
|||
USING THE DECISION TABLE |
|||
Printer does not print? (Answer y if statement is true or n): y |
|||
A red light is flashing? (Answer y if statement is true or n): n |
|||
Printer is unrecognised? (Answer y if statement is true or n): y |
|||
Try this: |
|||
Check the power cable |
|||
Check the printer-computer cable |
|||
Ensure printer software is installed |
|||
USING THE DECISION TABLE |
|||
Printer does not print? (Answer y if statement is true or n): n |
|||
A red light is flashing? (Answer y if statement is true or n): n |
|||
Printer is unrecognised? (Answer y if statement is true or n): n |
|||
Try this: |
|||
Pray!</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
Revision as of 20:52, 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
Python
<lang python> Create a Decision table then use it
def dt_creator():
print("\n\nCREATING THE DECISION TABLE\n") conditions = input("Input conditions, in order, separated by commas: ") conditions = [c.strip() for c in conditions.split(',')] print( ("\nThat was %s conditions:\n " % len(conditions)) + '\n '.join("%i: %s" % x for x in enumerate(conditions, 1)) ) print("\nInput an action, a semicolon, then a list of tuples of rules that trigger it. End with a blank line") action2rules, action = [], ' ' while action: action = input("%i: " % (len(action2rules) + 1)).strip() if action: name, _, rules = [x.strip() for x in action.partition(';')] rules = eval(rules) assert all(len(rule) == len(conditions) for rule in rules), \ "The number of conditions in a rule to trigger this action is wrong" action2rules.append((name, rules)) actions = [x[0] for x in action2rules] # Map condition to actions rule2actions = dict((y,[]) for y in set(sum((x[1] for x in action2rules), []))) for action, rules in action2rules: for r in rules: rule2actions[r].append( action ) return conditions, rule2actions
def dt_user(dt, default=['Pray!']):
conditions, rule2actions = dt print("\n\nUSING THE DECISION TABLE\n") rule = tuple((int('y' == input("%s? (Answer y if statement is true or n): " % c)) for c in conditions)) print("Try this:\n " + '\n '.join(rule2actions.get(rule, default)))
if __name__ == '__main__':
dt = dt_creator() dt_user(dt) dt_user(dt) dt_user(dt)</lang>
Sample Run
CREATING THE DECISION TABLE Input conditions, in order, separated by commas: Printer does not print, A red light is flashing, Printer is unrecognised That was 3 conditions: 1: Printer does not print 2: A red light is flashing 3: Printer is unrecognised Input an action, a semicolon, then a list of tuples of rules that trigger it. End with a blank line 1: Check the power cable; [(1,0,1)] 2: Check the printer-computer cable; [(1,1,1), (1,0,1)] 3: Ensure printer software is installed; [(1,1,1), (1,0,1), (0,1,1), (0,0,1)] 4: Check/replace ink; [(1,1,1), (1,1,0), (0,1,1), (0,1,0)] 5: Check for paper jam; [(1,1,0), (1,0,0)] 6: USING THE DECISION TABLE Printer does not print? (Answer y if statement is true or n): n A red light is flashing? (Answer y if statement is true or n): y Printer is unrecognised? (Answer y if statement is true or n): y Try this: Ensure printer software is installed Check/replace ink USING THE DECISION TABLE Printer does not print? (Answer y if statement is true or n): y A red light is flashing? (Answer y if statement is true or n): n Printer is unrecognised? (Answer y if statement is true or n): y Try this: Check the power cable Check the printer-computer cable Ensure printer software is installed USING THE DECISION TABLE Printer does not print? (Answer y if statement is true or n): n A red light is flashing? (Answer y if statement is true or n): n Printer is unrecognised? (Answer y if statement is true or n): n Try this: Pray!
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 tcl>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