Skip to content

Commit 8fca831

Browse files
committed
week4 Master lahendused
1 parent c5dea37 commit 8fca831

4 files changed

Lines changed: 502 additions & 0 deletions

File tree

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package week4.baselangs.bool;
2+
3+
import week4.baselangs.bool.ast.*;
4+
5+
import java.util.Set;
6+
import java.util.TreeSet;
7+
8+
import static week4.baselangs.bool.BoolMaster.DecisionTree.FALSE;
9+
import static week4.baselangs.bool.BoolMaster.DecisionTree.TRUE;
10+
import static week4.baselangs.bool.ast.BoolNode.not;
11+
import static week4.baselangs.bool.ast.BoolNode.or;
12+
13+
public class BoolMaster {
14+
15+
// Meil on antud järgnev klass andmete kogumiseks:
16+
public static final class Stats {
17+
private final Set<Character> variables = new TreeSet<>();
18+
private boolean found = false;
19+
20+
public Set<Character> getVariables() {
21+
return variables;
22+
}
23+
24+
public boolean containsImp() {
25+
return found;
26+
}
27+
28+
public void addVar(BoolVar node) {
29+
variables.add(node.name());
30+
}
31+
32+
public void foundImp() {
33+
found = true;
34+
}
35+
}
36+
37+
// Analüüsida avaldist kasutades Stats klassi meetodid.
38+
public static Stats analyze(BoolNode node) {
39+
Stats stats = new Stats();
40+
analyze(node, stats);
41+
return stats;
42+
}
43+
44+
private static void analyze(BoolNode node, Stats stats) {
45+
switch (node) {
46+
case BoolVar var -> stats.addVar(var);
47+
case BoolNot(BoolNode exp) -> analyze(exp, stats);
48+
case BoolOr(BoolNode left, BoolNode right) -> {
49+
analyze(left, stats);
50+
analyze(right, stats);
51+
}
52+
case BoolImp(BoolNode antedecent, BoolNode consequent) -> {
53+
stats.foundImp();
54+
analyze(antedecent, stats);
55+
analyze(consequent, stats);
56+
}
57+
}
58+
}
59+
60+
61+
// Teisendada avaldises implikatsiooni teiste operaatoritega.
62+
public static BoolNode transform(BoolNode node) {
63+
return switch (node) {
64+
case BoolVar var -> var;
65+
case BoolNot(BoolNode expr) -> not(transform(expr));
66+
case BoolOr(BoolNode left, BoolNode right) -> or(transform(left), transform(right));
67+
case BoolImp(BoolNode antedecent, BoolNode consequent) -> or(
68+
not(transform(antedecent)),
69+
transform(consequent)
70+
);
71+
};
72+
}
73+
74+
75+
// Teha avaldisest otsustuspuu.
76+
public static DecisionTree createDecisionTree(BoolNode node) {
77+
return switch (node) {
78+
case BoolVar(char name) -> DecisionTree.decision(name, TRUE, FALSE);
79+
case BoolNot(BoolNode expr) -> createDecisionTree(expr).compose(FALSE, TRUE);
80+
case BoolOr(BoolNode left, BoolNode right) ->
81+
createDecisionTree(left).compose(TRUE, createDecisionTree(right));
82+
case BoolImp(BoolNode antedecent, BoolNode consequent) -> {
83+
DecisionTree cons = createDecisionTree(consequent);
84+
yield createDecisionTree(antedecent).compose(cons, TRUE);
85+
}
86+
};
87+
}
88+
89+
/**
90+
* Otsustuspuu on tõeväärtusavaldise puukujuline esitus, kus vahetipudeks on ainult muutujad.
91+
* See esitab see avaldise tõeväärtustabelit, vt. meetod eval!
92+
* <p>
93+
* Puu loomiseks võib kasutada meetod compose, mis jätkab otsustuspuud
94+
* x.compose(y,z) tulemuseks on selline puu, et
95+
* kui x on tõene, siis on tulemuseks y.
96+
* vastasel korral on tulemuseks z.
97+
* Seega on näiteks avaldise x eitus lihtsalt x.compose(FALSE, TRUE).
98+
*/
99+
public abstract static class DecisionTree {
100+
101+
public static final DecisionTree TRUE = new TrueNode();
102+
public static final DecisionTree FALSE = new FalseNode();
103+
104+
public static DecisionTree decision(char c, DecisionTree tc, DecisionTree fc) {
105+
return new DecisionNode(c, tc, fc);
106+
}
107+
108+
public abstract boolean eval(Set<Character> tv);
109+
110+
public abstract DecisionTree compose(DecisionTree trueDecision, DecisionTree falseDecision);
111+
112+
113+
private static class DecisionNode extends DecisionTree {
114+
private final Character variable;
115+
private final DecisionTree trueTree;
116+
private final DecisionTree falseTree;
117+
118+
public DecisionNode(Character variable, DecisionTree trueTree, DecisionTree falseTree) {
119+
this.variable = variable;
120+
this.trueTree = trueTree;
121+
this.falseTree = falseTree;
122+
}
123+
124+
@Override
125+
public boolean eval(Set<Character> tv) {
126+
return tv.contains(variable) ? trueTree.eval(tv) : falseTree.eval(tv);
127+
}
128+
129+
@Override
130+
public DecisionTree compose(DecisionTree trueDecision, DecisionTree falseDecision) {
131+
return new DecisionNode(variable,
132+
trueTree.compose(trueDecision, falseDecision),
133+
falseTree.compose(trueDecision, falseDecision));
134+
}
135+
136+
@Override
137+
public String toString() {
138+
return "(" + variable + " ? " + trueTree + " : " + falseTree + ")";
139+
}
140+
}
141+
142+
private static class TrueNode extends DecisionTree {
143+
@Override
144+
public boolean eval(Set<Character> tv) {
145+
return true;
146+
}
147+
148+
@Override
149+
public DecisionTree compose(DecisionTree trueDecision, DecisionTree falseDecision) {
150+
return trueDecision;
151+
}
152+
153+
@Override
154+
public String toString() {
155+
return "true";
156+
}
157+
}
158+
159+
private static class FalseNode extends DecisionTree {
160+
@Override
161+
public boolean eval(Set<Character> tv) {
162+
return false;
163+
}
164+
165+
@Override
166+
public DecisionTree compose(DecisionTree trueDecision, DecisionTree falseDecision) {
167+
return falseDecision;
168+
}
169+
170+
@Override
171+
public String toString() {
172+
return "false";
173+
}
174+
}
175+
176+
}
177+
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package week4.baselangs.expr;
2+
3+
import week4.baselangs.expr.ast.*;
4+
5+
import java.util.*;
6+
7+
import static week4.baselangs.expr.ast.ExprNode.*;
8+
9+
public class ExprMaster {
10+
11+
/**
12+
* Kogub kokku kõik tippudes esinevad arvud (järjestatult vasakult paremale).
13+
*/
14+
public static List<Integer> valueList(ExprNode node) {
15+
return switch (node) {
16+
case ExprNum(int value) -> Collections.singletonList(value);
17+
case ExprNeg(ExprNode expr) -> valueList(expr);
18+
case ExprAdd(ExprNode left, ExprNode right) -> {
19+
List<Integer> result = new ArrayList<>();
20+
result.addAll(valueList(left));
21+
result.addAll(valueList(right));
22+
yield result;
23+
}
24+
case ExprDiv(ExprNode numerator, ExprNode denominator) -> {
25+
List<Integer> result = new ArrayList<>();
26+
result.addAll(valueList(numerator));
27+
result.addAll(valueList(denominator));
28+
yield result;
29+
}
30+
};
31+
}
32+
33+
/**
34+
* Asendab jagamised nende väärtustega.
35+
*/
36+
public static ExprNode replaceDivs(ExprNode node) {
37+
return switch (node) {
38+
case ExprNum num ->
39+
num; // Võime lihtsalt sama tipu tagastada, kuna teda ei saa muuta.
40+
case ExprNeg(ExprNode expr) ->
41+
neg(replaceDivs(expr)); // Siin peab koopia tegema, sest miinusmärgi all teeme teisendusi.
42+
case ExprAdd(ExprNode left, ExprNode right) ->
43+
add(replaceDivs(left), replaceDivs(right)); // Jällegi uus tipp teisendatud alampuudega.
44+
case ExprDiv div ->
45+
num(div.eval()); // Siin lõpuks toimub sisuline teisendus!
46+
};
47+
}
48+
49+
/**
50+
* Kogub kokku kõik tippudes esinevad arvud (järjestatult vasakult paremale) niimoodi, et summa oleks sama nagu avaldisel.
51+
* Eeldab, et jagamisi ei esine.
52+
*/
53+
public static List<Integer> signedValueList(ExprNode node) {
54+
return switch (node) {
55+
case ExprNum(int value) -> Collections.singletonList(value);
56+
case ExprNeg(ExprNode expr) ->
57+
signedValueList(expr).stream().map(i -> -i).toList(); // Kõikide elementide märke tuleb lihtsalt muuta
58+
case ExprAdd(ExprNode left, ExprNode right) -> {
59+
List<Integer> result = new ArrayList<>();
60+
result.addAll(signedValueList(left));
61+
result.addAll(signedValueList(right));
62+
yield result;
63+
}
64+
case ExprDiv _ -> throw new UnsupportedOperationException();
65+
};
66+
}
67+
68+
/**
69+
* Elimineerib miinused.
70+
*/
71+
public static ExprNode elimNegs(ExprNode node) {
72+
return elimNegs(node, 1);
73+
}
74+
75+
private static ExprNode elimNegs(ExprNode node, int sign) {
76+
return switch (node) {
77+
case ExprNum(int value) -> num(sign * value);
78+
case ExprNeg(ExprNode expr) -> elimNegs(expr, -sign);
79+
case ExprAdd(ExprNode left, ExprNode right) ->
80+
add(elimNegs(left, sign), elimNegs(right, sign));
81+
case ExprDiv(ExprNode numerator, ExprNode denominator) ->
82+
div(elimNegs(numerator, sign), elimNegs(denominator, 1));
83+
};
84+
}
85+
86+
/**
87+
* Trükib avaldise "ilusalt", st. võimalikult väheste vajalike sulgudega.
88+
*/
89+
public static String pretty(ExprNode node) {
90+
int priority = priorityOf(node);
91+
return switch (node) {
92+
case ExprNum(int value) -> Integer.toString(value);
93+
case ExprNeg(ExprNode expr) -> "-" + pretty(expr, priority);
94+
case ExprAdd(ExprNode left, ExprNode right) ->
95+
pretty(left, priority) + "+" + pretty(right, priority);
96+
case ExprDiv(ExprNode numerator, ExprNode denominator) ->
97+
pretty(numerator, priority) + "/" + pretty(denominator, priority + 1); // vasakassotsiatiivsus
98+
};
99+
}
100+
101+
/**
102+
* Otsustab konteksti põhjal, kas sulge on vaja või mitte.
103+
*/
104+
private static String pretty(ExprNode node, int contextPriority) {
105+
if (priorityOf(node) < contextPriority)
106+
return '(' + pretty(node) + ')';
107+
else
108+
return pretty(node);
109+
}
110+
111+
/**
112+
* Tagastab tehte prioriteedi.
113+
*/
114+
static int priorityOf(ExprNode node) {
115+
return switch (node) {
116+
case ExprAdd _ -> 1; // kõige madalama prioriteediga
117+
case ExprDiv _ -> 2;
118+
case ExprNeg _ -> 3;
119+
case ExprNum _ -> 4; // kõige kõrgema prioriteediga
120+
};
121+
}
122+
}
123+

0 commit comments

Comments
 (0)