合(析)取范式转主合(析)取范式--》Java实现
这次老师布置了如下上机作业,不限语言。思前想后,问了几个大神,说了一堆不知道什么鬼的算法名称。。。。
经过一番百度,发现Java可以包含库然后使用JavaScript的一些函数,其中eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。http://www.w3school.com.cn/jsref/jsref_eval.asp 想到了如下解决办法。。
1 import javax.script.ScriptEngine; 2 import javax.script.ScriptEngineManager; 3 import javax.script.ScriptException; 4 import java.util.*; 5 6 7 /** 8 * Creat by Qjm 9 */ 10 public class Test { 11 12 //A-Z 65-90 13 //a-z 97-122 14 public static Map<Integer, Integer> m = new HashMap<Integer, Integer>(); 15 public static int count = 0; 16 public static List<String> list_true_value = new ArrayList<String>(); 17 18 /** 19 * 获取主和取(析取)范式 20 * String @param problem 要转换的命题公式 21 * int @param flag 标记(1 :和取 2:析取) 22 * 23 * @return 24 * @throws ScriptException 25 */ 26 public static String getMainNormalForm(String problem, int flag) throws ScriptException { 27 ScriptEngineManager manager = new ScriptEngineManager(); 28 ScriptEngine engine = manager.getEngineByName("js"); 29 problem = problem.trim().toUpperCase(); 30 char[] pro_arr = problem.toCharArray(); 31 Set<String> s_variable = new LinkedHashSet<String>(); 32 for (char temp : pro_arr) { 33 if (temp >= 65 && temp <= 90) { 34 s_variable.add(temp + ""); 35 //System.out.println(temp+""); 36 } 37 } 38 39 40 String[] variables = (String[]) s_variable.toArray(new String[0]); 41 Arrays.sort(variables); 42 System.out.println("\n真值指派顺序:" + Arrays.toString(variables)); 43 method(engine, variables, variables.length, problem); 44 String result1 = "Σ("; 45 String result2 = "∏("; 46 String temp1 = ""; 47 String temp2 = ""; 48 for (Integer i : m.keySet()) { 49 if (m.get(i) == 1) { 50 result1 += i + ","; 51 temp1 += "m" + i + "∨"; 52 } else { 53 result2 += i + ","; 54 temp2 += "M" + i + "∧"; 55 } 56 } 57 result1 = result1.substring(0, result1.length() - 1); 58 result2 = result2.substring(0, result2.length() - 1); 59 temp1 = temp1.substring(0, temp1.length() - 1); 60 temp2 = temp2.substring(0, temp2.length() - 1); 61 result1 += ")"; 62 result2 += ")"; 63 64 count = 0; 65 m.clear(); 66 67 return flag == 1 ? temp2 + "\n" + result2 : temp1 + "\n" + result1; 68 } 69 70 71 /** 72 * 递归函数,给每一个命题变远指派真值,得出每一种真值指派的结果 73 * ScriptEngine @param engine 74 * String[] @param variables 75 * int @param times 命题变元的个数 76 * String @param problem 要转换的命题公式 77 * 将注释掉的打印输出取消,可以看到该算法的具体执行过程 78 * @throws ScriptException 79 */ 80 public static void method(ScriptEngine engine, String[] variables, int times, String problem) throws ScriptException { 81 if (times < 1) { 82 Integer result = (Integer) engine.eval(problem); 83 84 //System.out.println("" + problem + ""); 85 //System.out.println("结果类型:" + result.getClass().getName() + ",计算结果:" + result + ""); 86 m.put(count, result); 87 count++; 88 //System.out.println(transMapToString(m)); 89 return; 90 } else { 91 for (int i = 0; i < 2; i++) { 92 engine.put(variables[variables.length - times], i); 93 //System.out.println("\ntimes : " + times + "\nbool :" + variables[times - 1] + "--->" + i); 94 method(engine, variables, times - 1, problem); 95 } 96 } 97 98 } 99 100 /** 101 /** 102 * 方法名称:transMapToString 103 * 传入参数:map 104 * 返回值:String 形如 username'chenziwen^password'1234 105 */ 106 public static String transMapToString(Map map) { 107 Set s = map.keySet(); 108 String temp = ""; 109 for (Object i : s) { 110 temp += "key : " + (Integer) i + "\t\tvalue : " + map.get(i) + "\n"; 111 } 112 return temp; 113 } 114 115 116 public static void main(String[] args) throws ScriptException { 117 String problem = ""; 118 int flag = 0; 119 Scanner s = new Scanner(System.in); 120 while (true) { 121 System.out.println("请输入要转换的合(析)取范式(&->合取 |->析取 !->非):"); 122 try{ 123 problem = s.next(); 124 }catch(NoSuchElementException exception){ 125 System.out.println("mdzz"); 126 System.exit(0); 127 } 128 System.out.println("待转化的命题公式:" + problem); 129 System.out.println("以下是对应的真值表"); 130 System.out.println("主合取范式: " + getMainNormalForm(problem, 1)); 131 System.out.println("主析取范式: " + getMainNormalForm(problem, 2) + "\n"); 132 } 133 134 } 135 }
基本思路是:
- 首先,engine.eval(problem); 可以直接把字符串当作数学表达式运行
- 然后,
engine.put(variables[variables.length - times], i); 可以直接把字符串中的指定字符换为目标数据,,这样就可以实现对表达式的每一个命题变元的真值指派。
- 再利用递归函数实现类似真值表法的遍历, 再记录每一次真值指派的表达式的真值,再化为对应的表达式。
以下是运行截图