Add tasks for all the new languages
This commit is contained in:
parent
9dc3c2bb62
commit
bba7bfd280
13208 changed files with 134745 additions and 0 deletions
109
Task/24-game/8th/24-game.8th
Normal file
109
Task/24-game/8th/24-game.8th
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
\ Generate four random digits and display to the user
|
||||
\ then get an expression from the user using +, -, / and * and the digits
|
||||
\ the result must equal 24
|
||||
\ http://8th-dev.com/24game.html
|
||||
|
||||
\ Only the words in namespace 'game' are available to the player:
|
||||
ns: game
|
||||
|
||||
: + n:+ ;
|
||||
: - n:- ;
|
||||
: * n:* ;
|
||||
: / n:/ ;
|
||||
|
||||
ns: G
|
||||
|
||||
var random-digits
|
||||
var user-input
|
||||
|
||||
: one-digit \ a -- a
|
||||
rand n:abs 9 n:mod n:1+ a:push ;
|
||||
|
||||
: gen-digits \ - a
|
||||
[] clone nip \ the clone nip is not needed in versions past 1.0.2...
|
||||
' one-digit 4 times
|
||||
' n:cmp a:sort
|
||||
random-digits ! ;
|
||||
|
||||
: prompt-user
|
||||
cr "The digits are: " . random-digits @ . cr ;
|
||||
|
||||
: goodbye
|
||||
cr "Thanks for playing!\n" . cr 0 die ;
|
||||
|
||||
: get-input
|
||||
70 null con:accept dup user-input !
|
||||
null? if drop goodbye then ;
|
||||
|
||||
: compare-digits
|
||||
true swap
|
||||
(
|
||||
\ inputed-array index
|
||||
dup >r
|
||||
a:@
|
||||
random-digits @ r> a:@ nip
|
||||
n:= not if
|
||||
break
|
||||
swap drop false swap
|
||||
then
|
||||
) 0 3 loop drop ;
|
||||
|
||||
/^\D*(\d)\D+(\d)\D+(\d)\D+(\d)\D*$/ var, digits-regex
|
||||
|
||||
: all-digits?
|
||||
user-input @ digits-regex @ r:match
|
||||
null? if drop false else
|
||||
5 = not if
|
||||
false
|
||||
else
|
||||
\ convert the captured digits in the regex into a sorted array:
|
||||
digits-regex @
|
||||
( r:@ >n swap ) 1 4 loop drop
|
||||
4 a:close ' n:cmp a:sort
|
||||
compare-digits
|
||||
then
|
||||
then ;
|
||||
|
||||
: does-eval?
|
||||
0 user-input @ eval 24 n:=
|
||||
dup not if
|
||||
cr "Sorry, that expression is wrong" . cr
|
||||
then ;
|
||||
|
||||
: check-input
|
||||
reset
|
||||
all-digits? if
|
||||
does-eval? if
|
||||
cr "Excellent! Your expression: \"" .
|
||||
user-input @ .
|
||||
"\" worked!" . cr
|
||||
then
|
||||
else
|
||||
cr "You did not use the digits properly, try again." . cr
|
||||
then ;
|
||||
|
||||
: intro quote |
|
||||
|
||||
Welcome to the '24 game'!
|
||||
|
||||
You will be shown four digits each time. Using only the + - * and / operators
|
||||
and all the digits (and only the digits), produce the number '24'
|
||||
|
||||
Enter your result in 8th syntax, e.g.: 4 4 + 2 1 + *
|
||||
|
||||
To quit the game, just hit enter by itself. Enjoy!
|
||||
|
||||
| . ;
|
||||
|
||||
: start
|
||||
\ don't allow anything but the desired words
|
||||
ns:game only
|
||||
intro
|
||||
repeat
|
||||
gen-digits
|
||||
prompt-user
|
||||
get-input
|
||||
check-input
|
||||
again ;
|
||||
|
||||
start
|
||||
221
Task/24-game/Ceylon/24-game.ceylon
Normal file
221
Task/24-game/Ceylon/24-game.ceylon
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
import ceylon.random {
|
||||
|
||||
DefaultRandom
|
||||
}
|
||||
|
||||
class Rational(shared Integer numerator, shared Integer denominator = 1) satisfies Numeric<Rational> {
|
||||
|
||||
assert(denominator != 0);
|
||||
|
||||
Integer gcd(Integer a, Integer b) => if(b == 0) then a else gcd(b, a % b);
|
||||
|
||||
shared Rational inverted => Rational(denominator, numerator);
|
||||
|
||||
shared Rational simplified =>
|
||||
let(largestFactor = gcd(numerator, denominator))
|
||||
Rational(numerator / largestFactor, denominator / largestFactor);
|
||||
|
||||
divided(Rational other) => (this * other.inverted).simplified;
|
||||
|
||||
negated => Rational(-numerator, denominator).simplified;
|
||||
|
||||
plus(Rational other) =>
|
||||
let(top = numerator * other.denominator + other.numerator * denominator,
|
||||
bottom = denominator * other.denominator)
|
||||
Rational(top, bottom).simplified;
|
||||
|
||||
times(Rational other) =>
|
||||
Rational(numerator * other.numerator, denominator * other.denominator).simplified;
|
||||
|
||||
shared Integer integer => numerator / denominator;
|
||||
shared Float float => numerator.float / denominator.float;
|
||||
|
||||
string => denominator == 1 then numerator.string else "``numerator``/``denominator``";
|
||||
}
|
||||
|
||||
interface Expression {
|
||||
shared formal Rational evaluate();
|
||||
}
|
||||
|
||||
class NumberExpression(Rational number) satisfies Expression {
|
||||
evaluate() => number;
|
||||
string => number.string;
|
||||
}
|
||||
|
||||
class OperatorExpression(Expression left, Character operator, Expression right) satisfies Expression {
|
||||
shared actual Rational evaluate() {
|
||||
switch(operator)
|
||||
case('*') {
|
||||
return left.evaluate() * right.evaluate();
|
||||
}
|
||||
case('/') {
|
||||
return left.evaluate() / right.evaluate();
|
||||
}
|
||||
case('-') {
|
||||
return left.evaluate() - right.evaluate();
|
||||
}
|
||||
case('+') {
|
||||
return left.evaluate() + right.evaluate();
|
||||
}
|
||||
else {
|
||||
throw Exception("unknown operator ``operator``");
|
||||
}
|
||||
}
|
||||
|
||||
string => "(``left.string`` ``operator.string`` ``right.string``)";
|
||||
}
|
||||
|
||||
"A simplified top down operator precedence parser. There aren't any right
|
||||
binding operators so we don't have to worry about that."
|
||||
class PrattParser(String input) {
|
||||
|
||||
value tokens = input.replace(" ", "");
|
||||
variable value index = -1;
|
||||
|
||||
shared Expression expression(Integer precedence = 0) {
|
||||
value token = advance();
|
||||
variable value left = parseUnary(token);
|
||||
while(precedence < getPrecedence(peek())) {
|
||||
value nextToken = advance();
|
||||
left = parseBinary(left, nextToken);
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
Integer getPrecedence(Character op) =>
|
||||
switch(op)
|
||||
case('*' | '/') 2
|
||||
case('+' | '-') 1
|
||||
else 0;
|
||||
|
||||
Character advance(Character? expected = null) {
|
||||
index++;
|
||||
value token = tokens[index] else ' ';
|
||||
if(exists expected, token != expected) {
|
||||
throw Exception("unknown character ``token``");
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
Character peek() => tokens[index + 1] else ' ';
|
||||
|
||||
Expression parseBinary(Expression left, Character operator) =>
|
||||
let(right = expression(getPrecedence(operator)))
|
||||
OperatorExpression(left, operator, right);
|
||||
|
||||
Expression parseUnary(Character token) {
|
||||
if(token.digit) {
|
||||
assert(exists int = parseInteger(token.string));
|
||||
return NumberExpression(Rational(int));
|
||||
} else if(token == '(') {
|
||||
value exp = expression();
|
||||
advance(')');
|
||||
return exp;
|
||||
} else {
|
||||
throw Exception("unknown character ``token``");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Run the module `twentyfourgame`."
|
||||
shared void run() {
|
||||
|
||||
value random = DefaultRandom();
|
||||
|
||||
function random4Numbers() =>
|
||||
random.elements(1..9).take(4).sequence();
|
||||
|
||||
function isValidGuess(String input, {Integer*} allowedNumbers) {
|
||||
value allowedOperators = set {*"()+-/*"};
|
||||
value extractedNumbers = input
|
||||
.split((Character ch) => ch in allowedOperators || ch.whitespace)
|
||||
.map((String element) => parseInteger(element))
|
||||
.coalesced;
|
||||
if(extractedNumbers.any((Integer element) => element > 9)) {
|
||||
print("number too big!");
|
||||
return false;
|
||||
}
|
||||
if(extractedNumbers.any((Integer element) => element < 1)) {
|
||||
print("number too small!");
|
||||
return false;
|
||||
}
|
||||
if(extractedNumbers.sort(byIncreasing(Integer.magnitude)) != allowedNumbers.sort(byIncreasing(Integer.magnitude))) {
|
||||
print("use all the numbers, please!");
|
||||
return false;
|
||||
}
|
||||
if(!input.every((Character element) => element in allowedOperators || element.digit || element.whitespace)) {
|
||||
print("only digits and mathematical operators, please");
|
||||
return false;
|
||||
}
|
||||
variable value lefts = 0;
|
||||
for(c in input) {
|
||||
if(c == '(') {
|
||||
lefts++;
|
||||
} else if(c == ')') {
|
||||
lefts--;
|
||||
if(lefts < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(lefts != 0) {
|
||||
print("unbalanced brackets!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function evaluate(String input) =>
|
||||
let(parser = PrattParser(input),
|
||||
exp = parser.expression())
|
||||
exp.evaluate();
|
||||
|
||||
print("Welcome to The 24 Game.
|
||||
Create a mathematical equation with four random
|
||||
numbers that evaluates to 24.
|
||||
You must use all the numbers once and only once,
|
||||
but in any order.
|
||||
Also, only + - / * and parentheses are allowed.
|
||||
For example: (1 + 2 + 3) * 4
|
||||
Also: enter n for new numbers and q to quit.
|
||||
-----------------------------------------------");
|
||||
|
||||
while(true) {
|
||||
|
||||
value chosenNumbers = random4Numbers();
|
||||
void pleaseTryAgain() => print("Sorry, please try again. (Your numbers are ``chosenNumbers``)");
|
||||
|
||||
print("Your numbers are ``chosenNumbers``. Please turn them into 24.");
|
||||
|
||||
while(true) {
|
||||
value line = process.readLine()?.trimmed;
|
||||
if(exists line) {
|
||||
if(line.uppercased == "Q") {
|
||||
print("bye!");
|
||||
return;
|
||||
}
|
||||
if(line.uppercased == "N") {
|
||||
break;
|
||||
}
|
||||
if(isValidGuess(line, chosenNumbers)) {
|
||||
try {
|
||||
value result = evaluate(line);
|
||||
print("= ``result``");
|
||||
if(result.integer == 24) {
|
||||
print("You did it!");
|
||||
break;
|
||||
} else {
|
||||
pleaseTryAgain();
|
||||
}
|
||||
} catch(Exception e) {
|
||||
print(e.message);
|
||||
pleaseTryAgain();
|
||||
}
|
||||
} else {
|
||||
pleaseTryAgain();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
31
Task/24-game/EchoLisp/24-game.echolisp
Normal file
31
Task/24-game/EchoLisp/24-game.echolisp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
(string-delimiter "")
|
||||
;; check that nums are in expr, and only once
|
||||
(define (is-valid? expr sorted: nums)
|
||||
(when (equal? 'q expr) (error "24-game" "Thx for playing"))
|
||||
(unless (and
|
||||
(list? expr)
|
||||
(equal? nums (list-sort < (filter number? (flatten expr)))))
|
||||
(writeln "🎃 Please use" nums)
|
||||
#f))
|
||||
|
||||
;; 4 random digits
|
||||
(define (gen24)
|
||||
(->> (append (range 1 10)(range 1 10)) shuffle (take 4) (list-sort < )))
|
||||
|
||||
(define (is-24? num)
|
||||
(unless (= 24 num)
|
||||
(writeln "😧 Sorry - Result = " num)
|
||||
#f))
|
||||
|
||||
(define (check-24 expr)
|
||||
(if (and
|
||||
(is-valid? expr nums)
|
||||
(is-24? (js-eval (string expr)))) ;; use js evaluator
|
||||
"🍀 🌸 Congrats - (play24) for another one."
|
||||
(input-expr check-24 (string nums))))
|
||||
|
||||
(define nums null)
|
||||
(define (play24)
|
||||
(set! nums (gen24))
|
||||
(writeln "24-game - Can you combine" nums "to get 24 ❓ (q to exit)")
|
||||
(input-expr check-24 (string-append (string nums) " -> 24 ❓")))
|
||||
70
Task/24-game/Lasso/24-game.lasso
Normal file
70
Task/24-game/Lasso/24-game.lasso
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
[
|
||||
if(sys_listunboundmethods !>> 'randoms') => {
|
||||
define randoms()::array => {
|
||||
local(out = array)
|
||||
loop(4) => { #out->insert(math_random(9,1)) }
|
||||
return #out
|
||||
}
|
||||
}
|
||||
if(sys_listunboundmethods !>> 'checkvalid') => {
|
||||
define checkvalid(str::string, nums::array)::boolean => {
|
||||
local(chk = array('*','/','+','-','(',')',' '), chknums = array, lastintpos = -1, poscounter = 0)
|
||||
loop(9) => { #chk->insert(loop_count) }
|
||||
with s in #str->values do => {
|
||||
#poscounter++
|
||||
#chk !>> #s && #chk !>> integer(#s) ? return false
|
||||
integer(#s) > 0 && #lastintpos + 1 >= #poscounter ? return false
|
||||
integer(#s) > 0 ? #chknums->insert(integer(#s))
|
||||
integer(#s) > 0 ? #lastintpos = #poscounter
|
||||
}
|
||||
#chknums->size != 4 ? return false
|
||||
#nums->sort
|
||||
#chknums->sort
|
||||
loop(4) => { #nums->get(loop_count) != #chknums(loop_count) ? return false }
|
||||
return true
|
||||
}
|
||||
}
|
||||
if(sys_listunboundmethods !>> 'executeexpr') => {
|
||||
define executeexpr(expr::string)::integer => {
|
||||
local(keep = string)
|
||||
with i in #expr->values do => {
|
||||
if(array('*','/','+','-','(',')') >> #i) => {
|
||||
#keep->append(#i)
|
||||
else
|
||||
integer(#i) > 0 ? #keep->append(decimal(#i))
|
||||
}
|
||||
}
|
||||
return integer(sourcefile('['+#keep+']','24game',true,true)->invoke)
|
||||
}
|
||||
}
|
||||
|
||||
local(numbers = array, exprsafe = true, exprcorrect = false, exprresult = 0)
|
||||
if(web_request->param('nums')->asString->size) => {
|
||||
with n in web_request->param('nums')->asString->split(',') do => { #numbers->insert(integer(#n->trim&)) }
|
||||
}
|
||||
#numbers->size != 4 ? #numbers = randoms()
|
||||
if(web_request->param('nums')->asString->size) => {
|
||||
#exprsafe = checkvalid(web_request->param('expr')->asString,#numbers)
|
||||
if(#exprsafe) => {
|
||||
#exprresult = executeexpr(web_request->param('expr')->asString)
|
||||
#exprresult == 24 ? #exprcorrect = true
|
||||
}
|
||||
}
|
||||
|
||||
]<h1>24 Game</h1>
|
||||
<p><b>Rules:</b><br>
|
||||
Enter an expression that evaluates to 24</p>
|
||||
<ul>
|
||||
<li>Only multiplication, division, addition, and subtraction operators/functions are allowed.</li>
|
||||
<li>Brackets are allowed.</li>
|
||||
<li>Forming multiple digit numbers from the supplied digits is disallowed. (So an answer of 12+12 when given 1, 2, 2, and 1 is wrong).</li>
|
||||
<li>The order of the digits when given does not have to be preserved.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Numbers</h2>
|
||||
<p>[#numbers->join(', ')] (<a href="?">Reload</a>)</p>
|
||||
[!#exprsafe ? '<p>Please provide a valid expression</p>']
|
||||
<form><input type="hidden" value="[#numbers->join(',')]" name="nums"><input type="text" name="expr" value="[web_request->param('expr')->asString]"><input type="submit" name="submit" value="submit"></form>
|
||||
[if(#exprsafe)]
|
||||
<p>Result: <b>[#exprresult]</b> [#exprcorrect ? 'is CORRECT!' | 'is incorrect']</p>
|
||||
[/if]
|
||||
5
Task/24-game/LiveCode/24-game-1.livecode
Normal file
5
Task/24-game/LiveCode/24-game-1.livecode
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
on mouseUp
|
||||
put empty into fld "EvalField"
|
||||
put empty into fld "AnswerField"
|
||||
put random(9) & comma & random(9) & comma & random(9) & comma & random(9) into fld "YourNumbersField"
|
||||
end mouseUp
|
||||
30
Task/24-game/LiveCode/24-game-2.livecode
Normal file
30
Task/24-game/LiveCode/24-game-2.livecode
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
on keyDown k
|
||||
local ops, nums, allowedKeys, numsCopy, expr
|
||||
put "+,-,/,*,(,)" into ops
|
||||
put the text of fld "YourNumbersField" into nums
|
||||
put the text of fld "EvalField" into expr
|
||||
if matchText(expr & k,"\d\d") then
|
||||
answer "You can't enter 2 digits together"
|
||||
exit keyDown
|
||||
end if
|
||||
repeat with n = 1 to the number of chars of expr
|
||||
if offset(char n of expr, nums) > 0 then
|
||||
delete char offset(char n of expr, nums) of nums
|
||||
end if
|
||||
end repeat
|
||||
put ops & comma & nums into allowedKeys
|
||||
if k is among the items of allowedKeys then
|
||||
put k after expr
|
||||
delete char offset(k, nums) of nums
|
||||
replace comma with empty in nums
|
||||
try
|
||||
put the value of merge("[[expr]]") into fld "AnswerField"
|
||||
if the value of fld "AnswerField" is 24 and nums is empty then
|
||||
answer "You win!"
|
||||
end if
|
||||
end try
|
||||
pass keyDown
|
||||
else
|
||||
exit keyDown
|
||||
end if
|
||||
end keyDown
|
||||
40
Task/24-game/Nim/24-game.nim
Normal file
40
Task/24-game/Nim/24-game.nim
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import math, strutils, algorithm, sequtils
|
||||
randomize()
|
||||
|
||||
template newSeqWith(len: int, init: expr): expr =
|
||||
var result {.gensym.} = newSeq[type(init)](len)
|
||||
for i in 0 .. <len:
|
||||
result[i] = init
|
||||
result
|
||||
|
||||
var
|
||||
problem = newSeqWith(4, random(1..9))
|
||||
stack = newSeq[float]()
|
||||
digits = newSeq[int]()
|
||||
|
||||
echo "Make 24 with the digits: ", problem
|
||||
|
||||
template op(c): stmt =
|
||||
let a = stack.pop
|
||||
stack.add c(stack.pop, a)
|
||||
|
||||
for c in stdin.readLine:
|
||||
case c
|
||||
of '1'..'9':
|
||||
digits.add c.ord - '0'.ord
|
||||
stack.add float(c.ord - '0'.ord)
|
||||
of '+': op `+`
|
||||
of '*': op `*`
|
||||
of '-': op `-`
|
||||
of '/': op `/`
|
||||
of Whitespace: discard
|
||||
else: raise ValueError.newException "Wrong char: " & c
|
||||
|
||||
sort digits, cmp[int]
|
||||
sort problem, cmp[int]
|
||||
if digits.deduplicate != problem.deduplicate:
|
||||
raise ValueError.newException "Not using the given digits."
|
||||
if stack.len != 1:
|
||||
raise ValueError.newException "Wrong expression."
|
||||
echo "Result: ", stack[0]
|
||||
echo if abs(stack[0] - 24) < 0.001: "Good job!" else: "Try again."
|
||||
19
Task/24-game/Oforth/24-game.oforth
Normal file
19
Task/24-game/Oforth/24-game.oforth
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
: 24game
|
||||
| l expr w n i |
|
||||
ListBuffer init(4, #[ 9 rand ]) ->l
|
||||
|
||||
System.Out "Digits : " << l << " --> RPN Expression for 24 : " << drop
|
||||
System.Console askln ->expr
|
||||
|
||||
expr words forEach: w [
|
||||
w "+" == ifTrue: [ + continue ]
|
||||
w "-" == ifTrue: [ - continue ]
|
||||
w "*" == ifTrue: [ * continue ]
|
||||
w "/" == ifTrue: [ asFloat / continue ]
|
||||
|
||||
w asInteger dup ->n ifNull: [ System.Out "Word " << w << " not allowed " << cr break ]
|
||||
l indexOf(n) dup ->i ifNull: [ System.Out "Integer " << n << " is wrong " << cr break ]
|
||||
n l put(i, null)
|
||||
]
|
||||
l conform(#isNull) ifFalse: [ "Sorry, all numbers must be used..." println return ]
|
||||
24 == ifTrue: [ "You won !" ] else: [ "You loose..." ] println ;
|
||||
177
Task/24-game/Phix/24-game.phix
Normal file
177
Task/24-game/Phix/24-game.phix
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
-- Note this uses simple/strict left association, so for example:
|
||||
-- 1+2*1*8 is ((1+2)*1)*8 not 1+((2*1)*8) [or 1+(2*(1*8))], and
|
||||
-- 7-(2*2)*8 is (7-(2*2))*8 not 7-((2*2)*8)
|
||||
-- Does not allow unary minus on the first digit.
|
||||
-- Uses solve24() from the next task, when it can.
|
||||
-- (you may want to comment out the last 2 lines/uncomment the if 0, in that file)
|
||||
--
|
||||
--include 24_game_solve.exw
|
||||
|
||||
--with trace
|
||||
forward function eval(string equation, sequence unused, integer idx=1)
|
||||
-- (the above definition is entirely optional, but good coding style)
|
||||
|
||||
constant errorcodes = {"digit expected", -- 1
|
||||
"')' expected", -- 2
|
||||
"digit already used", -- 3
|
||||
"digit not offered", -- 4
|
||||
"operand expected"} -- 5
|
||||
|
||||
function card(integer idx) -- (for error handling)
|
||||
if idx=1 then return "1st" end if
|
||||
if idx=2 then return "2nd" end if
|
||||
-- (assumes expression is less than 21 characters)
|
||||
return sprintf("%dth",idx)
|
||||
end function
|
||||
|
||||
function errorchar(sequence equation, integer idx)
|
||||
if idx>length(equation) then return "" end if
|
||||
return sprintf("(%s)",equation[idx])
|
||||
end function
|
||||
|
||||
sequence rset = repeat(0,4)
|
||||
|
||||
procedure new_rset()
|
||||
for i=1 to length(rset) do
|
||||
rset[i] = rand(9)
|
||||
end for
|
||||
end procedure
|
||||
|
||||
function get_operand(string equation, integer idx, sequence unused)
|
||||
integer ch, k,
|
||||
error = 1 -- "digit expected"
|
||||
atom res
|
||||
|
||||
if idx<=length(equation) then
|
||||
ch = equation[idx]
|
||||
if ch='(' then
|
||||
{error,res,unused,idx} = eval(equation,unused,idx+1)
|
||||
if error=0
|
||||
and idx<=length(equation) then
|
||||
ch = equation[idx]
|
||||
if ch=')' then
|
||||
return {0,res,unused,idx+1}
|
||||
end if
|
||||
end if
|
||||
if error=0 then
|
||||
error = 2 -- "')' expected"
|
||||
end if
|
||||
elsif ch>='0' and ch<='9' then
|
||||
res = ch-'0'
|
||||
k = find(res,unused)
|
||||
if k!=0 then
|
||||
unused[k..k] = {}
|
||||
return {0,res,unused,idx+1}
|
||||
end if
|
||||
if find(res,rset) then
|
||||
error = 3 -- "digit already used"
|
||||
else
|
||||
error = 4 -- "digit not offered"
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
return {error,0,unused,idx}
|
||||
end function
|
||||
|
||||
function get_operator(string equation, integer idx)
|
||||
integer ch, error = 5 -- "operand expected"
|
||||
if idx<=length(equation) then
|
||||
ch = equation[idx]
|
||||
if find(ch,"+-/*") then
|
||||
return {0,ch,idx+1}
|
||||
end if
|
||||
end if
|
||||
return {error,0,idx}
|
||||
end function
|
||||
|
||||
function eval(string equation, sequence unused, integer idx=1)
|
||||
atom lhs, rhs
|
||||
integer ch, error
|
||||
{error,lhs,unused,idx} = get_operand(equation,idx,unused)
|
||||
if error=0 then
|
||||
while 1 do
|
||||
{error,ch,idx} = get_operator(equation,idx)
|
||||
if error!=0 then exit end if
|
||||
{error,rhs,unused,idx} = get_operand(equation,idx,unused)
|
||||
if error!=0 then exit end if
|
||||
if ch='+' then lhs += rhs
|
||||
elsif ch='-' then lhs -= rhs
|
||||
elsif ch='/' then lhs /= rhs
|
||||
elsif ch='*' then lhs *= rhs
|
||||
else ?9/0 -- (should not happen)
|
||||
end if
|
||||
if idx>length(equation) then
|
||||
return {0,lhs,unused,idx}
|
||||
end if
|
||||
ch = equation[idx]
|
||||
if ch=')' then
|
||||
return {0,lhs,unused,idx}
|
||||
end if
|
||||
end while
|
||||
end if
|
||||
return {error,0,unused,idx}
|
||||
end function
|
||||
|
||||
function strip(string equation)
|
||||
for i=length(equation) to 1 by -1 do
|
||||
if find(equation[i]," \t\r\n") then
|
||||
equation[i..i] = ""
|
||||
end if
|
||||
end for
|
||||
return equation
|
||||
end function
|
||||
|
||||
function strip0(atom a) -- (for error handling)
|
||||
string res = sprintf("%f",a)
|
||||
integer ch
|
||||
for i=length(res) to 2 by -1 do
|
||||
ch = res[i]
|
||||
if ch='.' then return res[1..i-1] end if
|
||||
if ch!='0' then return res[1..i] end if
|
||||
end for
|
||||
return res
|
||||
end function
|
||||
|
||||
procedure play()
|
||||
sequence unused
|
||||
string equation
|
||||
integer error,idx
|
||||
atom res
|
||||
|
||||
new_rset()
|
||||
printf(1,"Enter an expression which evaluates to exactly 24\n"&
|
||||
"Use all of, and only, the digits %d, %d, %d, and %d\n"&
|
||||
"You may only use the operators + - * /\n"&
|
||||
"Parentheses and spaces are allowed\n",rset)
|
||||
while 1 do
|
||||
equation = strip(gets(0))
|
||||
if upper(equation)="Q" then exit end if
|
||||
if equation="?" then
|
||||
puts(1,"\n")
|
||||
integer r_solve24 = routine_id("solve24") -- see below
|
||||
if r_solve24=-1 then -- (someone copied just this code out?)
|
||||
puts(1,"no solve24 routine\n")
|
||||
else
|
||||
call_proc(r_solve24,{rset})
|
||||
end if
|
||||
else
|
||||
{error,res,unused,idx} = eval(equation, rset)
|
||||
if error!=0 then
|
||||
printf(1," %s on the %s character%s\n",{errorcodes[error],card(idx),errorchar(equation,idx)})
|
||||
elsif idx<=length(equation) then
|
||||
printf(1,"\neval() returned only having processed %d of %d characters\n",{idx,length(equation)})
|
||||
elsif length(unused) then
|
||||
printf(1," not all the digits were used\n",error)
|
||||
elsif res!=24 then
|
||||
printf(1,"\nresult is %s, not 24\n",{strip0(res)})
|
||||
else
|
||||
puts(1," correct! Press any key to quit\n")
|
||||
if getc(0) then end if
|
||||
exit
|
||||
end if
|
||||
end if
|
||||
puts(1,"enter Q to give up and quit\n")
|
||||
end while
|
||||
end procedure
|
||||
|
||||
play()
|
||||
40
Task/24-game/Potion/24-game.potion
Normal file
40
Task/24-game/Potion/24-game.potion
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
is_num = (s):
|
||||
x = s ord(0)
|
||||
if (x >= "0"ord && x <= "9"ord): true.
|
||||
else: false.
|
||||
.
|
||||
|
||||
nums = (s):
|
||||
res = ()
|
||||
0 to (s length, (b):
|
||||
c = s(b)
|
||||
if (is_num(c)):
|
||||
res push(c).
|
||||
.)
|
||||
res.
|
||||
|
||||
try = 1
|
||||
while (true):
|
||||
r = rand string
|
||||
digits = (r(0),r(1),r(2),r(3))
|
||||
"\nMy next four digits: " print
|
||||
digits join(" ") say
|
||||
digit_s = digits ins_sort string
|
||||
|
||||
("Your expression to create 24 (try ", try, "): ") print
|
||||
entry = read slice(0,-1)
|
||||
expr = entry eval
|
||||
parse = nums(entry)
|
||||
parse_s = parse clone ins_sort string
|
||||
try++
|
||||
if (parse length != 4):
|
||||
("Wrong number of digits:", parse) say.
|
||||
elsif (parse_s != digit_s):
|
||||
("Wrong digits:", parse) say.
|
||||
elsif (expr == 24):
|
||||
"You won!" say
|
||||
entry print, " => 24" say
|
||||
return().
|
||||
else:
|
||||
(entry, " => ", expr string, " != 24") join("") say.
|
||||
.
|
||||
36
Task/24-game/Sidef/24-game.sidef
Normal file
36
Task/24-game/Sidef/24-game.sidef
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
const digits = (1..9 -> pick(4));
|
||||
const grammar = Regex.new(
|
||||
'^ (?&exp) \z
|
||||
(?(DEFINE)
|
||||
(?<exp> ( (?&term) (?&op) (?&term) )+ )
|
||||
(?<term> \( (?&exp) \) | [' + digits.join + '])
|
||||
(?<op> [-+*/] )
|
||||
)', 'x'
|
||||
);
|
||||
|
||||
say "Here are your digits: #{digits.join(' ')}";
|
||||
|
||||
loop {
|
||||
var input = Sys.scanln("Expression: ");
|
||||
|
||||
var expr = input;
|
||||
expr -= /\s+/g; # remove all whitespace
|
||||
|
||||
input == 'q' && (
|
||||
say "Goodbye. Sorry you couldn't win.";
|
||||
break;
|
||||
);
|
||||
|
||||
var given_digits = digits.map{.to_s}.sort.join;
|
||||
var entry_digits = input.scan(/\d/).sort.join;
|
||||
|
||||
if ((given_digits != entry_digits) || (expr !~ grammar)) {
|
||||
say "That's not valid";
|
||||
next;
|
||||
}
|
||||
|
||||
given(var n = eval(input)) {
|
||||
when (24) { say "You win!"; break }
|
||||
default { say "Sorry, your expression is #{n}, not 24" }
|
||||
}
|
||||
}
|
||||
74
Task/24-game/Swift/24-game.swift
Normal file
74
Task/24-game/Swift/24-game.swift
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import Darwin
|
||||
import Foundation
|
||||
|
||||
println("24 Game")
|
||||
println("Generating 4 digits...")
|
||||
|
||||
func randomDigits() -> Int[] {
|
||||
var result = Int[]();
|
||||
for var i = 0; i < 4; i++ {
|
||||
result.append(Int(arc4random_uniform(9)+1))
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Choose 4 digits
|
||||
let digits = randomDigits()
|
||||
|
||||
print("Make 24 using these digits : ")
|
||||
|
||||
for digit in digits {
|
||||
print("\(digit) ")
|
||||
}
|
||||
println()
|
||||
|
||||
// get input from operator
|
||||
var input = NSString(data:NSFileHandle.fileHandleWithStandardInput().availableData, encoding:NSUTF8StringEncoding)
|
||||
|
||||
var enteredDigits = Int[]()
|
||||
|
||||
var enteredOperations = Character[]()
|
||||
|
||||
let inputString = input as String
|
||||
|
||||
// store input in the appropriate table
|
||||
for character in inputString {
|
||||
switch character {
|
||||
case "1", "2", "3", "4", "5", "6", "7", "8", "9":
|
||||
let digit = String(character)
|
||||
enteredDigits.append(digit.toInt()!)
|
||||
case "+", "-", "*", "/":
|
||||
enteredOperations.append(character)
|
||||
case "\n":
|
||||
println()
|
||||
default:
|
||||
println("Invalid expression")
|
||||
}
|
||||
}
|
||||
|
||||
// check value of expression provided by the operator
|
||||
var value = Int()
|
||||
|
||||
if enteredDigits.count == 4 && enteredOperations.count == 3 {
|
||||
value = enteredDigits[0]
|
||||
for (i, operation) in enumerate(enteredOperations) {
|
||||
switch operation {
|
||||
case "+":
|
||||
value = value + enteredDigits[i+1]
|
||||
case "-":
|
||||
value = value - enteredDigits[i+1]
|
||||
case "*":
|
||||
value = value * enteredDigits[i+1]
|
||||
case "/":
|
||||
value = value / enteredDigits[i+1]
|
||||
default:
|
||||
println("This message should never happen!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if value != 24 {
|
||||
println("The value of the provided expression is \(value) instead of 24!")
|
||||
} else {
|
||||
println("Congratulations, you found a solution!")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue