Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
264
Task/24-game-Solve/Java/24-game-solve.java
Normal file
264
Task/24-game-Solve/Java/24-game-solve.java
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
import java.util.*;
|
||||
|
||||
public class Game24Player {
|
||||
final String[] patterns = {"nnonnoo", "nnonono", "nnnoono", "nnnonoo",
|
||||
"nnnnooo"};
|
||||
final String ops = "+-*/^";
|
||||
|
||||
String solution;
|
||||
List<Integer> digits;
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Game24Player().play();
|
||||
}
|
||||
|
||||
void play() {
|
||||
digits = getSolvableDigits();
|
||||
|
||||
Scanner in = new Scanner(System.in);
|
||||
while (true) {
|
||||
System.out.print("Make 24 using these digits: ");
|
||||
System.out.println(digits);
|
||||
System.out.println("(Enter 'q' to quit, 's' for a solution)");
|
||||
System.out.print("> ");
|
||||
|
||||
String line = in.nextLine();
|
||||
if (line.equalsIgnoreCase("q")) {
|
||||
System.out.println("\nThanks for playing");
|
||||
return;
|
||||
}
|
||||
|
||||
if (line.equalsIgnoreCase("s")) {
|
||||
System.out.println(solution);
|
||||
digits = getSolvableDigits();
|
||||
continue;
|
||||
}
|
||||
|
||||
char[] entry = line.replaceAll("[^*+-/)(\\d]", "").toCharArray();
|
||||
|
||||
try {
|
||||
validate(entry);
|
||||
|
||||
if (evaluate(infixToPostfix(entry))) {
|
||||
System.out.println("\nCorrect! Want to try another? ");
|
||||
digits = getSolvableDigits();
|
||||
} else {
|
||||
System.out.println("\nNot correct.");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.out.printf("%n%s Try again.%n", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validate(char[] input) throws Exception {
|
||||
int total1 = 0, parens = 0, opsCount = 0;
|
||||
|
||||
for (char c : input) {
|
||||
if (Character.isDigit(c))
|
||||
total1 += 1 << (c - '0') * 4;
|
||||
else if (c == '(')
|
||||
parens++;
|
||||
else if (c == ')')
|
||||
parens--;
|
||||
else if (ops.indexOf(c) != -1)
|
||||
opsCount++;
|
||||
if (parens < 0)
|
||||
throw new Exception("Parentheses mismatch.");
|
||||
}
|
||||
|
||||
if (parens != 0)
|
||||
throw new Exception("Parentheses mismatch.");
|
||||
|
||||
if (opsCount != 3)
|
||||
throw new Exception("Wrong number of operators.");
|
||||
|
||||
int total2 = 0;
|
||||
for (int d : digits)
|
||||
total2 += 1 << d * 4;
|
||||
|
||||
if (total1 != total2)
|
||||
throw new Exception("Not the same digits.");
|
||||
}
|
||||
|
||||
boolean evaluate(char[] line) throws Exception {
|
||||
Stack<Float> s = new Stack<>();
|
||||
try {
|
||||
for (char c : line) {
|
||||
if ('0' <= c && c <= '9')
|
||||
s.push((float) c - '0');
|
||||
else
|
||||
s.push(applyOperator(s.pop(), s.pop(), c));
|
||||
}
|
||||
} catch (EmptyStackException e) {
|
||||
throw new Exception("Invalid entry.");
|
||||
}
|
||||
return (Math.abs(24 - s.peek()) < 0.001F);
|
||||
}
|
||||
|
||||
float applyOperator(float a, float b, char c) {
|
||||
switch (c) {
|
||||
case '+':
|
||||
return a + b;
|
||||
case '-':
|
||||
return b - a;
|
||||
case '*':
|
||||
return a * b;
|
||||
case '/':
|
||||
return b / a;
|
||||
default:
|
||||
return Float.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
List<Integer> randomDigits() {
|
||||
Random r = new Random();
|
||||
List<Integer> result = new ArrayList<>(4);
|
||||
for (int i = 0; i < 4; i++)
|
||||
result.add(r.nextInt(9) + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
List<Integer> getSolvableDigits() {
|
||||
List<Integer> result;
|
||||
do {
|
||||
result = randomDigits();
|
||||
} while (!isSolvable(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean isSolvable(List<Integer> digits) {
|
||||
Set<List<Integer>> dPerms = new HashSet<>(4 * 3 * 2);
|
||||
permute(digits, dPerms, 0);
|
||||
|
||||
int total = 4 * 4 * 4;
|
||||
List<List<Integer>> oPerms = new ArrayList<>(total);
|
||||
permuteOperators(oPerms, 4, total);
|
||||
|
||||
StringBuilder sb = new StringBuilder(4 + 3);
|
||||
|
||||
for (String pattern : patterns) {
|
||||
char[] patternChars = pattern.toCharArray();
|
||||
|
||||
for (List<Integer> dig : dPerms) {
|
||||
for (List<Integer> opr : oPerms) {
|
||||
|
||||
int i = 0, j = 0;
|
||||
for (char c : patternChars) {
|
||||
if (c == 'n')
|
||||
sb.append(dig.get(i++));
|
||||
else
|
||||
sb.append(ops.charAt(opr.get(j++)));
|
||||
}
|
||||
|
||||
String candidate = sb.toString();
|
||||
try {
|
||||
if (evaluate(candidate.toCharArray())) {
|
||||
solution = postfixToInfix(candidate);
|
||||
return true;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
sb.setLength(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String postfixToInfix(String postfix) {
|
||||
class Expression {
|
||||
String op, ex;
|
||||
int prec = 3;
|
||||
|
||||
Expression(String e) {
|
||||
ex = e;
|
||||
}
|
||||
|
||||
Expression(String e1, String e2, String o) {
|
||||
ex = String.format("%s %s %s", e1, o, e2);
|
||||
op = o;
|
||||
prec = ops.indexOf(o) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
Stack<Expression> expr = new Stack<>();
|
||||
|
||||
for (char c : postfix.toCharArray()) {
|
||||
int idx = ops.indexOf(c);
|
||||
if (idx != -1) {
|
||||
|
||||
Expression r = expr.pop();
|
||||
Expression l = expr.pop();
|
||||
|
||||
int opPrec = idx / 2;
|
||||
|
||||
if (l.prec < opPrec)
|
||||
l.ex = '(' + l.ex + ')';
|
||||
|
||||
if (r.prec <= opPrec)
|
||||
r.ex = '(' + r.ex + ')';
|
||||
|
||||
expr.push(new Expression(l.ex, r.ex, "" + c));
|
||||
} else {
|
||||
expr.push(new Expression("" + c));
|
||||
}
|
||||
}
|
||||
return expr.peek().ex;
|
||||
}
|
||||
|
||||
char[] infixToPostfix(char[] infix) throws Exception {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Stack<Integer> s = new Stack<>();
|
||||
try {
|
||||
for (char c : infix) {
|
||||
int idx = ops.indexOf(c);
|
||||
if (idx != -1) {
|
||||
if (s.isEmpty())
|
||||
s.push(idx);
|
||||
else {
|
||||
while (!s.isEmpty()) {
|
||||
int prec2 = s.peek() / 2;
|
||||
int prec1 = idx / 2;
|
||||
if (prec2 >= prec1)
|
||||
sb.append(ops.charAt(s.pop()));
|
||||
else
|
||||
break;
|
||||
}
|
||||
s.push(idx);
|
||||
}
|
||||
} else if (c == '(') {
|
||||
s.push(-2);
|
||||
} else if (c == ')') {
|
||||
while (s.peek() != -2)
|
||||
sb.append(ops.charAt(s.pop()));
|
||||
s.pop();
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
while (!s.isEmpty())
|
||||
sb.append(ops.charAt(s.pop()));
|
||||
|
||||
} catch (EmptyStackException e) {
|
||||
throw new Exception("Invalid entry.");
|
||||
}
|
||||
return sb.toString().toCharArray();
|
||||
}
|
||||
|
||||
void permute(List<Integer> lst, Set<List<Integer>> res, int k) {
|
||||
for (int i = k; i < lst.size(); i++) {
|
||||
Collections.swap(lst, i, k);
|
||||
permute(lst, res, k + 1);
|
||||
Collections.swap(lst, k, i);
|
||||
}
|
||||
if (k == lst.size())
|
||||
res.add(new ArrayList<>(lst));
|
||||
}
|
||||
|
||||
void permuteOperators(List<List<Integer>> res, int n, int total) {
|
||||
for (int i = 0, npow = n * n; i < total; i++)
|
||||
res.add(Arrays.asList((i / npow), (i % npow) / n, i % n));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue