September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -1,87 +0,0 @@
# This program tries to find some way to turn four digits into an arithmetic
# expression that adds up to 24.
#
# Example solution for 5, 7, 8, 8:
# (((8 + 7) * 8) / 5)
solve_24_game = (digits...) ->
# Create an array of objects for our helper functions
arr = for digit in digits
{
val: digit
expr: digit
}
combo4 arr...
combo4 = (a, b, c, d) ->
arr = [a, b, c, d]
# Reduce this to a three-node problem by combining two
# nodes from the array.
permutations = [
[0, 1, 2, 3]
[0, 2, 1, 3]
[0, 3, 1, 2]
[1, 2, 0, 3]
[1, 3, 0, 2]
[2, 3, 0, 1]
]
for permutation in permutations
[i, j, k, m] = permutation
for combo in combos arr[i], arr[j]
answer = combo3 combo, arr[k], arr[m]
return answer if answer
null
combo3 = (a, b, c) ->
arr = [a, b, c]
permutations = [
[0, 1, 2]
[0, 2, 1]
[1, 2, 0]
]
for permutation in permutations
[i, j, k] = permutation
for combo in combos arr[i], arr[j]
answer = combo2 combo, arr[k]
return answer if answer
null
combo2 = (a, b) ->
for combo in combos a, b
return combo.expr if combo.val == 24
null
combos = (a, b) ->
[
val: a.val + b.val
expr: "(#{a.expr} + #{b.expr})"
,
val: a.val * b.val
expr: "(#{a.expr} * #{b.expr})"
,
val: a.val - b.val
expr: "(#{a.expr} - #{b.expr})"
,
val: b.val - a.val
expr: "(#{b.expr} - #{a.expr})"
,
val: a.val / b.val
expr: "(#{a.expr} / #{b.expr})"
,
val: b.val / a.val
expr: "(#{b.expr} / #{a.expr})"
,
]
# test
do ->
rand_digit = -> 1 + Math.floor (9 * Math.random())
for i in [1..15]
a = rand_digit()
b = rand_digit()
c = rand_digit()
d = rand_digit()
solution = solve_24_game a, b, c, d
console.log "Solution for #{[a,b,c,d]}: #{solution ? 'no solution'}"

View file

@ -1,16 +0,0 @@
> coffee 24_game.coffee
Solution for 8,3,1,8: ((1 + 8) * (8 / 3))
Solution for 6,9,5,7: (6 - ((5 - 7) * 9))
Solution for 4,2,1,1: no solution
Solution for 3,5,1,3: (((3 + 5) * 1) * 3)
Solution for 6,4,1,7: ((7 - (4 - 1)) * 6)
Solution for 8,1,3,1: (((8 + 1) - 1) * 3)
Solution for 6,1,3,3: (((6 + 1) * 3) + 3)
Solution for 7,1,5,6: (((7 - 1) * 5) - 6)
Solution for 4,2,3,1: ((3 + 1) * (4 + 2))
Solution for 8,8,5,8: ((5 * 8) - (8 + 8))
Solution for 3,8,4,1: ((1 - (3 - 8)) * 4)
Solution for 6,4,3,8: ((8 - (6 / 3)) * 4)
Solution for 2,1,8,7: (((2 * 8) + 1) + 7)
Solution for 5,2,7,5: ((2 * 7) + (5 + 5))
Solution for 2,4,8,9: ((9 - (2 + 4)) * 8)

View file

@ -0,0 +1,99 @@
// version 1.1.3
import java.util.Random
const val N_CARDS = 4
const val SOLVE_GOAL = 24
const val MAX_DIGIT = 9
class Frac(val num: Int, val den: Int)
enum class OpType { NUM, ADD, SUB, MUL, DIV }
class Expr(
var op: OpType = OpType.NUM,
var left: Expr? = null,
var right: Expr? = null,
var value: Int = 0
)
fun showExpr(e: Expr?, prec: OpType, isRight: Boolean) {
if (e == null) return
val op = when (e.op) {
OpType.NUM -> { print(e.value); return }
OpType.ADD -> " + "
OpType.SUB -> " - "
OpType.MUL -> " x "
OpType.DIV -> " / "
}
if ((e.op == prec && isRight) || e.op < prec) print("(")
showExpr(e.left, e.op, false)
print(op)
showExpr(e.right, e.op, true)
if ((e.op == prec && isRight) || e.op < prec) print(")")
}
fun evalExpr(e: Expr?): Frac {
if (e == null) return Frac(0, 1)
if (e.op == OpType.NUM) return Frac(e.value, 1)
val l = evalExpr(e.left)
val r = evalExpr(e.right)
return when (e.op) {
OpType.ADD -> Frac(l.num * r.den + l.den * r.num, l.den * r.den)
OpType.SUB -> Frac(l.num * r.den - l.den * r.num, l.den * r.den)
OpType.MUL -> Frac(l.num * r.num, l.den * r.den)
OpType.DIV -> Frac(l.num * r.den, l.den * r.num)
else -> throw IllegalArgumentException("Unknown op: ${e.op}")
}
}
fun solve(ea: Array<Expr?>, len: Int): Boolean {
if (len == 1) {
val final = evalExpr(ea[0])
if (final.num == final.den * SOLVE_GOAL && final.den != 0) {
showExpr(ea[0], OpType.NUM, false)
return true
}
}
val ex = arrayOfNulls<Expr>(N_CARDS)
for (i in 0 until len - 1) {
for (j in i + 1 until len) ex[j - 1] = ea[j]
val node = Expr()
ex[i] = node
for (j in i + 1 until len) {
node.left = ea[i]
node.right = ea[j]
for (k in OpType.values().drop(1)) {
node.op = k
if (solve(ex, len - 1)) return true
}
node.left = ea[j]
node.right = ea[i]
node.op = OpType.SUB
if (solve(ex, len - 1)) return true
node.op = OpType.DIV
if (solve(ex, len - 1)) return true
ex[j] = ea[j]
}
ex[i] = ea[i]
}
return false
}
fun solve24(n: IntArray) =
solve (Array(N_CARDS) { Expr(value = n[it]) }, N_CARDS)
fun main(args: Array<String>) {
val r = Random()
val n = IntArray(N_CARDS)
for (j in 0..9) {
for (i in 0 until N_CARDS) {
n[i] = 1 + r.nextInt(MAX_DIGIT)
print(" ${n[i]}")
}
print(": ")
println(if (solve24(n)) "" else "No solution")
}
}

View file

@ -1,35 +0,0 @@
editvar /modify -random- = <10
:a
editvar /newvar /withothervar /value=-random- /title=1
editvar /newvar /withothervar /value=-random- /title=2
editvar /newvar /withothervar /value=-random- /title=3
editvar /newvar /withothervar /value=-random- /title=4
printline These are your four digits: -1- -2- -3- -4-
printline Use an algorithm to make the number 24.
editvar /newvar /value=a /userinput=1 /title=Algorithm:
do -a-
if -a- /hasvalue 24 printline Your algorithm worked! & goto :b (
) else printline Your algorithm did not work.
editvar /newvar /value=b /userinput=1 /title=Do you want to see how you could have done it?
if -b- /hasvalue y goto :c else goto :b
:b
editvar /newvar /value=c /userinput=1 /title=Do you want to play again?
if -c- /hasvalue y goto :a else exitcurrentprogram
:c
editvar /newvar /value=do -1- + -2- + -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- - -2- + -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- / -2- + -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- * -2- + -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- - -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- / -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- * -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- + -3- - -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- + -3- / -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- + -3- * -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- - -2- - -3- - -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- / -2- / -3- / -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- * -2- * -3- * -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
:solve
printline you could have done it by doing -c-
stoptask
goto :b

View file

@ -1,11 +0,0 @@
These are your four digits: 1 4 5 2
Use an algorithm to make the number 24.
Algorithm: 4 + 2 - 5 + 1
Your algorithm did not work.
Do you want to play again? y
These are your four digits: 1 8 9 6
Use an algorithm to make the number 24.
Algorithm: 1 + 8 + 9 + 6
Your algorithm worked!
Do you want to play again? n

View file

@ -0,0 +1,165 @@
#[derive(Clone, Copy, Debug)]
enum Operator {
Sub,
Plus,
Mul,
Div,
}
#[derive(Clone, Debug)]
struct Factor {
content: String,
value: i32,
}
fn apply(op: Operator, left: &[Factor], right: &[Factor]) -> Vec<Factor> {
let mut ret = Vec::new();
for l in left.iter() {
for r in right.iter() {
use Operator::*;
ret.push(match op {
Sub if l.value > r.value => Factor {
content: format!("({} - {})", l.content, r.content),
value: l.value - r.value,
},
Plus => Factor {
content: format!("({} + {})", l.content, r.content),
value: l.value + r.value,
},
Mul => Factor {
content: format!("({} x {})", l.content, r.content),
value: l.value * r.value,
},
Div if l.value >= r.value && r.value > 0 && l.value % r.value == 0 => Factor {
content: format!("({} / {})", l.content, r.content),
value: l.value / r.value,
},
_ => continue,
})
}
}
ret
}
fn calc(op: [Operator; 3], numbers: [i32; 4]) -> Vec<Factor> {
fn calc(op: &[Operator], numbers: &[i32], acc: &[Factor]) -> Vec<Factor> {
use Operator::*;
if op.is_empty() {
return Vec::from(acc)
}
let mut ret = Vec::new();
let mono_factor = [Factor {
content: numbers[0].to_string(),
value: numbers[0],
}];
match op[0] {
Mul => ret.extend_from_slice(&apply(op[0], acc, &mono_factor)),
Div => {
ret.extend_from_slice(&apply(op[0], acc, &mono_factor));
ret.extend_from_slice(&apply(op[0], &mono_factor, acc));
},
Sub => {
ret.extend_from_slice(&apply(op[0], acc, &mono_factor));
ret.extend_from_slice(&apply(op[0], &mono_factor, acc));
},
Plus => ret.extend_from_slice(&apply(op[0], acc, &mono_factor)),
}
calc(&op[1..], &numbers[1..], &ret)
}
calc(&op, &numbers[1..], &[Factor { content: numbers[0].to_string(), value: numbers[0] }])
}
fn solutions(numbers: [i32; 4]) -> Vec<Factor> {
use std::collections::hash_set::HashSet;
let mut ret = Vec::new();
let mut hash_set = HashSet::new();
for ops in OpIter(0) {
for o in orders().iter() {
let numbers = apply_order(numbers, o);
let r = calc(ops, numbers);
ret.extend(r.into_iter().filter(|&Factor { value, ref content }| value == 24 && hash_set.insert(content.to_owned())))
}
}
ret
}
fn main() {
let mut numbers = Vec::new();
if let Some(input) = std::env::args().skip(1).next() {
for c in input.chars() {
if let Ok(n) = c.to_string().parse() {
numbers.push(n)
}
if numbers.len() == 4 {
let numbers = [numbers[0], numbers[1], numbers[2], numbers[3]];
let solutions = solutions(numbers);
let len = solutions.len();
if len == 0 {
println!("no solution for {}, {}, {}, {}", numbers[0], numbers[1], numbers[2], numbers[3]);
return
}
println!("solutions for {}, {}, {}, {}", numbers[0], numbers[1], numbers[2], numbers[3]);
for s in solutions {
println!("{}", s.content)
}
println!("{} solutions found", len);
return
}
}
} else {
println!("empty input")
}
}
struct OpIter (usize);
impl Iterator for OpIter {
type Item = [Operator; 3];
fn next(&mut self) -> Option<[Operator; 3]> {
use Operator::*;
const OPTIONS: [Operator; 4] = [Mul, Sub, Plus, Div];
if self.0 >= 1 << 6 {
return None
}
let f1 = OPTIONS[(self.0 & (3 << 4)) >> 4];
let f2 = OPTIONS[(self.0 & (3 << 2)) >> 2];
let f3 = OPTIONS[(self.0 & (3 << 0)) >> 0];
self.0 += 1;
Some([f1, f2, f3])
}
}
fn orders() -> [[usize; 4]; 24] {
[
[0, 1, 2, 3],
[0, 1, 3, 2],
[0, 2, 1, 3],
[0, 2, 3, 1],
[0, 3, 1, 2],
[0, 3, 2, 1],
[1, 0, 2, 3],
[1, 0, 3, 2],
[1, 2, 0, 3],
[1, 2, 3, 0],
[1, 3, 0, 2],
[1, 3, 2, 0],
[2, 0, 1, 3],
[2, 0, 3, 1],
[2, 1, 0, 3],
[2, 1, 3, 0],
[2, 3, 0, 1],
[2, 3, 1, 0],
[3, 0, 1, 2],
[3, 0, 2, 1],
[3, 1, 0, 2],
[3, 1, 2, 0],
[3, 2, 0, 1],
[3, 2, 1, 0]
]
}
fn apply_order(numbers: [i32; 4], order: &[usize; 4]) -> [i32; 4] {
[numbers[order[0]], numbers[order[1]], numbers[order[2]], numbers[order[3]]]
}

View file

@ -4,28 +4,29 @@ var formats = [
'(%d %s %d) %s (%d %s %d)',
'%d %s ((%d %s %d) %s %d)',
'%d %s (%d %s (%d %s %d))',
];
]
var op = %w( + - * / );
var operators = op.map { |a| op.map {|b| op.map {|c| "#{a} #{b} #{c}" } } }.flatten;
var op = %w( + - * / )
var operators = op.map { |a| op.map {|b| op.map {|c| "#{a} #{b} #{c}" } } }.flat
loop {
var input = Sys.scanln("Enter four integers or 'q' to exit: ");
input == 'q' && break;
var input = read("Enter four integers or 'q' to exit: ", String)
input == 'q' && break
input ~~ /^\h*[1-9]\h+[1-9]\h+[1-9]\h+[1-9]\h*$/ || (
say "Invalid input!"; next;
);
if (input !~ /^\h*[1-9]\h+[1-9]\h+[1-9]\h+[1-9]\h*$/) {
say "Invalid input!"
next
}
var n = input.split.map{.to_i};
var numbers = n.permute;
var n = input.split.map{.to_n}
var numbers = n.permutations
formats.each { |format|
numbers.each { |n|
operators.each { |operator|
var o = operator.split;
var str = (format % (n[0],o[0],n[1],o[1],n[2],o[2],n[3]));
eval(str) == 24 && say str;
var str = (format % (n[0],o[0],n[1],o[1],n[2],o[2],n[3]))
eval(str) == 24 && say str
}
}
}

View file

@ -1,56 +1,57 @@
var formats = [
{|a,b,c|
Hash.new(
Hash(
func => {|d,e,f,g| ((d.$a(e)).$b(f)).$c(g) },
format => "((%d #{a} %d) #{b} %d) #{c} %d"
)
},
{|a,b,c|
Hash.new(
Hash(
func => {|d,e,f,g| (d.$a((e.$b(f)))).$c(g) },
format => "(%d #{a} (%d #{b} %d)) #{c} %d",
)
},
{|a,b,c|
Hash.new(
Hash(
func => {|d,e,f,g| (d.$a(e)).$b(f.$c(g)) },
format => "(%d #{a} %d) #{b} (%d #{c} %d)",
)
},
{|a,b,c|
Hash.new(
Hash(
func => {|d,e,f,g| (d.$a(e)).$b(f.$c(g)) },
format => "(%d #{a} %d) #{b} (%d #{c} %d)",
)
},
{|a,b,c|
Hash.new(
Hash(
func => {|d,e,f,g| d.$a(e.$b(f.$c(g))) },
format => "%d #{a} (%d #{b} (%d #{c} %d))",
)
},
];
var op = %w( + - * / );
var op = %w( + - * / )
var blocks = op.map { |a| op.map { |b| op.map { |c| formats.map { |format|
format(a,b,c)
}}}}.flatten;
}}}}.flat
loop {
var input = Sys.scanln("Enter four integers or 'q' to exit: ");
input == 'q' && break;
input ~~ /^\h*[1-9]\h+[1-9]\h+[1-9]\h+[1-9]\h*$/ || (
say "Invalid input!"; next;
);
if (input !~ /^\h*[1-9]\h+[1-9]\h+[1-9]\h+[1-9]\h*$/) {
say "Invalid input!"
next
}
var n = input.split.map{.to_num};
var numbers = n.permute;
var n = input.split.map{.to_n}
var numbers = n.permutations
blocks.each { |block|
numbers.each { |n|
if (block{:func}.call(n...) == 24) {
say (block{:format} % (n...));
say (block{:format} % (n...))
}
}
}

View file

@ -0,0 +1,297 @@
BEGIN
CLASS EXPR;
BEGIN
REAL PROCEDURE POP;
BEGIN
IF STACKPOS > 0 THEN
BEGIN STACKPOS := STACKPOS - 1; POP := STACK(STACKPOS); END;
END POP;
PROCEDURE PUSH(NEWTOP); REAL NEWTOP;
BEGIN
STACK(STACKPOS) := NEWTOP;
STACKPOS := STACKPOS + 1;
END PUSH;
REAL PROCEDURE CALC(OPERATOR, ERR); CHARACTER OPERATOR; LABEL ERR;
BEGIN
REAL X, Y; X := POP; Y := POP;
IF OPERATOR = '+' THEN PUSH(Y + X)
ELSE IF OPERATOR = '-' THEN PUSH(Y - X)
ELSE IF OPERATOR = '*' THEN PUSH(Y * X)
ELSE IF OPERATOR = '/' THEN BEGIN
IF X = 0 THEN
BEGIN
EVALUATEDERR :- "DIV BY ZERO";
GOTO ERR;
END;
PUSH(Y / X);
END
ELSE
BEGIN
EVALUATEDERR :- "UNKNOWN OPERATOR";
GOTO ERR;
END
END CALC;
PROCEDURE READCHAR(CH); NAME CH; CHARACTER CH;
BEGIN
IF T.MORE THEN CH := T.GETCHAR ELSE CH := EOT;
END READCHAR;
PROCEDURE SKIPWHITESPACE(CH); NAME CH; CHARACTER CH;
BEGIN
WHILE (CH = SPACE) OR (CH = TAB) OR (CH = CR) OR (CH = LF) DO
READCHAR(CH);
END SKIPWHITESPACE;
PROCEDURE BUSYBOX(OP, ERR); INTEGER OP; LABEL ERR;
BEGIN
CHARACTER OPERATOR;
REAL NUMBR;
BOOLEAN NEGATIVE;
SKIPWHITESPACE(CH);
IF OP = EXPRESSION THEN
BEGIN
NEGATIVE := FALSE;
WHILE (CH = '+') OR (CH = '-') DO
BEGIN
IF CH = '-' THEN NEGATIVE := NOT NEGATIVE;
READCHAR(CH);
END;
BUSYBOX(TERM, ERR);
IF NEGATIVE THEN
BEGIN
NUMBR := POP; PUSH(0 - NUMBR);
END;
WHILE (CH = '+') OR (CH = '-') DO
BEGIN
OPERATOR := CH; READCHAR(CH);
BUSYBOX(TERM, ERR); CALC(OPERATOR, ERR);
END;
END
ELSE IF OP = TERM THEN
BEGIN
BUSYBOX(FACTOR, ERR);
WHILE (CH = '*') OR (CH = '/') DO
BEGIN
OPERATOR := CH; READCHAR(CH);
BUSYBOX(FACTOR, ERR); CALC(OPERATOR, ERR)
END
END
ELSE IF OP = FACTOR THEN
BEGIN
IF (CH = '+') OR (CH = '-') THEN
BUSYBOX(EXPRESSION, ERR)
ELSE IF (CH >= '0') AND (CH <= '9') THEN
BUSYBOX(NUMBER, ERR)
ELSE IF CH = '(' THEN
BEGIN
READCHAR(CH);
BUSYBOX(EXPRESSION, ERR);
IF CH = ')' THEN READCHAR(CH) ELSE GOTO ERR;
END
ELSE GOTO ERR;
END
ELSE IF OP = NUMBER THEN
BEGIN
NUMBR := 0;
WHILE (CH >= '0') AND (CH <= '9') DO
BEGIN
NUMBR := 10 * NUMBR + RANK(CH) - RANK('0'); READCHAR(CH);
END;
IF CH = '.' THEN
BEGIN
REAL FAKTOR;
READCHAR(CH);
FAKTOR := 10;
WHILE (CH >= '0') AND (CH <= '9') DO
BEGIN
NUMBR := NUMBR + (RANK(CH) - RANK('0')) / FAKTOR;
FAKTOR := 10 * FAKTOR;
READCHAR(CH);
END;
END;
PUSH(NUMBR);
END;
SKIPWHITESPACE(CH);
END BUSYBOX;
BOOLEAN PROCEDURE EVAL(INP); TEXT INP;
BEGIN
EVALUATEDERR :- NOTEXT;
STACKPOS := 0;
T :- COPY(INP.STRIP);
READCHAR(CH);
BUSYBOX(EXPRESSION, ERRORLABEL);
IF NOT T.MORE AND STACKPOS = 1 AND CH = EOT THEN
BEGIN
EVALUATED := POP;
EVAL := TRUE;
GOTO NOERRORLABEL;
END;
ERRORLABEL:
EVAL := FALSE;
IF EVALUATEDERR = NOTEXT THEN
EVALUATEDERR :- "INVALID EXPRESSION: " & INP;
NOERRORLABEL:
END EVAL;
REAL PROCEDURE RESULT;
RESULT := EVALUATED;
TEXT PROCEDURE ERR;
ERR :- EVALUATEDERR;
TEXT T;
INTEGER EXPRESSION;
INTEGER TERM;
INTEGER FACTOR;
INTEGER NUMBER;
CHARACTER TAB;
CHARACTER LF;
CHARACTER CR;
CHARACTER SPACE;
CHARACTER EOT;
CHARACTER CH;
REAL ARRAY STACK(0:31);
INTEGER STACKPOS;
REAL EVALUATED;
TEXT EVALUATEDERR;
EXPRESSION := 1;
TERM := 2;
FACTOR := 3;
NUMBER := 4;
TAB := CHAR(9);
LF := CHAR(10);
CR := CHAR(13);
SPACE := CHAR(32);
EOT := CHAR(0);
END EXPR;
INTEGER ARRAY DIGITS(1:4);
INTEGER SEED, I;
REF(EXPR) E;
INTEGER SOLUTION;
INTEGER D1,D2,D3,D4;
INTEGER O1,O2,O3;
TEXT OPS;
OPS :- "+-*/";
E :- NEW EXPR;
OUTTEXT("ENTER FOUR INTEGERS: ");
OUTIMAGE;
FOR I := 1 STEP 1 UNTIL 4 DO DIGITS(I) := ININT; !RANDINT(0, 9, SEED);
! DIGITS ;
FOR D1 := 1 STEP 1 UNTIL 4 DO
FOR D2 := 1 STEP 1 UNTIL 4 DO IF D2 <> D1 THEN
FOR D3 := 1 STEP 1 UNTIL 4 DO IF D3 <> D2 AND
D3 <> D1 THEN
FOR D4 := 1 STEP 1 UNTIL 4 DO IF D4 <> D3 AND
D4 <> D2 AND
D4 <> D1 THEN
! OPERATORS ;
FOR O1 := 1 STEP 1 UNTIL 4 DO
FOR O2 := 1 STEP 1 UNTIL 4 DO
FOR O3 := 1 STEP 1 UNTIL 4 DO
BEGIN
PROCEDURE P(FMT); TEXT FMT;
BEGIN
INTEGER PLUS;
TRY.SETPOS(1);
WHILE FMT.MORE DO
BEGIN
CHARACTER C;
C := FMT.GETCHAR;
IF (C >= '1') AND (C <= '4') THEN
BEGIN
INTEGER DIG; CHARACTER NCH;
DIG := IF C = '1' THEN DIGITS(D1)
ELSE IF C = '2' THEN DIGITS(D2)
ELSE IF C = '3' THEN DIGITS(D3)
ELSE DIGITS(D4);
NCH := CHAR( DIG + RANK('0') );
TRY.PUTCHAR(NCH);
END
ELSE IF C = '+' THEN
BEGIN
PLUS := PLUS + 1;
OPS.SETPOS(IF PLUS = 1 THEN O1 ELSE
IF PLUS = 2 THEN O2
ELSE O3);
TRY.PUTCHAR(OPS.GETCHAR);
END
ELSE IF (C = '(') OR (C = ')') OR (C = ' ') THEN
TRY.PUTCHAR(C)
ELSE
ERROR("ILLEGAL EXPRESSION");
END;
IF E.EVAL(TRY) THEN
BEGIN
IF ABS(E.RESULT - 24) < 0.001 THEN
BEGIN
SOLUTION := SOLUTION + 1;
OUTTEXT(TRY); OUTTEXT(" = ");
OUTFIX(E.RESULT, 4, 10);
OUTIMAGE;
END;
END
ELSE
BEGIN
IF E.ERR <> "DIV BY ZERO" THEN
BEGIN
OUTTEXT(TRY); OUTIMAGE;
OUTTEXT(E.ERR); OUTIMAGE;
END;
END;
END P;
TEXT TRY;
TRY :- BLANKS(17);
P("(1 + 2) + (3 + 4)");
P("(1 + (2 + 3)) + 4");
P("((1 + 2) + 3) + 4");
P("1 + ((2 + 3) + 4)");
P("1 + (2 + (3 + 4))");
END;
OUTINT(SOLUTION, 0);
OUTTEXT(" SOLUTIONS FOUND");
OUTIMAGE;
END.

View file

@ -0,0 +1,26 @@
var [const] H=Utils.Helpers;
fcn u(xs){ xs.reduce(fcn(us,s){us.holds(s) and us or us.append(s) },L()) }
var ops=u(H.combosK(3,"+-*/".split("")).apply(H.permute).flatten());
var fs=T(
fcn f0(a,b,c,d,x,y,z){ Op(z)(Op(y)(Op(x)(a,b),c),d) }, // ((AxB)yC)zD
fcn f1(a,b,c,d,x,y,z){ Op(y)(Op(x)(a,b),Op(z)(c,d)) }, // (AxB)y(CzD)
fcn f2(a,b,c,d,x,y,z){ Op(z)(Op(x)(a,Op(y)(b,c)),d) }, // (Ax(ByC))zD
fcn f3(a,b,c,d,x,y,z){ Op(x)(a,Op(z)(Op(y)(b,c),d)) }, // Ax((ByC)zD)
fcn f4(a,b,c,d,x,y,z){ Op(x)(a,Op(y)(b,Op(z)(c,d))) }, // Ax(By(CzD))
);
var fts= // format strings for human readable formulas
T("((d.d).d).d", "(d.d).(d.d)", "(d.(d.d)).d", "d.((d.d).d)", "d.(d.(d.d))")
.pump(List,T("replace","d","%d"),T("replace",".","%s"));
fcn f2s(digits,ops,f){
fts[f.name[1].toInt()].fmt(digits.zip(ops).flatten().xplode(),digits[3]);
}
fcn game24Solver(digitsString){
digits:=digitsString.split("").apply("toFloat");
[[(digits4,ops3,f); H.permute(digits); ops; // list comprehension
fs,{ try{f(digits4.xplode(),ops3.xplode()).closeTo(24,0.001) }
catch(MathError){ False } };
{ f2s(digits4,ops3,f) }]];
}

View file

@ -0,0 +1,3 @@
solutions:=u(game24Solver(ask(0,"digits: ")));
println(solutions.len()," solutions:");
solutions.apply2(Console.println);