This commit is contained in:
Ingy döt Net 2013-04-10 21:29:02 -07:00
parent 764da6cbbb
commit db842d013d
19005 changed files with 197040 additions and 7 deletions

View file

@ -0,0 +1,71 @@
load compiler
function genRandomNumbers( amount )
rtn = []
for i in [ 0 : amount ]: rtn += random( 1, 9 )
return( rtn )
end
function getAnswer( exp )
ic = ICompiler()
ic.compileAll(exp)
return( ic.result )
end
function validInput( str )
for i in [ 0 : str.len() ]
if str[i] notin ' ()[]0123456789-+/*'
> 'INVALID Character = ', str[i]
return( false )
end
end
return( true )
end
printl('
The 24 Game
Given any four digits in the range 1 to 9, which may have repetitions,
Using just the +, -, *, and / operators; and the possible use of
brackets, (), show how to make an answer of 24.
An answer of "q" will quit the game.
An answer of "!" will generate a new set of four digits.
Otherwise you are repeatedly asked for an expression until it evaluates to 24
Note: you cannot form multiple digit numbers from the supplied digits,
so an answer of 12+12 when given 1, 2, 2, and 1 would not be allowed.
')
num = genRandomNumbers( 4 )
while( true )
>> "Here are the numbers to choose from: "
map({ a => print(a, " ") }, num)
>
exp = input()
switch exp
case "q", "Q"
exit()
case "!"
> 'Generating new numbers list'
num = genRandomNumbers( 4 )
default
if not validInput( exp ): continue
answer = getAnswer( exp )
if answer == 24
> "By George you GOT IT! Your expression equals 24"
else
> "Ahh Sorry, So Sorry your answer of ", answer, " does not equal 24."
end
end
end

View file

@ -0,0 +1,92 @@
# Solution in '''RPN'''
Play24 := function()
local input, digits, line, c, chars, stack, stackptr, cur, p, q, ok, a, b, run;
input := InputTextUser();
run := true;
while run do
digits := List([1 .. 4], n -> Random(1, 9));
while true do
Display(digits);
line := ReadLine(input);
line := Chomp(line);
if line = "end" then
run := false;
break;
elif line = "next" then
break;
else
ok := true;
stack := [ ];
stackptr := 0;
chars := "123456789+-*/ ";
cur := ShallowCopy(digits);
for c in line do
if c = ' ' then
continue;
fi;
p := Position(chars, c);
if p = fail then
ok := false;
break;
fi;
if p < 10 then
q := Position(cur, p);
if q = fail then
ok := false;
break;
fi;
Unbind(cur[q]);
stackptr := stackptr + 1;
stack[stackptr] := p;
else
if stackptr < 2 then
ok := false;
break;
fi;
b := stack[stackptr];
a := stack[stackptr - 1];
stackptr := stackptr - 1;
if c = '+' then
a := a + b;
elif c = '-' then
a := a - b;
elif c = '*' then
a := a * b;
elif c = '/' then
if b = 0 then
ok := false;
break;
fi;
a := a / b;
else
ok := false;
break;
fi;
stack[stackptr] := a;
fi;
od;
if ok and stackptr = 1 and Size(cur) = 0 then
if stack[1] = 24 then
Print("Good !\n");
break;
else
Print("Bad value: ", stack[1], "\n");
continue;
fi;
fi;
Print("Invalid expression\n");
fi;
od;
od;
CloseStream(input);
end;
# example session
# type "end" to quit the game, "next" to try another list of digits
gap> Play24();
[ 7, 6, 8, 5 ]
86*75-/
Good !
[ 5, 9, 2, 7 ]
end
gap>

View file

@ -0,0 +1,105 @@
uses java.lang.Double
uses java.lang.Integer
uses java.util.ArrayList
uses java.util.List
uses java.util.Scanner
uses java.util.Stack
function doEval( scanner : Scanner, allowed : List<Integer> ) : double {
var stk = new Stack<Double>()
while( scanner.hasNext() ) {
if( scanner.hasNextInt() ) {
var n = scanner.nextInt()
// Make sure they're allowed to use n
if( n <= 0 || n >= 10 ) {
print( n + " isn't allowed" )
return 0
}
var idx = allowed.indexOf( n )
if( idx == -1 ) {
print( "You aren't allowed to use so many " + n + "s!" )
return 0
}
// Add the input number to the stack
stk.push( new Double( n ) )
// Mark n as used
allowed.remove( idx )
} else {
// It has to be an operator...
if( stk.size() < 2 ) {
print( "Invalid Expression: Stack underflow!" )
return 0
}
// Gets the next operator as a single character token
var s = scanner.next("[\\+-/\\*]")
// Get the operands
var r = stk.pop().doubleValue()
var l = stk.pop().doubleValue()
// Determine which operator and invoke it
if( s.equals( "+" ) ) {
stk.push( new Double( l + r ) )
} else if( s.equals( "-" ) ) {
stk.push( new Double( l - r ) )
} else if( s.equals( "*" ) ) {
stk.push( new Double( l * r ) )
} else if( s.equals( "/" ) ) {
if( r == 0.0 ) {
print( "Invalid Expression: Division by zero!" )
return 0
}
stk.push( new Double( l / r ) )
} else {
print( "Internal Error: looking for operator yielded '" + s + "'" )
return 0
}
}
}
// Did they skip any numbers?
if( allowed.size() != 0 ) {
print( "You didn't use ${allowed}" )
return 0
}
// Did they use enough operators?
if( stk.size() != 1 ) {
print( "Invalid Expression: Not enough operators!" )
return 0
}
return stk.pop().doubleValue()
}
// Pick 4 random numbers from [1..9]
var nums = new ArrayList<Integer>()
var gen = new java.util.Random( new java.util.Date().getTime() )
for( i in 0..3 ) {
nums.add( gen.nextInt(9) + 1 )
}
// Prompt the user
print( "Using addition, subtraction, multiplication and division, write an" )
print( "expression that evaluates to 24 using" )
print( "${nums.get(0)}, ${nums.get(1)}, ${nums.get(2)} and ${nums.get(3)}" )
print( "" )
print( "Please enter your expression in RPN" )
// Build a tokenizer over a line of input
var sc = new Scanner( new java.io.BufferedReader( new java.io.InputStreamReader( java.lang.System.in ) ).readLine() )
// eval the expression
var val = doEval( sc, nums )
// winner?
if( java.lang.Math.abs( val - 24.0 ) < 0.001 ) {
print( "You win!" )
} else {
print( "You lose!" )
}

View file

@ -0,0 +1,67 @@
final random = new Random()
final input = new Scanner(System.in)
def evaluate = { expr ->
if (expr == 'QUIT') {
return 'QUIT'
} else {
try { Eval.me(expr.replaceAll(/(\d)/, '$1.0')) }
catch (e) { 'syntax error' }
}
}
def readGuess = { digits ->
while (true) {
print "Enter your guess using ${digits} (q to quit): "
def expr = input.nextLine()
switch (expr) {
case ~/^[qQ].*/:
return 'QUIT'
case ~/.*[^\d\s\+\*\/\(\)-].*/:
def badChars = expr.replaceAll(~/[\d\s\+\*\/\(\)-]/, '')
println "invalid characters in input: ${(badChars as List) as Set}"
break
case { (it.replaceAll(~/\D/, '') as List).sort() != ([]+digits).sort() }:
println '''you didn't use the right digits'''
break
case ~/.*\d\d.*/:
println 'no multi-digit numbers allowed'
break
default:
return expr
}
}
}
def digits = (1..4).collect { (random.nextInt(9) + 1) as String }
while (true) {
def guess = readGuess(digits)
def result = evaluate(guess)
switch (result) {
case 'QUIT':
println 'Awwww. Maybe next time?'
return
case 24:
println 'Yes! You got it.'
return
case 'syntax error':
println "A ${result} was found in ${guess}"
break
default:
println "Nope: ${guess} == ${result}, not 24"
println 'One more try, then?'
}
}

View file

@ -0,0 +1,35 @@
DIMENSION digits(4), input_digits(100), difference(4)
CHARACTER expression*100, prompt*100, answers='Wrong,Correct,', protocol='24 game.txt'
1 digits = CEILING( RAN(9) )
2 DLG(Edit=expression, Text=digits, TItle=prompt)
READ(Text=expression, ItemS=n) input_digits
IF(n == 4) THEN
ALIAS(input_digits,1, input,4)
SORT(Vector=digits, Sorted=digits)
SORT(Vector=input, Sorted=input)
difference = ABS(digits - input)
IF( SUM(difference) == 0 ) THEN
EDIT(Text=expression, ScaNnot='123456789+-*/ ()', GetPos=i, CoPyto=prompt)
IF( i > 0 ) THEN
prompt = TRIM(expression) // ': ' //TRIM(prompt) // ' is an illegal character'
ELSE
prompt = TRIM(expression) // ': Syntax error'
result = XEQ(expression, *2) ! on error branch to label 2
EDIT(Text=answers, ITeM=(result==24)+1, Parse=answer)
WRITE(Text=prompt, Name) TRIM(expression)//': ', answer, result
ENDIF
ELSE
WRITE(Text=prompt) TRIM(expression), ': You used ', input, ' instead ', digits
ENDIF
ELSE
prompt = TRIM(expression) // ': Instead 4 digits you used ' // n
ENDIF
OPEN(FIle=protocol, APPend)
WRITE(FIle=protocol, CLoSe=1) prompt
DLG(TItle=prompt, Button='>2:Try again', B='>1:New game', B='Quit')
END

View file

@ -0,0 +1,6 @@
4 + 8 + 7 + 5: You used 4 5 7 8 instead 4 4 7 8
4 + 8 + 7 + a: Instead 4 digits you used 3
4 + 8 + 7 + a + 4: a is an illegal character
4 + 8 + 7a + 4: a is an illegal character
4 + 8 + 7 + 4:; answer=Wrong; result=23;
4 * 7 - 8 + 4:; answer=Correct; result=24;

View file

@ -0,0 +1,58 @@
invocable all
link strings # for csort, deletec
procedure main()
help()
repeat {
every (n := "") ||:= (1 to 4, string(1+?8))
writes("Your four digits are : ")
every writes(!n," ")
write()
e := trim(read()) | fail
case e of {
"q"|"quit": return
"?"|"help": help()
default: {
e := deletec(e,' \t') # no whitespace
d := deletec(e,~&digits) # just digits
if csort(n) ~== csort(d) then # and only the 4 given digits
write("Invalid repsonse.") & next
if e ? (ans := eval(E()), pos(0)) then # parse and evaluate
if ans = 24 then write("Congratulations you win!")
else write("Your answer was ",ans,". Try again.")
else write("Invalid expression.")
}
}
}
end
procedure eval(X) #: return the evaluated AST
if type(X) == "list" then {
x := eval(get(X))
while x := get(X)(real(x), real(eval(get(X) | stop("Malformed expression."))))
}
return \x | X
end
procedure E() #: expression
put(lex := [],T())
while put(lex,tab(any('+-*/'))) do
put(lex,T())
suspend if *lex = 1 then lex[1] else lex # strip useless []
end
procedure T() #: Term
suspend 2(="(", E(), =")") | # parenthesized subexpression, or ...
tab(any(&digits)) # just a value
end
procedure help()
return write(
"Welcome to 24\n\n",
"Combine the 4 given digits to make 24 using only + - * / and ( ).\n ",
"All operations have equal precedence and are evaluated left to right.\n",
"Combining (concatenating) digits is not allowed.\n",
"Enter 'help', 'quit', or an expression.\n")
end

11
Task/24-game/J/24-game.j Normal file
View file

@ -0,0 +1,11 @@
require'misc'
deal=: 1 + ? bind 9 9 9 9
rules=: smoutput bind 'see http://en.wikipedia.org/wiki/24_Game'
input=: prompt @ ('enter 24 expression using ', ":, ': '"_)
wellformed=: (' '<;._1@, ":@[) -:&(/:~) '(+-*%)' -.&;:~ ]
is24=: 24 -: ". ::0:@]
respond=: (;:'no yes') {::~ wellformed * is24
game24=: (respond input)@deal@rules

View file

@ -0,0 +1,87 @@
dim d(4)
dim chk(4)
print "The 24 Game"
print
print "Given four digits and using just the +, -, *, and / operators; and the"
print "possible use of brackets, (), enter an expression that equates to 24."
do
d$=""
for i = 1 to 4
d(i)=int(rnd(1)*9)+1 '1..9
chk(i)=d(i)
d$=d$;d(i) 'valid digits, to check with Instr
next
print
print "These are your four digits: ";
for i = 1 to 4
print d(i);left$(",",i<>4);
next
print
Print "Enter expression:"
Input "24 = ";expr$
'check expr$ for validity
'check right digits used
failed = 0
for i = 1 to len(expr$)
c$=mid$(expr$,i,1)
if instr("123456789", c$)<>0 then 'digit
if instr(d$, c$)=0 then failed = 1: exit for
if i>1 and instr("123456789", mid$(expr$,i-1,1))<>0 then failed = 2: exit for
for j =1 to 4
if chk(j)=val(c$) then chk(j)=0: exit for
next
end if
next
if failed=1 then
print "Wrong digit (";c$;")"
goto [fail]
end if
if failed=2 then
print "Multiple digit numbers is disallowed."
goto [fail]
end if
'check all digits used
if chk(1)+ chk(2)+ chk(3)+ chk(4)<>0 then
print "Not all digits used"
goto [fail]
end if
'check valid operations
failed = 0
for i = 1 to len(expr$)
c$=mid$(expr$,i,1)
if instr("+-*/()"+d$, c$)=0 then failed = 1: exit for
next
if failed then
print "Wrong operation (";c$;")"
goto [fail]
end if
'some errors (like brackets) trapped by error handler
Err$=""
res=evalWithErrCheck(expr$)
if Err$<>"" then
print "Error in expression"
goto [fail]
end if
if res = 24 then
print "Correct!"
else
print "Wrong! (you got ";res ;")"
end if
[fail]
Input "Play again (y/n)? "; ans$
loop while ans$="y"
end
function evalWithErrCheck(expr$)
on error goto [handler]
evalWithErrCheck=eval(expr$)
exit function
[handler]
end function

View file

@ -0,0 +1,54 @@
10 CLS:RANDOMIZE TIME
20 PRINT "The 24 Game"
30 PRINT "===========":PRINT
40 PRINT "Enter an arithmetic expression"
50 PRINT "that evaluates to 24,"
60 PRINT "using only the provided digits"
70 PRINT "and +, -, *, /, (, )."
80 PRINT "(Just hit Return for new digits.)"
90 ' create new digits
100 FOR i=1 TO 4:a(i)=INT(RND*9)+1:NEXT
110 PRINT
120 PRINT "The digits are";a(1);a(2);a(3);a(4)
130 PRINT
140 ' user enters solution
150 INPUT "Your solution";s$
160 IF s$="" THEN PRINT "Creating new digits...":GOTO 100
170 GOTO 300
180 ' a little hack to create something like an EVAL function
190 OPENOUT "exp.bas"
200 PRINT #9,"1000 x="s$":return"
210 CLOSEOUT
220 CHAIN MERGE "exp",240
230 ' now evaluate the expression
240 ON ERROR GOTO 530
250 GOSUB 1000
260 IF x=24 THEN PRINT "Well done!":END
270 PRINT "No, this evaluates to"x:PRINT "Please try again."
280 GOTO 150
290 ' check input for correctness
300 FOR i=1 TO LEN(s$)
310 q=ASC(MID$(s$,i,1))
320 IF q=32 OR (q>39 AND q<44) OR q=45 OR (q>46 AND q<58) THEN NEXT
330 IF i-1=LEN(s$) THEN 370
340 PRINT "Bad character in expression:"CHR$(q)
350 PRINT "Try again":GOTO 150
360 ' new numbers in solution?
370 FOR i=1 TO LEN(s$)-1
380 q=ASC(MID$(s$,i,1)):p=ASC(MID$(s$,i+1,1))
390 IF q>47 AND q<58 AND p>47 AND p<58 THEN PRINT "No forming of new numbers, please!":GOTO 150
400 NEXT
410 FOR i=1 TO 9:orig(i)=0:guess(i)=0:NEXT
420 FOR i=1 TO 4:orig(a(i))=orig(a(i))+1:NEXT
430 FOR i=1 TO LEN(s$)
440 v$=MID$(s$,i,1)
450 va=ASC(v$)-48
460 IF va>0 AND va<10 THEN guess(va)=guess(va)+1
470 NEXT
480 FOR i=1 TO 9
490 IF guess(i)<>orig(i) THEN PRINT "Only use all the provided digits!":GOTO 150
500 NEXT
510 GOTO 190
520 ' syntax error, e.g. non-matching parentheses
530 PRINT "Error in expression, please try again."
540 RESUME 150

View file

@ -0,0 +1,74 @@
; useful constants
make "false 1=0
make "true 1=1
make "lf char 10
make "sp char 32
; non-digits legal in expression
make "operators (lput sp [+ - * / \( \)])
; display help message
to show_help :digits
type lf
print sentence quoted [Using only these digits:] :digits
print sentence quoted [and these operators:] [* / + -]
print quoted [\(and parentheses as needed\),]
print quoted [enter an arithmetic expression
which evaluates to exactly 24.]
type lf
print quoted [Enter \"!\" to get fresh numbers.]
print quoted [Enter \"q\" to quit.]
type lf
end
make "digits []
make "done false
until [done] [
if empty? digits [
make "digits (map [(random 9) + 1] [1 2 3 4])
]
(type "Solution sp "for sp digits "? sp )
make "expression readrawline
ifelse [expression = "?] [
show_help digits
] [ifelse [expression = "q] [
print "Bye!
make "done true
] [ifelse [expression = "!] [
make "digits []
] [
make "exprchars ` expression
make "allowed (sentence digits operators)
ifelse (member? false (map [[c] member? c allowed] exprchars)) [
(print quoted [Illegal character in input.])
] [
catch "error [
make "syntax_error true
make "testval (run expression)
make "syntax_error false
]
ifelse syntax_error [
(print quoted [Invalid expression.])
] [
ifelse (testval = 24) [
print quoted [You win!]
make "done true
] [
(print (sentence
quoted [Incorrect \(got ] testval quoted [instead of 24\).]))
]
]
]
]]]
]
bye

View file

@ -0,0 +1,15 @@
isLegal[n_List, x_String] :=
Quiet[Check[
With[{h = ToExpression[x, StandardForm, HoldForm]},
If[Cases[Level[h, {2, \[Infinity]}, Hold, Heads -> True],
Except[_Integer | Plus | _Plus | Times | _Times | Power |
Power[_, -1]]] === {} &&
Sort[Level[h /. Power[q_, -1] -> q, {-1}] /.
q_Integer -> Abs[q]] === Sort[n], ReleaseHold[h]]], Null]]
Grid[{{Button[
"new numbers", {a, b, c, d} = Table[RandomInteger[{1, 9}], {4}]],
InputField[Dynamic[x], String]}, {Dynamic[{a, b, c, d}],
Dynamic[Switch[isLegal[{a, b, c, d}, x], Null,
"Sorry, that is invalid.", 24, "Congrats! That's 24!", _,
"Sorry, that makes " <> ToString[ToExpression@x, InputForm] <>
", not 24."]]}}]

View file

@ -0,0 +1,179 @@
MODULE TwentyFour;
FROM InOut IMPORT WriteString, WriteLn, Write, ReadString, WriteInt;
FROM RandomGenerator IMPORT Random;
TYPE operator_t = (add, sub, mul, div);
expr_t = RECORD
operand : ARRAY[0..3] OF CARDINAL;
operator : ARRAY[1..3] OF operator_t;
END;(*of RECORD*)
numbers_t = SET OF CHAR;
VAR expr : expr_t;
numbers : numbers_t;
(*******************************************************************createExpr*)
(*analyse the input string *)
PROCEDURE createExpr(s: ARRAY OF CHAR);
VAR index, counter : INTEGER;
token : CHAR;
temp_expr : expr_t;
operand : CARDINAL;
operator : operator_t;
(************************************nextToken*)
(* returns the next CHAR that isn`t a space *)
PROCEDURE nextToken(): CHAR;
BEGIN
INC(index);
WHILE (s[index] = ' ') DO
INC(index);
END;(*of WHILE*)
RETURN(s[index]);
END nextToken;
(***********************************set_operand*)
(* checks if the CHAR o inerhits a valid number*)
(* and sets 'operand' to its value *)
PROCEDURE set_operand(o: CHAR);
BEGIN
CASE o OF
'0'..'9': IF o IN numbers THEN
operand := ORD(o)-48;
numbers := numbers - numbers_t{o};
ELSE
WriteString("ERROR: '");
Write( o);
WriteString( "' isn`t a available number ");
WriteLn;
HALT;
END;(*of IF*)|
0 : WriteString("ERROR: error in input ");
WriteLn;
HALT;
ELSE
WriteString("ERROR: '");
Write( o);
WriteString( "' isn`t a number ");
WriteLn;
HALT;
END;(*of CASE*)
END set_operand;
(**********************************set_operator*)
(* checks if the CHAR o inerhits a valid *)
(* operator and sets 'operator' to its value *)
PROCEDURE set_operator(o: CHAR);
BEGIN
CASE o OF
'+' : operator := add;|
'-' : operator := sub;|
'*' : operator := mul;|
'/' : operator := div;|
0 : WriteString("ERROR: error in input ");
WriteLn;
HALT;
ELSE
WriteString("ERROR: '");
Write( o);
WriteString( "' isn`t a operator ");
WriteLn;
HALT;
END;(*of CASE*)
END set_operator;
(************************************************)
BEGIN
index := -1;
token := nextToken();
set_operand(token);
expr.operand[0] := operand;
token := nextToken();
set_operator(token);
expr.operator[1] := operator;
token := nextToken();
set_operand(token);
expr.operand[1] := operand;
token := nextToken();
set_operator(token);
expr.operator[2] := operator;
token := nextToken();
set_operand(token);
expr.operand[2] := operand;
token := nextToken();
set_operator(token);
expr.operator[3] := operator;
token := nextToken();
set_operand(token);
expr.operand[3] := operand;
END createExpr;
(*****************************************************************evaluateExpr*)
(* evaluate the expresion that was createt by 'createExpr' *)
PROCEDURE evaluateExpr(VAR num: REAL);
VAR index : INTEGER;
BEGIN
WITH expr DO
num := VAL(REAL,operand[0]);
FOR index := 1 TO 3 DO
CASE operator[index] OF
add : num := num + VAL(REAL,operand[index]);|
sub : num := num - VAL(REAL,operand[index]);|
mul : num := num * VAL(REAL,operand[index]);|
div : num := num / VAL(REAL,operand[index]);
END;(*of CASE*)
END;(*of FOR*)
END;(*of WIHT*)
END evaluateExpr;
(**************************************************************generateNumbers*)
(* generates the 4 random numbers ond write them *)
PROCEDURE generateNumbers;
VAR index,ran : INTEGER;
BEGIN
numbers := numbers_t{};
ran := Random(0,9);
FOR index := 1 TO 4 DO
WHILE (CHR(ran+48) IN numbers )DO
ran := Random(0,9);
END;(*of While*)
Write(CHR(ran+48));
WriteLn;
numbers := numbers + numbers_t{CHR(ran+48)}
END;(*of FOR*)
END generateNumbers;
(****************************************************************Main Programm*)
VAR str : ARRAY[0..255] OF CHAR;
sum : REAL;
BEGIN
WriteString("Welcome to the 24 game in MODULA-2");
WriteLn;
WriteString("Here are your numbers:");
WriteLn;
generateNumbers;
WriteString("Enter your equation(This implementation dosn`t support brackets yet): ");
WriteLn;
ReadString(str);
createExpr(str);
evaluateExpr(sum);
WriteLn;
WriteString("Result:");
WriteLn;
WriteInt(TRUNC(sum),0);
WriteLn;
CASE (TRUNC(sum) - 24) OF
0 : WriteString("Perfect!");|
1 : WriteString("Almost perfect.");
ELSE
WriteString("You loose!");
END;(*of CASE*)
WriteLn;
END TwentyFour.