2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,18 +1,28 @@
|
|||
The [[wp:24 Game|24 Game]] tests one's mental arithmetic.
|
||||
|
||||
Write a program that [[task feature::Rosetta Code:randomness|randomly]] chooses and [[task feature::Rosetta Code:user output|displays]] four digits, each from one to nine, with repetitions allowed. The program should prompt for the player to enter an arithmetic expression using ''just'' those, and ''all'' of those four digits, used exactly ''once'' each. The program should ''check'' then [[task feature::Rosetta Code:parsing|evaluate the expression]].
|
||||
The goal is for the player to [[task feature::Rosetta Code:user input|enter]] an expression that evaluates to '''24'''.
|
||||
* Only multiplication, division, addition, and subtraction operators/functions are allowed.
|
||||
* Division should use floating point or rational arithmetic, etc, to preserve remainders.
|
||||
* Brackets are allowed, if using an infix expression evaluator.
|
||||
* 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).
|
||||
* The order of the digits when given does not have to be preserved.
|
||||
|
||||
Note:
|
||||
;Task
|
||||
Write a program that [[task feature::Rosetta Code:randomness|randomly]] chooses and [[task feature::Rosetta Code:user output|displays]] four digits, each from 1 ──► 9 (inclusive) with repetitions allowed.
|
||||
|
||||
The program should prompt for the player to enter an arithmetic expression using ''just'' those, and ''all'' of those four digits, used exactly ''once'' each. The program should ''check'' then [[task feature::Rosetta Code:parsing|evaluate the expression]].
|
||||
|
||||
The goal is for the player to [[task feature::Rosetta Code:user input|enter]] an expression that (numerically) evaluates to '''24'''.
|
||||
* Only the following operators/functions are allowed: multiplication, division, addition, subtraction
|
||||
* Division should use floating point or rational arithmetic, etc, to preserve remainders.
|
||||
* Brackets are allowed, if using an infix expression evaluator.
|
||||
* 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).
|
||||
* The order of the digits when given does not have to be preserved.
|
||||
|
||||
<br>
|
||||
;Notes
|
||||
* The type of expression evaluator used is not mandated. An [[wp:Reverse Polish notation|RPN]] evaluator is equally acceptable for example.
|
||||
* The task is not for the program to generate the expression, or test whether an expression is even possible.
|
||||
|
||||
C.f: [[24 game Player]]
|
||||
|
||||
'''Reference'''
|
||||
# [http://www.bbc.co.uk/dna/h2g2/A933121 The 24 Game] on h2g2.
|
||||
;Related tasks
|
||||
* [[24 game/Solve]]
|
||||
|
||||
|
||||
;Reference
|
||||
* [http://www.bbc.co.uk/dna/h2g2/A933121 The 24 Game] on h2g2.
|
||||
<br><br>
|
||||
|
|
|
|||
843
Task/24-game/COBOL/24-game.cobol
Normal file
843
Task/24-game/COBOL/24-game.cobol
Normal file
|
|
@ -0,0 +1,843 @@
|
|||
>>SOURCE FORMAT FREE
|
||||
*> This code is dedicated to the public domain
|
||||
*> This is GNUCobol 2.0
|
||||
identification division.
|
||||
program-id. twentyfour.
|
||||
environment division.
|
||||
configuration section.
|
||||
repository. function all intrinsic.
|
||||
data division.
|
||||
working-storage section.
|
||||
01 p pic 999.
|
||||
01 p1 pic 999.
|
||||
01 p-max pic 999 value 38.
|
||||
01 program-syntax pic x(494) value
|
||||
*>statement = expression;
|
||||
'001 001 000 n'
|
||||
& '002 000 004 ='
|
||||
& '003 005 000 n'
|
||||
& '004 000 002 ;'
|
||||
*>expression = term, {('+'|'-') term,};
|
||||
& '005 005 000 n'
|
||||
& '006 000 016 ='
|
||||
& '007 017 000 n'
|
||||
& '008 000 015 {'
|
||||
& '009 011 013 ('
|
||||
& '010 001 000 t'
|
||||
& '011 013 000 |'
|
||||
& '012 002 000 t'
|
||||
& '013 000 009 )'
|
||||
& '014 017 000 n'
|
||||
& '015 000 008 }'
|
||||
& '016 000 006 ;'
|
||||
*>term = factor, {('*'|'/') factor,};
|
||||
& '017 017 000 n'
|
||||
& '018 000 028 ='
|
||||
& '019 029 000 n'
|
||||
& '020 000 027 {'
|
||||
& '021 023 025 ('
|
||||
& '022 003 000 t'
|
||||
& '023 025 000 |'
|
||||
& '024 004 000 t'
|
||||
& '025 000 021 )'
|
||||
& '026 029 000 n'
|
||||
& '027 000 020 }'
|
||||
& '028 000 018 ;'
|
||||
*>factor = ('(' expression, ')' | digit,);
|
||||
& '029 029 000 n'
|
||||
& '030 000 038 ='
|
||||
& '031 035 037 ('
|
||||
& '032 005 000 t'
|
||||
& '033 005 000 n'
|
||||
& '034 006 000 t'
|
||||
& '035 037 000 |'
|
||||
& '036 000 000 n'
|
||||
& '037 000 031 )'
|
||||
& '038 000 030 ;'.
|
||||
01 filler redefines program-syntax.
|
||||
03 p-entry occurs 038.
|
||||
05 p-address pic 999.
|
||||
05 filler pic x.
|
||||
05 p-definition pic 999.
|
||||
05 p-alternate redefines p-definition pic 999.
|
||||
05 filler pic x.
|
||||
05 p-matching pic 999.
|
||||
05 filler pic x.
|
||||
05 p-symbol pic x.
|
||||
|
||||
01 t pic 999.
|
||||
01 t-len pic 99 value 6.
|
||||
01 terminal-symbols
|
||||
pic x(210) value
|
||||
'01 + '
|
||||
& '01 - '
|
||||
& '01 * '
|
||||
& '01 / '
|
||||
& '01 ( '
|
||||
& '01 ) '.
|
||||
01 filler redefines terminal-symbols.
|
||||
03 terminal-symbol-entry occurs 6.
|
||||
05 terminal-symbol-len pic 99.
|
||||
05 filler pic x.
|
||||
05 terminal-symbol pic x(32).
|
||||
|
||||
01 nt pic 999.
|
||||
01 nt-lim pic 99 value 5.
|
||||
01 nonterminal-statements pic x(294) value
|
||||
"000 ....,....,....,....,....,....,....,....,....,"
|
||||
& "001 statement = expression; "
|
||||
& "005 expression = term, {('+'|'-') term,}; "
|
||||
& "017 term = factor, {('*'|'/') factor,}; "
|
||||
& "029 factor = ('(' expression, ')' | digit,); "
|
||||
& "036 digit; ".
|
||||
01 filler redefines nonterminal-statements.
|
||||
03 nonterminal-statement-entry occurs 5.
|
||||
05 nonterminal-statement-number pic 999.
|
||||
05 filler pic x.
|
||||
05 nonterminal-statement pic x(45).
|
||||
|
||||
01 indent pic x(64) value all '| '.
|
||||
01 interpreter-stack.
|
||||
03 r pic 99. *> previous top of stack
|
||||
03 s pic 99. *> current top of stack
|
||||
03 s-max pic 99 value 32.
|
||||
03 s-entry occurs 32.
|
||||
05 filler pic x(2) value 'p='.
|
||||
05 s-p pic 999. *> callers return address
|
||||
05 filler pic x(4) value ' sc='.
|
||||
05 s-start-control pic 999. *> sequence start address
|
||||
05 filler pic x(4) value ' ec='.
|
||||
05 s-end-control pic 999. *> sequence end address
|
||||
05 filler pic x(4) value ' al='.
|
||||
05 s-alternate pic 999. *> the next alternate
|
||||
05 filler pic x(3) value ' r='.
|
||||
05 s-result pic x. *> S success, F failure, N no result
|
||||
05 filler pic x(3) value ' c='.
|
||||
05 s-count pic 99. *> successes in a sequence
|
||||
05 filler pic x(3) value ' x='.
|
||||
05 s-repeat pic 99. *> repeats in a {} sequence
|
||||
05 filler pic x(4) value ' nt='.
|
||||
05 s-nt pic 99. *> current nonterminal
|
||||
|
||||
01 language-area.
|
||||
03 l pic 99.
|
||||
03 l-lim pic 99.
|
||||
03 l-len pic 99 value 1.
|
||||
03 nd pic 9.
|
||||
03 number-definitions.
|
||||
05 n occurs 4 pic 9.
|
||||
03 nu pic 9.
|
||||
03 number-use.
|
||||
05 u occurs 4 pic x.
|
||||
03 statement.
|
||||
05 c occurs 32.
|
||||
07 c9 pic 9.
|
||||
|
||||
01 number-validation.
|
||||
03 p4 pic 99.
|
||||
03 p4-lim pic 99 value 24.
|
||||
03 permutations-4 pic x(96) value
|
||||
'1234'
|
||||
& '1243'
|
||||
& '1324'
|
||||
& '1342'
|
||||
& '1423'
|
||||
& '1432'
|
||||
& '2134'
|
||||
& '2143'
|
||||
& '2314'
|
||||
& '2341'
|
||||
& '2413'
|
||||
& '2431'
|
||||
& '3124'
|
||||
& '3142'
|
||||
& '3214'
|
||||
& '3241'
|
||||
& '3423'
|
||||
& '3432'
|
||||
& '4123'
|
||||
& '4132'
|
||||
& '4213'
|
||||
& '4231'
|
||||
& '4312'
|
||||
& '4321'.
|
||||
03 filler redefines permutations-4.
|
||||
05 permutation-4 occurs 24 pic x(4).
|
||||
03 current-permutation-4 pic x(4).
|
||||
03 cpx pic 9.
|
||||
03 od1 pic 9.
|
||||
03 od2 pic 9.
|
||||
03 odx pic 9.
|
||||
03 od-lim pic 9 value 4.
|
||||
03 operator-definitions pic x(4) value '+-*/'.
|
||||
03 current-operators pic x(3).
|
||||
03 co3 pic 9.
|
||||
03 rpx pic 9.
|
||||
03 rpx-lim pic 9 value 4.
|
||||
03 valid-rpn-forms pic x(28) value
|
||||
'nnonono'
|
||||
& 'nnnonoo'
|
||||
& 'nnnoono'
|
||||
& 'nnnnooo'.
|
||||
03 filler redefines valid-rpn-forms.
|
||||
05 rpn-form occurs 4 pic x(7).
|
||||
03 current-rpn-form pic x(7).
|
||||
|
||||
01 calculation-area.
|
||||
03 osx pic 99.
|
||||
03 operator-stack pic x(32).
|
||||
03 oqx pic 99.
|
||||
03 oqx1 pic 99.
|
||||
03 output-queue pic x(32).
|
||||
03 work-number pic s9999.
|
||||
03 top-numerator pic s9999 sign leading separate.
|
||||
03 top-denominator pic s9999 sign leading separate.
|
||||
03 rsx pic 9.
|
||||
03 result-stack occurs 8.
|
||||
05 numerator pic s9999.
|
||||
05 denominator pic s9999.
|
||||
|
||||
01 error-found pic x.
|
||||
01 divide-by-zero-error pic x.
|
||||
|
||||
*> diagnostics
|
||||
01 NL pic x value x'0A'.
|
||||
01 NL-flag pic x value space.
|
||||
01 display-level pic x value '0'.
|
||||
01 loop-lim pic 9999 value 1500.
|
||||
01 loop-count pic 9999 value 0.
|
||||
01 message-area value spaces.
|
||||
03 message-level pic x.
|
||||
03 message-value pic x(128).
|
||||
|
||||
*> input and examples
|
||||
01 instruction pic x(32) value spaces.
|
||||
01 tsx pic 99.
|
||||
01 tsx-lim pic 99 value 14.
|
||||
01 test-statements.
|
||||
03 filler pic x(32) value '1234;1 + 2 + 3 + 4'.
|
||||
03 filler pic x(32) value '1234;1 * 2 * 3 * 4'.
|
||||
03 filler pic x(32) value '1234;((1)) * (((2 * 3))) * 4'.
|
||||
03 filler pic x(32) value '1234;((1)) * ((2 * 3))) * 4'.
|
||||
03 filler pic x(32) value '1234;(1 + 2 + 3 + 4'.
|
||||
03 filler pic x(32) value '1234;)1 + 2 + 3 + 4'.
|
||||
03 filler pic x(32) value '1234;1 * * 2 * 3 * 4'.
|
||||
03 filler pic x(32) value '5679;6 - (5 - 7) * 9'.
|
||||
03 filler pic x(32) value '1268;((1 * (8 * 6) / 2))'.
|
||||
03 filler pic x(32) value '4583;-5-3+(8*4)'.
|
||||
03 filler pic x(32) value '4583;8 * 4 - 5 - 3'.
|
||||
03 filler pic x(32) value '4583;8 * 4 - (5 + 3)'.
|
||||
03 filler pic x(32) value '1223;1 * 3 / (2 - 2)'.
|
||||
03 filler pic x(32) value '2468;(6 * 8) / 4 / 2'.
|
||||
01 filler redefines test-statements.
|
||||
03 filler occurs 14.
|
||||
05 test-numbers pic x(4).
|
||||
05 filler pic x.
|
||||
05 test-statement pic x(27).
|
||||
|
||||
procedure division.
|
||||
start-twentyfour.
|
||||
display 'start twentyfour'
|
||||
perform generate-numbers
|
||||
display 'type h <enter> to see instructions'
|
||||
accept instruction
|
||||
perform until instruction = spaces or 'q'
|
||||
evaluate true
|
||||
when instruction = 'h'
|
||||
perform display-instructions
|
||||
when instruction = 'n'
|
||||
perform generate-numbers
|
||||
when instruction(1:1) = 'm'
|
||||
move instruction(2:4) to number-definitions
|
||||
perform validate-number
|
||||
if divide-by-zero-error = space
|
||||
and 24 * top-denominator = top-numerator
|
||||
display number-definitions ' is solved by ' output-queue(1:oqx)
|
||||
else
|
||||
display number-definitions ' is not solvable'
|
||||
end-if
|
||||
when instruction = 'd0' or 'd1' or 'd2' or 'd3'
|
||||
move instruction(2:1) to display-level
|
||||
when instruction = 'e'
|
||||
display 'examples:'
|
||||
perform varying tsx from 1 by 1
|
||||
until tsx > tsx-lim
|
||||
move spaces to statement
|
||||
move test-numbers(tsx) to number-definitions
|
||||
move test-statement(tsx) to statement
|
||||
perform evaluate-statement
|
||||
perform show-result
|
||||
end-perform
|
||||
when other
|
||||
move instruction to statement
|
||||
perform evaluate-statement
|
||||
perform show-result
|
||||
end-evaluate
|
||||
move spaces to instruction
|
||||
display 'instruction? ' with no advancing
|
||||
accept instruction
|
||||
end-perform
|
||||
|
||||
display 'exit twentyfour'
|
||||
stop run
|
||||
.
|
||||
generate-numbers.
|
||||
perform with test after until divide-by-zero-error = space
|
||||
and 24 * top-denominator = top-numerator
|
||||
compute n(1) = random(seconds-past-midnight) * 10 *> seed
|
||||
perform varying nd from 1 by 1 until nd > 4
|
||||
compute n(nd) = random() * 10
|
||||
perform until n(nd) <> 0
|
||||
compute n(nd) = random() * 10
|
||||
end-perform
|
||||
end-perform
|
||||
perform validate-number
|
||||
end-perform
|
||||
display NL 'numbers:' with no advancing
|
||||
perform varying nd from 1 by 1 until nd > 4
|
||||
display space n(nd) with no advancing
|
||||
end-perform
|
||||
display space
|
||||
.
|
||||
validate-number.
|
||||
perform varying p4 from 1 by 1 until p4 > p4-lim
|
||||
move permutation-4(p4) to current-permutation-4
|
||||
perform varying od1 from 1 by 1 until od1 > od-lim
|
||||
move operator-definitions(od1:1) to current-operators(1:1)
|
||||
perform varying od2 from 1 by 1 until od2 > od-lim
|
||||
move operator-definitions(od2:1) to current-operators(2:1)
|
||||
perform varying odx from 1 by 1 until odx > od-lim
|
||||
move operator-definitions(odx:1) to current-operators(3:1)
|
||||
perform varying rpx from 1 by 1 until rpx > rpx-lim
|
||||
move rpn-form(rpx) to current-rpn-form
|
||||
move 0 to cpx co3
|
||||
move spaces to output-queue
|
||||
move 7 to oqx
|
||||
perform varying oqx1 from 1 by 1 until oqx1 > oqx
|
||||
if current-rpn-form(oqx1:1) = 'n'
|
||||
add 1 to cpx
|
||||
move current-permutation-4(cpx:1) to nd
|
||||
move n(nd) to output-queue(oqx1:1)
|
||||
else
|
||||
add 1 to co3
|
||||
move current-operators(co3:1) to output-queue(oqx1:1)
|
||||
end-if
|
||||
end-perform
|
||||
end-perform
|
||||
perform evaluate-rpn
|
||||
if divide-by-zero-error = space
|
||||
and 24 * top-denominator = top-numerator
|
||||
exit paragraph
|
||||
end-if
|
||||
end-perform
|
||||
end-perform
|
||||
end-perform
|
||||
end-perform
|
||||
.
|
||||
display-instructions.
|
||||
display '1) Type h <enter> to repeat these instructions.'
|
||||
display '2) The program will display four randomly-generated'
|
||||
display ' single-digit numbers and will then prompt you to enter'
|
||||
display ' an arithmetic expression followed by <enter> to sum'
|
||||
display ' the given numbers to 24.'
|
||||
display ' The four numbers may contain duplicates and the entered'
|
||||
display ' expression must reference all the generated numbers and duplicates.'
|
||||
display ' Warning: the program converts the entered infix expression'
|
||||
display ' to a reverse polish notation (rpn) expression'
|
||||
display ' which is then interpreted from RIGHT to LEFT.'
|
||||
display ' So, for instance, 8*4 - 5 - 3 will not sum to 24.'
|
||||
display '3) Type n <enter> to generate a new set of four numbers.'
|
||||
display ' The program will ensure the generated numbers are solvable.'
|
||||
display '4) Type m#### <enter> (e.g. m1234) to create a fixed set of numbers'
|
||||
display ' for testing purposes.'
|
||||
display ' The program will test the solvability of the entered numbers.'
|
||||
display ' For example, m1234 is solvable and m9999 is not solvable.'
|
||||
display '5) Type d0, d1, d2 or d3 followed by <enter> to display none or'
|
||||
display ' increasingly detailed diagnostic information as the program evaluates'
|
||||
display ' the entered expression.'
|
||||
display '6) Type e <enter> to see a list of example expressions and results'
|
||||
display '7) Type <enter> or q <enter> to exit the program'
|
||||
.
|
||||
show-result.
|
||||
if error-found = 'y'
|
||||
or divide-by-zero-error = 'y'
|
||||
exit paragraph
|
||||
end-if
|
||||
display 'statement in RPN is' space output-queue
|
||||
evaluate true
|
||||
when top-numerator = 0
|
||||
when top-denominator = 0
|
||||
when 24 * top-denominator <> top-numerator
|
||||
display 'result (' top-numerator '/' top-denominator ') is not 24'
|
||||
when other
|
||||
display 'result is 24'
|
||||
end-evaluate
|
||||
.
|
||||
evaluate-statement.
|
||||
compute l-lim = length(trim(statement))
|
||||
|
||||
display NL 'numbers:' space n(1) space n(2) space n(3) space n(4)
|
||||
move number-definitions to number-use
|
||||
display 'statement is' space statement
|
||||
|
||||
move 1 to l
|
||||
move 0 to loop-count
|
||||
move space to error-found
|
||||
|
||||
move 0 to osx oqx
|
||||
move spaces to output-queue
|
||||
|
||||
move 1 to p
|
||||
move 1 to nt
|
||||
move 0 to s
|
||||
perform increment-s
|
||||
perform display-start-nonterminal
|
||||
perform increment-p
|
||||
|
||||
*>===================================
|
||||
*> interpret ebnf
|
||||
*>===================================
|
||||
perform until s = 0
|
||||
or error-found = 'y'
|
||||
|
||||
evaluate true
|
||||
|
||||
when p-symbol(p) = 'n'
|
||||
and p-definition(p) = 000 *> a variable
|
||||
perform test-variable
|
||||
if s-result(s) = 'S'
|
||||
perform increment-l
|
||||
end-if
|
||||
perform increment-p
|
||||
|
||||
when p-symbol(p) = 'n'
|
||||
and p-address(p) <> p-definition(p) *> nonterminal reference
|
||||
move p to s-p(s)
|
||||
move p-definition(p) to p
|
||||
|
||||
when p-symbol(p) = 'n'
|
||||
and p-address(p) = p-definition(p) *> nonterminal definition
|
||||
perform increment-s
|
||||
perform display-start-nonterminal
|
||||
perform increment-p
|
||||
|
||||
when p-symbol(p) = '=' *> nonterminal control
|
||||
move p to s-start-control(s)
|
||||
move p-matching(p) to s-end-control(s)
|
||||
perform increment-p
|
||||
|
||||
when p-symbol(p) = ';' *> end nonterminal
|
||||
perform display-end-control
|
||||
perform display-end-nonterminal
|
||||
perform decrement-s
|
||||
if s > 0
|
||||
evaluate true
|
||||
when s-result(r) = 'S'
|
||||
perform set-success
|
||||
when s-result(r) = 'F'
|
||||
perform set-failure
|
||||
end-evaluate
|
||||
move s-p(s) to p
|
||||
perform increment-p
|
||||
perform display-continue-nonterminal
|
||||
end-if
|
||||
|
||||
when p-symbol(p) = '{' *> start repeat sequence
|
||||
perform increment-s
|
||||
perform display-start-control
|
||||
move p to s-start-control(s)
|
||||
move p-alternate(p) to s-alternate(s)
|
||||
move p-matching(p) to s-end-control(s)
|
||||
move 0 to s-count(s)
|
||||
perform increment-p
|
||||
|
||||
when p-symbol(p) = '}' *> end repeat sequence
|
||||
perform display-end-control
|
||||
evaluate true
|
||||
when s-result(s) = 'S' *> repeat the sequence
|
||||
perform display-repeat-control
|
||||
perform set-nothing
|
||||
add 1 to s-repeat(s)
|
||||
move s-start-control(s) to p
|
||||
perform increment-p
|
||||
when other
|
||||
perform decrement-s
|
||||
evaluate true
|
||||
when s-result(r) = 'N'
|
||||
and s-repeat(r) = 0 *> no result
|
||||
perform increment-p
|
||||
when s-result(r) = 'N'
|
||||
and s-repeat(r) > 0 *> no result after success
|
||||
perform set-success
|
||||
perform increment-p
|
||||
when other *> fail the sequence
|
||||
perform increment-p
|
||||
end-evaluate
|
||||
end-evaluate
|
||||
|
||||
when p-symbol(p) = '(' *> start sequence
|
||||
perform increment-s
|
||||
perform display-start-control
|
||||
move p to s-start-control(s)
|
||||
move p-alternate(p) to s-alternate(s)
|
||||
move p-matching(p) to s-end-control(s)
|
||||
move 0 to s-count(s)
|
||||
perform increment-p
|
||||
|
||||
when p-symbol(p) = ')' *> end sequence
|
||||
perform display-end-control
|
||||
perform decrement-s
|
||||
evaluate true
|
||||
when s-result(r) = 'S' *> success
|
||||
perform set-success
|
||||
perform increment-p
|
||||
when s-result(r) = 'N' *> no result
|
||||
perform set-failure
|
||||
perform increment-p
|
||||
when other *> fail the sequence
|
||||
perform set-failure
|
||||
perform increment-p
|
||||
end-evaluate
|
||||
|
||||
when p-symbol(p) = '|' *> alternate
|
||||
evaluate true
|
||||
when s-result(s) = 'S' *> exit the sequence
|
||||
perform display-skip-alternate
|
||||
move s-end-control(s) to p
|
||||
when other
|
||||
perform display-take-alternate
|
||||
move p-alternate(p) to s-alternate(s) *> the next alternate
|
||||
perform increment-p
|
||||
perform set-nothing
|
||||
end-evaluate
|
||||
|
||||
when p-symbol(p) = 't' *> terminal
|
||||
move p-definition(p) to t
|
||||
move terminal-symbol-len(t) to t-len
|
||||
perform display-terminal
|
||||
evaluate true
|
||||
when statement(l:t-len) = terminal-symbol(t)(1:t-len) *> successful match
|
||||
perform set-success
|
||||
perform display-recognize-terminal
|
||||
perform process-token
|
||||
move t-len to l-len
|
||||
perform increment-l
|
||||
perform increment-p
|
||||
when s-alternate(s) <> 000 *> we are in an alternate sequence
|
||||
move s-alternate(s) to p
|
||||
when other *> fail the sequence
|
||||
perform set-failure
|
||||
move s-end-control(s) to p
|
||||
end-evaluate
|
||||
|
||||
when other *> end control
|
||||
perform display-control-failure *> shouldnt happen
|
||||
|
||||
end-evaluate
|
||||
|
||||
end-perform
|
||||
|
||||
evaluate true *> at end of evaluation
|
||||
when error-found = 'y'
|
||||
continue
|
||||
when l <= l-lim *> not all tokens parsed
|
||||
display 'error: invalid statement'
|
||||
perform statement-error
|
||||
when number-use <> spaces
|
||||
display 'error: not all numbers were used: ' number-use
|
||||
move 'y' to error-found
|
||||
end-evaluate
|
||||
.
|
||||
increment-l.
|
||||
evaluate true
|
||||
when l > l-lim *> end of statement
|
||||
continue
|
||||
when other
|
||||
add l-len to l
|
||||
perform varying l from l by 1
|
||||
until c(l) <> space
|
||||
or l > l-lim
|
||||
continue
|
||||
end-perform
|
||||
move 1 to l-len
|
||||
if l > l-lim
|
||||
perform end-tokens
|
||||
end-if
|
||||
end-evaluate
|
||||
.
|
||||
increment-p.
|
||||
evaluate true
|
||||
when p >= p-max
|
||||
display 'at' space p ' parse overflow'
|
||||
space 's=<' s space s-entry(s) '>'
|
||||
move 'y' to error-found
|
||||
when other
|
||||
add 1 to p
|
||||
perform display-statement
|
||||
end-evaluate
|
||||
.
|
||||
increment-s.
|
||||
evaluate true
|
||||
when s >= s-max
|
||||
display 'at' space p ' stack overflow '
|
||||
space 's=<' s space s-entry(s) '>'
|
||||
move 'y' to error-found
|
||||
when other
|
||||
move s to r
|
||||
add 1 to s
|
||||
initialize s-entry(s)
|
||||
move 'N' to s-result(s)
|
||||
move p to s-p(s)
|
||||
move nt to s-nt(s)
|
||||
end-evaluate
|
||||
.
|
||||
decrement-s.
|
||||
if s > 0
|
||||
move s to r
|
||||
subtract 1 from s
|
||||
if s > 0
|
||||
move s-nt(s) to nt
|
||||
end-if
|
||||
end-if
|
||||
.
|
||||
set-failure.
|
||||
move 'F' to s-result(s)
|
||||
if s-count(s) > 0
|
||||
display 'sequential parse failure'
|
||||
perform statement-error
|
||||
end-if
|
||||
.
|
||||
set-success.
|
||||
move 'S' to s-result(s)
|
||||
add 1 to s-count(s)
|
||||
.
|
||||
set-nothing.
|
||||
move 'N' to s-result(s)
|
||||
move 0 to s-count(s)
|
||||
.
|
||||
statement-error.
|
||||
display statement
|
||||
move spaces to statement
|
||||
move '^ syntax error' to statement(l:)
|
||||
display statement
|
||||
move 'y' to error-found
|
||||
.
|
||||
*>=====================
|
||||
*> twentyfour semantics
|
||||
*>=====================
|
||||
test-variable.
|
||||
*> check validity
|
||||
perform varying nd from 1 by 1 until nd > 4
|
||||
or c(l) = n(nd)
|
||||
continue
|
||||
end-perform
|
||||
*> check usage
|
||||
perform varying nu from 1 by 1 until nu > 4
|
||||
or c(l) = u(nu)
|
||||
continue
|
||||
end-perform
|
||||
evaluate true
|
||||
when l > l-lim
|
||||
perform set-failure
|
||||
when c9(l) not numeric
|
||||
perform set-failure
|
||||
when nd > 4
|
||||
display 'invalid number'
|
||||
perform statement-error
|
||||
when nu > 4
|
||||
display 'number already used'
|
||||
perform statement-error
|
||||
when other
|
||||
move space to u(nu)
|
||||
perform set-success
|
||||
add 1 to oqx
|
||||
move c(l) to output-queue(oqx:1)
|
||||
end-evaluate
|
||||
.
|
||||
*> ==================================
|
||||
*> Dijkstra Shunting-Yard Algorithm
|
||||
*> to convert infix to rpn
|
||||
*> ==================================
|
||||
process-token.
|
||||
evaluate true
|
||||
when c(l) = '('
|
||||
add 1 to osx
|
||||
move c(l) to operator-stack(osx:1)
|
||||
when c(l) = ')'
|
||||
perform varying osx from osx by -1 until osx < 1
|
||||
or operator-stack(osx:1) = '('
|
||||
add 1 to oqx
|
||||
move operator-stack(osx:1) to output-queue(oqx:1)
|
||||
end-perform
|
||||
if osx < 1
|
||||
display 'parenthesis error'
|
||||
perform statement-error
|
||||
exit paragraph
|
||||
end-if
|
||||
subtract 1 from osx
|
||||
when (c(l) = '+' or '-') and (operator-stack(osx:1) = '*' or '/')
|
||||
*> lesser operator precedence
|
||||
add 1 to oqx
|
||||
move operator-stack(osx:1) to output-queue(oqx:1)
|
||||
move c(l) to operator-stack(osx:1)
|
||||
when other
|
||||
*> greater operator precedence
|
||||
add 1 to osx
|
||||
move c(l) to operator-stack(osx:1)
|
||||
end-evaluate
|
||||
.
|
||||
end-tokens.
|
||||
*> 1) copy stacked operators to the output-queue
|
||||
perform varying osx from osx by -1 until osx < 1
|
||||
or operator-stack(osx:1) = '('
|
||||
add 1 to oqx
|
||||
move operator-stack(osx:1) to output-queue(oqx:1)
|
||||
end-perform
|
||||
if osx > 0
|
||||
display 'parenthesis error'
|
||||
perform statement-error
|
||||
exit paragraph
|
||||
end-if
|
||||
*> 2) evaluate the rpn statement
|
||||
perform evaluate-rpn
|
||||
if divide-by-zero-error = 'y'
|
||||
display 'divide by zero error'
|
||||
end-if
|
||||
.
|
||||
evaluate-rpn.
|
||||
move space to divide-by-zero-error
|
||||
move 0 to rsx *> stack depth
|
||||
perform varying oqx1 from 1 by 1 until oqx1 > oqx
|
||||
if output-queue(oqx1:1) >= '1' and <= '9'
|
||||
*> push current data onto the stack
|
||||
add 1 to rsx
|
||||
move top-numerator to numerator(rsx)
|
||||
move top-denominator to denominator(rsx)
|
||||
move output-queue(oqx1:1) to top-numerator
|
||||
move 1 to top-denominator
|
||||
else
|
||||
*> apply the operation
|
||||
evaluate true
|
||||
when output-queue(oqx1:1) = '+'
|
||||
compute top-numerator = top-numerator * denominator(rsx)
|
||||
+ top-denominator * numerator(rsx)
|
||||
compute top-denominator = top-denominator * denominator(rsx)
|
||||
when output-queue(oqx1:1) = '-'
|
||||
compute top-numerator = top-denominator * numerator(rsx)
|
||||
- top-numerator * denominator(rsx)
|
||||
compute top-denominator = top-denominator * denominator(rsx)
|
||||
when output-queue(oqx1:1) = '*'
|
||||
compute top-numerator = top-numerator * numerator(rsx)
|
||||
compute top-denominator = top-denominator * denominator(rsx)
|
||||
when output-queue(oqx1:1) = '/'
|
||||
compute work-number = numerator(rsx) * top-denominator
|
||||
compute top-denominator = denominator(rsx) * top-numerator
|
||||
if top-denominator = 0
|
||||
move 'y' to divide-by-zero-error
|
||||
exit paragraph
|
||||
end-if
|
||||
move work-number to top-numerator
|
||||
end-evaluate
|
||||
*> pop the stack
|
||||
subtract 1 from rsx
|
||||
end-if
|
||||
end-perform
|
||||
.
|
||||
*>====================
|
||||
*> diagnostic displays
|
||||
*>====================
|
||||
display-start-nonterminal.
|
||||
perform varying nt from nt-lim by -1 until nt < 1
|
||||
or p-definition(p) = nonterminal-statement-number(nt)
|
||||
continue
|
||||
end-perform
|
||||
if nt > 0
|
||||
move '1' to NL-flag
|
||||
string '1' indent(1:s + s) 'at ' s space p ' start ' trim(nonterminal-statement(nt))
|
||||
into message-area perform display-message
|
||||
move nt to s-nt(s)
|
||||
end-if
|
||||
.
|
||||
display-continue-nonterminal.
|
||||
move s-nt(s) to nt
|
||||
string '1' indent(1:s + s) 'at ' s space p space p-symbol(p) ' continue ' trim(nonterminal-statement(nt)) ' with result ' s-result(s)
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-end-nonterminal.
|
||||
move s-nt(s) to nt
|
||||
move '2' to NL-flag
|
||||
string '1' indent(1:s + s) 'at ' s space p ' end ' trim(nonterminal-statement(nt)) ' with result ' s-result(s)
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-start-control.
|
||||
string '2' indent(1:s + s) 'at ' s space p ' start ' p-symbol(p) ' in ' trim(nonterminal-statement(nt))
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-repeat-control.
|
||||
string '2' indent(1:s + s) 'at ' s space p ' repeat ' p-symbol(p) ' in ' trim(nonterminal-statement(nt)) ' with result ' s-result(s)
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-end-control.
|
||||
string '2' indent(1:s + s) 'at ' s space p ' end ' p-symbol(p) ' in ' trim(nonterminal-statement(nt)) ' with result ' s-result(s)
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-take-alternate.
|
||||
string '2' indent(1:s + s) 'at ' s space p ' take alternate' ' in ' trim(nonterminal-statement(nt))
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-skip-alternate.
|
||||
string '2' indent(1:s + s) 'at ' s space p ' skip alternate' ' in ' trim(nonterminal-statement(nt))
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-terminal.
|
||||
string '1' indent(1:s + s) 'at ' s space p
|
||||
' compare ' statement(l:t-len) ' to ' terminal-symbol(t)(1:t-len)
|
||||
' in ' trim(nonterminal-statement(nt))
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-recognize-terminal.
|
||||
string '1' indent(1:s + s) 'at ' s space p ' recognize terminal: ' c(l) ' in ' trim(nonterminal-statement(nt))
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-recognize-variable.
|
||||
string '1' indent(1:s + s) 'at ' s space p ' recognize digit: ' c(l) ' in ' trim(nonterminal-statement(nt))
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-statement.
|
||||
compute p1 = p - s-start-control(s)
|
||||
string '3' indent(1:s + s) 'at ' s space p
|
||||
' statement: ' s-start-control(s) '/' p1
|
||||
space p-symbol(p) space s-result(s)
|
||||
' in ' trim(nonterminal-statement(nt))
|
||||
into message-area perform display-message
|
||||
.
|
||||
display-control-failure.
|
||||
display loop-count space indent(1:s + s) 'at' space p ' control failure' ' in ' trim(nonterminal-statement(nt))
|
||||
display loop-count space indent(1:s + s) ' ' 'p=<' p p-entry(p) '>'
|
||||
display loop-count space indent(1:s + s) ' ' 's=<' s space s-entry(s) '>'
|
||||
display loop-count space indent(1:s + s) ' ' 'l=<' l space c(l)'>'
|
||||
perform statement-error
|
||||
.
|
||||
display-message.
|
||||
if display-level = 1
|
||||
move space to NL-flag
|
||||
end-if
|
||||
evaluate true
|
||||
when loop-count > loop-lim *> loop control
|
||||
display 'display count exceeds ' loop-lim
|
||||
stop run
|
||||
when message-level <= display-level
|
||||
evaluate true
|
||||
when NL-flag = '1'
|
||||
display NL loop-count space trim(message-value)
|
||||
when NL-flag = '2'
|
||||
display loop-count space trim(message-value) NL
|
||||
when other
|
||||
display loop-count space trim(message-value)
|
||||
end-evaluate
|
||||
end-evaluate
|
||||
add 1 to loop-count
|
||||
move spaces to message-area
|
||||
move space to NL-flag
|
||||
.
|
||||
end program twentyfour.
|
||||
39
Task/24-game/Elixir/24-game.elixir
Normal file
39
Task/24-game/Elixir/24-game.elixir
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
defmodule Game24 do
|
||||
def main do
|
||||
IO.puts "24 Game"
|
||||
play
|
||||
end
|
||||
|
||||
defp play do
|
||||
IO.puts "Generating 4 digits..."
|
||||
digts = for _ <- 1..4, do: Enum.random(1..9)
|
||||
IO.puts "Your digits\t#{inspect digts, char_lists: :as_lists}"
|
||||
read_eval(digts)
|
||||
play
|
||||
end
|
||||
|
||||
defp read_eval(digits) do
|
||||
exp = IO.gets("Your expression: ") |> String.strip
|
||||
if exp in ["","q"], do: exit(:normal) # give up
|
||||
case {correct_nums(exp, digits), eval(exp)} do
|
||||
{:ok, x} when x==24 -> IO.puts "You Win!"
|
||||
{:ok, x} -> IO.puts "You Lose with #{inspect x}!"
|
||||
{err, _} -> IO.puts "The following numbers are wrong: #{inspect err, char_lists: :as_lists}"
|
||||
end
|
||||
end
|
||||
|
||||
defp correct_nums(exp, digits) do
|
||||
nums = String.replace(exp, ~r/\D/, " ") |> String.split |> Enum.map(&String.to_integer &1)
|
||||
if length(nums)==4 and (nums--digits)==[], do: :ok, else: nums
|
||||
end
|
||||
|
||||
defp eval(exp) do
|
||||
try do
|
||||
Code.eval_string(exp) |> elem(0)
|
||||
rescue
|
||||
e -> Exception.message(e)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Game24.main
|
||||
|
|
@ -29,10 +29,9 @@ processGuess digits xs = calc xs >>= check
|
|||
check x = Left (show (fromRational (x :: Rational)) ++ " is wrong")
|
||||
|
||||
-- A Reverse Polish Notation calculator with full error handling
|
||||
calc = result []
|
||||
where result [n] [] = Right n
|
||||
result _ [] = Left "Too few operators"
|
||||
result ns (x:xs) = simplify ns x >>= flip result xs
|
||||
calc xs = foldM simplify [] xs >>= \ns -> (case ns of
|
||||
[n] -> Right n
|
||||
_ -> Left "Too few operators")
|
||||
|
||||
simplify (a:b:ns) s | isOp s = Right ((fromJust $ lookup s ops) b a : ns)
|
||||
simplify _ s | isOp s = Left ("Too few values before " ++ s)
|
||||
|
|
|
|||
84
Task/24-game/Maple/24-game.maple
Normal file
84
Task/24-game/Maple/24-game.maple
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
play24 := module()
|
||||
export ModuleApply;
|
||||
local cheating;
|
||||
cheating := proc(input, digits)
|
||||
local i, j, stringDigits;
|
||||
use StringTools in
|
||||
stringDigits := Implode([seq(convert(i, string), i in digits)]);
|
||||
for i in digits do
|
||||
for j in digits do
|
||||
if Search(cat(convert(i, string), j), input) > 0 then
|
||||
return true, ": Please don't combine digits to form another number."
|
||||
end if;
|
||||
end do;
|
||||
end do;
|
||||
for i in digits do
|
||||
if CountCharacterOccurrences(input, convert(i, string)) < CountCharacterOccurrences(stringDigits, convert(i, string)) then
|
||||
return true, ": Please use all digits.";
|
||||
end if;
|
||||
end do;
|
||||
for i in digits do
|
||||
if CountCharacterOccurrences(input, convert(i, string)) > CountCharacterOccurrences(stringDigits, convert(i, string)) then
|
||||
return true, ": Please only use a digit once.";
|
||||
end if;
|
||||
end do;
|
||||
for i in input do
|
||||
try
|
||||
if type(parse(i), numeric) and not member(parse(i), digits) then
|
||||
return true, ": Please only use the digits you were given.";
|
||||
end if;
|
||||
catch:
|
||||
end try;
|
||||
end do;
|
||||
return false, "";
|
||||
end use;
|
||||
end proc:
|
||||
|
||||
ModuleApply := proc()
|
||||
local replay, digits, err, message, answer;
|
||||
randomize():
|
||||
replay := "":
|
||||
while not replay = "END" do
|
||||
if not replay = "YES" then
|
||||
digits := [seq(rand(1..9)(), i = 1..4)]:
|
||||
end if;
|
||||
err := true:
|
||||
while err do
|
||||
message := "";
|
||||
printf("Please make 24 from the digits: %a. Press enter for a new set of numbers or type END to quit\n", digits);
|
||||
answer := StringTools[UpperCase](readline());
|
||||
if not answer = "" and not answer = "END" then
|
||||
try
|
||||
if not type(parse(answer), numeric) then
|
||||
error;
|
||||
elif cheating(answer, digits)[1] then
|
||||
message := cheating(answer, digits)[2];
|
||||
error;
|
||||
end if;
|
||||
err := false;
|
||||
catch:
|
||||
printf("Invalid Input%s\n\n", message);
|
||||
end try;
|
||||
else
|
||||
err := false;
|
||||
end if;
|
||||
end do:
|
||||
if not answer = "" and not answer = "END" then
|
||||
if parse(answer) = 24 then
|
||||
printf("You win! Do you wish to play another game? (Press enter for a new set of numbers or END to quit.)\n");
|
||||
replay := StringTools[UpperCase](readline());
|
||||
else
|
||||
printf("Your expression evaluated to %a. Try again!\n", parse(answer));
|
||||
replay := "YES";
|
||||
end if;
|
||||
else
|
||||
replay := answer;
|
||||
end if;
|
||||
|
||||
printf("\n");
|
||||
end do:
|
||||
printf("GAME OVER\n");
|
||||
end proc:
|
||||
end module:
|
||||
|
||||
play24();
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
use MONKEY-SEE-NO-EVAL;
|
||||
|
||||
say "Here are your digits: ",
|
||||
constant @digits = (1..9).roll(4)».Str;
|
||||
|
||||
|
|
@ -9,15 +11,16 @@ grammar Exp24 {
|
|||
}
|
||||
|
||||
while my $exp = prompt "\n24? " {
|
||||
if Exp24.parse: $exp {
|
||||
say "You win :)";
|
||||
last;
|
||||
if try Exp24.parse: $exp {
|
||||
say "You win :)";
|
||||
last;
|
||||
} else {
|
||||
say pick 1,
|
||||
'Sorry. Try again.' xx 20,
|
||||
'Try harder.' xx 5,
|
||||
'Nope. Not even close.' xx 2,
|
||||
'Are you five or something?',
|
||||
'Come on, you can do better than that.';
|
||||
say (
|
||||
'Sorry. Try again.' xx 20,
|
||||
'Try harder.' xx 5,
|
||||
'Nope. Not even close.' xx 2,
|
||||
'Are you five or something?',
|
||||
'Come on, you can do better than that.'
|
||||
).flat.pick
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,4 +64,5 @@ def main():
|
|||
if ans == 24:
|
||||
print ("Thats right!")
|
||||
print ("Thank you and goodbye")
|
||||
main()
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
|
|
|
|||
|
|
@ -1,73 +1,68 @@
|
|||
/*REXX program which allows a user to play the game of 24 (twenty-four). */
|
||||
numeric digits 15 /*allow more leeway when computing #s. */
|
||||
parse arg yyy /*get the optional arguments from C.L. */
|
||||
yyy = space(yyy,0) /*remove extraneous blanks from YYY. */
|
||||
parse var yyy start '-' fin /*get the START and FINish (maybe). */
|
||||
fin = word(fin start,1) /*if no FINish specified, use START.*/
|
||||
opers = '+-*/' /*define the legal arithmetic operators*/
|
||||
ops = length(opers) /* ··· and the count of them (length). */
|
||||
groupSymbols = '()[]{}' /*legal grouping symbols for this game.*/
|
||||
indent = left('',30) /*used to indent display of solutions. */
|
||||
Lpar = '(' /*a string to make the output prettier.*/
|
||||
Rpar = ')' /*Ditto. [You can say that again.] */
|
||||
digs = 123456789 /*numerals (digits) that can be used. */
|
||||
show = 1 /*flag used show solutions (0 = not). */
|
||||
do j=1 for ops /*define a version for fast execution. */
|
||||
@.j=substr(opers,j,1) /*assign each operation to an array. */
|
||||
end /*j*/
|
||||
signal on syntax /*enable program to trap syntax errors.*/
|
||||
if yyy\=='' then do /*if START (or FINish), then solve 'em.*/
|
||||
sols=solve(start,fin) /*solve START ───► FINish. */
|
||||
if sols <0 then exit 13 /*Was there a problem with input? */
|
||||
if sols==0 then sols='No' /*Englishize the SOLS variable.*/
|
||||
say; say sols 'unique solution's(sols) "found for" yyy
|
||||
exit /*S [↑] does pluralizations. */
|
||||
end
|
||||
show=0 /*stop SOLVE from blabbing solutions.*/
|
||||
/*REXX program supports a human to play the game of 24 (twenty-four) with error checking*/
|
||||
numeric digits 15 /*allow more leeway when computing #s. */
|
||||
parse arg yyy /*get the optional arguments from C.L. */
|
||||
yyy = space(yyy, 0) /*remove extraneous blanks from YYY. */
|
||||
parse var yyy start '-' fin /*get the START and FINish (maybe). */
|
||||
fin = word(fin start, 1) /*if no FINish specified, use START.*/
|
||||
ops = '+-*/' ; Lops = length(0ps) /*define the legal arithmetic operators*/
|
||||
groupSym = '()[]{}' /*legal grouping symbols for this game.*/
|
||||
indent = left('', 30) /*used to indent display of solutions. */
|
||||
Lpar = '(' ; Rpar = ')' /*strings to make the output prettier.*/
|
||||
digs = 123456789 /*numerals (digits) that can be used. */
|
||||
show = 1 /*flag used show solutions (0 = not). */
|
||||
do j=1 for Lops; @.j=substr(ops,j,1) /*define a version for fast execution. */
|
||||
end /*j*/
|
||||
signal on syntax /*enable program to trap syntax errors.*/
|
||||
if yyy\=='' then do; sols=solve(start, fin) /*solve from START ───► FINish. */
|
||||
if sols <0 then exit 13 /*Was there a problem with the input? */
|
||||
if sols==0 then sols='No' /*Englishize the SOLS variable value*/
|
||||
say; say sols 'unique solution's(sols) "found for" yyy
|
||||
exit /*S [↑] does pluralizations. */
|
||||
end
|
||||
show=0 /*stop SOLVE from blabbing solutions.*/
|
||||
do forever; rrrr=random(1111, 9999)
|
||||
if pos(0, rrrr)\==0 then iterate /*if contains a zero, ignore it*/
|
||||
if solve(rrrr)\==0 then leave /*if solved, then stop looking.*/
|
||||
if pos(0, rrrr)\==0 then iterate /*if it contains a zero, then ignore it*/
|
||||
if solve(rrrr) \==0 then leave /*if solved, then we can stop looking. */
|
||||
end /*forever*/
|
||||
show=1 /*enable SOLVE to display solutions. */
|
||||
rrrr=sort(rrrr) /*sort four digits (for consistency). */
|
||||
show=1 /*enable SOLVE to display solutions. */
|
||||
rrrr=sort(rrrr); Lrrrr=length(rrrr) /*sort four digits (for consistency). */
|
||||
$.=0
|
||||
do j=1 for length(rrrr) /*digit count for each digit in RRRR. */
|
||||
_=substr(rrrr, j, 1) /*pick off one of the digits in RRRR. */
|
||||
$._=countDigs(rrrr, _) /*define the count for this digit. */
|
||||
end /*j*/ /* [↑] counts duplicates twice, no harm*/
|
||||
do j=1 for Lrrrr; _=substr(rrrr,j,1) /*digit count for each digit in RRRR. */
|
||||
$._= countDigs(rrrr, _) /*define the count for this digit. */
|
||||
end /*j*/ /* [↑] counts duplicates twice, no harm*/
|
||||
|
||||
prompt= 'Using the digits' rrrr", enter an expression that equals 24 (or QUIT):"
|
||||
/* [↓] ITERATE needs a variable name.*/
|
||||
do prompter=0; say; say prompt /*display blank line and the prompt (P)*/
|
||||
pull y; y=space(y,0) /*get Y from CL, then remove all blanks*/
|
||||
if abbrev('QUIT',y,1) then exit /*Does the user want to quit this game?*/
|
||||
_v=verify(y, digs || opers || groupSymbols); a=substr(y, max(1,_v), 1)
|
||||
if _v\==0 then do; call ger 'invalid character:' a; iterate; end
|
||||
if pos('**',y) then do; call ger 'invalid ** operator'; iterate; end
|
||||
if pos('//',y) then do; call ger 'invalid // operator'; iterate; end
|
||||
yL=length(y)
|
||||
if y=='' then do; call validate y; iterate; end
|
||||
__ = copies('─', 9) /*used for output highlighting. */
|
||||
prompt= 'Using the digits ' rrrr", enter an expression that equals 24 (or QUIT):"
|
||||
/* [↓] ITERATE needs a variable name.*/
|
||||
do prompter=0; say; say __ prompt /*display blank line and the prompt (P)*/
|
||||
pull y; y=space(y, 0) /*get Y from CL, then remove all blanks*/
|
||||
if abbrev('QUIT', y, 1) then exit 0 /*Does the user want to quit this game?*/
|
||||
_v=verify(y, digs || ops || groupSym); a=substr(y, max(1,_v), 1)
|
||||
if _v\==0 then do; call ger "invalid character:" a; iterate; end
|
||||
if pos('**', y) then do; call ger "invalid ** operator"; iterate; end
|
||||
if pos('//', y) then do; call ger "invalid // operator"; iterate; end
|
||||
Ly=length(y)
|
||||
if y=='' then do; call validate y; iterate; end
|
||||
|
||||
do j=1 for yL-1; if \datatype(substr(y, j ,1), 'W') then iterate
|
||||
if \datatype(substr(y, j+1,1), 'W') then iterate
|
||||
do j=1 for Ly-1; if \datatype(substr(y, j , 1), 'W') then iterate
|
||||
if \datatype(substr(y, j+1, 1), 'W') then iterate
|
||||
call ger 'invalid use of "digit abuttal".'
|
||||
iterate prompter
|
||||
end /*j*/
|
||||
|
||||
yd=countDigs(y, digs) /*count of the digits 1──►9 (123456789)*/
|
||||
if yd<4 then do; call ger 'not enough digits entered.'; iterate prompter; end
|
||||
if yd>4 then do; call ger 'too many digits entered.' ; iterate prompter; end
|
||||
yd=countDigs(y, digs) /*count of the digits 1──►9 (123456789)*/
|
||||
if yd<4 then do; call ger 'not enough digits entered.'; iterate /*prompter*/; end
|
||||
if yd>4 then do; call ger 'too many digits entered.' ; iterate /*prompter*/; end
|
||||
|
||||
do j=1 for 9; if $.j==0 then iterate
|
||||
_d=countDigs(y, j); if $.j==_d then iterate
|
||||
if _d<$.j then call ger 'not enough' j "digits, must be" $.j
|
||||
else call ger 'too many' j "digits, must be" $.j
|
||||
do j=1 for 9; if $.j==0 then iterate
|
||||
_d=countDigs(y, j); if $.j==_d then iterate
|
||||
if _d<$.j then call ger 'not enough' j "digits, must be" $.j
|
||||
else call ger 'too many' j "digits, must be" $.j
|
||||
iterate prompter
|
||||
end /*j*/
|
||||
|
||||
y=translate(y, '()()', "[]{}")
|
||||
interpret 'ans=' y; ans=ans/1; if ans==24 then leave prompter
|
||||
say 'incorrect, ' y'='ans
|
||||
interpret 'ans=' translate(y, '()()', "[]{}"); ans=ans/1
|
||||
if ans==24 then leave prompter; say 'incorrect, ' y"="ans
|
||||
end /*prompter*/
|
||||
|
||||
say; say center('┌─────────────────────┐', 79)
|
||||
|
|
@ -75,84 +70,65 @@ say; say center('┌────────────────
|
|||
say center('│ congratulations ! │', 79)
|
||||
say center('│ │', 79)
|
||||
say center('└─────────────────────┘', 79)
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────one─liner subroutines─────────────────────*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
countDigs: arg ?; return length(?) - length(space(translate(?, , arg(2)), 0))
|
||||
div: if arg(1)=0 then return 7e9; return arg(1) /*if ÷ by 0, fudge result*/
|
||||
ger: say; say '***error!*** for argument:' y; say arg(1); say;errCode=1;return 0
|
||||
s: if arg(1)==1 then return ''; return 's' /*simple pluralizer.*/
|
||||
syntax: call ger 'illegal syntax in' y; exit
|
||||
/*──────────────────────────────────SOLVE subroutine──────────────────────────*/
|
||||
solve: parse arg ssss, ffff /*parse the argument passed to SOLVE. */
|
||||
if ffff=='' then ffff=ssss /*create a FFFF if necessary. */
|
||||
if \validate(ssss) then return -1 /*validate the SSSS field. */
|
||||
if \validate(ffff) then return -1 /* " " FFFF " */
|
||||
#=0 /*number of found solutions (so far). */
|
||||
!.=0 /*a method to hold unique expressions. */
|
||||
/*alternative: indent=copies(' ',30) */
|
||||
div: if arg(1)=0 then return 7e9; return arg(1) /*÷ by 0? Fudge result*/
|
||||
ger: say; say __ '***error*** for expression:' y; say __ arg(1); say; OK=0; return 0
|
||||
s: if arg(1)==1 then return ''; return "s" /*a simple pluralizer.*/
|
||||
syntax: call ger 'illegal syntax in' y; exit
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
solve: parse arg ssss, ffff /*parse the argument passed to SOLVE. */
|
||||
if ffff=='' then ffff=ssss /*create a FFFF if necessary. */
|
||||
if \validate(ssss) then return -1 /*validate the SSSS field. */
|
||||
if \validate(ffff) then return -1 /* " " FFFF " */
|
||||
#=0 /*number of found solutions (so far). */
|
||||
!.=0 /*a method to hold unique expressions. */
|
||||
/*alternative: indent=copies(' ',30) */
|
||||
do g=ssss to ffff /*process a (possible) range of values.*/
|
||||
if pos(0, g)\==0 then iterate /*ignore values with zero in them. */
|
||||
|
||||
do g=ssss to ffff /*process a (possible) range of values.*/
|
||||
if pos(0, g)\==0 then iterate /*ignore values with zero in them. */
|
||||
do j=1 for 4; g.j=substr(g, j, 1) /*define a version for fast execution. */
|
||||
end /*j*/
|
||||
|
||||
do j=1 for 4 /*define a version for fast execution. */
|
||||
g.j=substr(g, j, 1) /*extract each digit of G into array.*/
|
||||
end /*j*/
|
||||
do i =1 for Lops /*insert an operator after 1st number. */
|
||||
do j =1 for Lops /* " " " " 2nd " */
|
||||
do k =1 for Lops /* " " " " 3rd " */
|
||||
do m=0 to 3; L.= /*assume no left parenthesis (so far).*/
|
||||
do n=m+1 to 4; L.m=Lpar; R.= /*match left paren with a right paren. */
|
||||
if m==1 & n==2 then L.= /*special case of : (n) + ··· */
|
||||
else if m\==0 then R.n=Rpar /*no (, no )*/
|
||||
e= L.1 g.1 @.i L.2 g.2 @.j L.3 g.3 R.3 @.k g.4 R.4
|
||||
e=space(e, 0) /*remove all blanks from the expression*/
|
||||
yyyE=e /*keep old the version for the display.*/
|
||||
/* [↓] change /(yyy) ═══► /div(yyy) */
|
||||
if pos('/(', e)\==0 then e=changestr( "/(", e, '/div(' )
|
||||
if !.e then iterate /*was this expression already used? */
|
||||
!.e=1 /*mark this expression as being used. */
|
||||
interpret 'x=' e /*have REXX do all the heavy lifting */
|
||||
if x\=24 then iterate /*Is the result incorrect? Try again. */
|
||||
#=#+1 /*bump number of found solutions. */
|
||||
if show then say indent 'a solution:' translate(yyyE, '][', ")(")
|
||||
end /*n*/ /* [↑] display a (single) solution. */
|
||||
end /*m*/
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
end /*i*/
|
||||
end /*g*/
|
||||
|
||||
do i =1 for ops /*insert an operator after 1st number. */
|
||||
do j =1 for ops /*insert an operator after 2nd number. */
|
||||
do k =1 for ops /*insert an operator after 2nd number. */
|
||||
do m=0 to 3; L.= /*assume no left parenthesis so far. */
|
||||
do n=m+1 to 4 /*match left paren with a right paren. */
|
||||
L.m=Lpar /*define a left paren, m=0 means ignore*/
|
||||
R.= /*un-define all right parenthesis. */
|
||||
if m==1 & n==2 then L.= /*special case of : (n) + ··· */
|
||||
else if m\==0 then R.n=Rpar /*no (, no )*/
|
||||
e = L.1 g.1 @.i L.2 g.2 @.j L.3 g.3 R.3 @.k g.4 R.4
|
||||
e=space(e, 0) /*remove all blanks from the expression*/
|
||||
/* [↓] change expression: */
|
||||
/* /(yyy) ═══► /div(yyy) */
|
||||
/*Enables to check for division by zero*/
|
||||
yyyE=e /*keep old the version for the display.*/
|
||||
if pos('/(', e)\==0 then e=changestr( '/(', e, "/div(" )
|
||||
/* [↓] INTERPRET stresses REXX's groin,*/
|
||||
/* so try to avoid repeated lifting.*/
|
||||
if !.e then iterate /*was this expression already used? */
|
||||
!.e=1 /*mark this expression as being used. */
|
||||
interpret 'x=' e /*have REXX do all the heavy lifting */
|
||||
x=x/1 /*remove any trailing decimal point. */
|
||||
if x\==24 then iterate /*Is the result incorrect? Try again. */
|
||||
#=#+1 /*bump number of found solutions. */
|
||||
_=translate(yyyE, '][', ")(") /*display [], not (). */
|
||||
if show then say indent 'a solution:' _
|
||||
end /*n*/ /* [↑] show a solution.*/
|
||||
end /*m*/
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
end /*i*/
|
||||
end /*g*/
|
||||
|
||||
return #
|
||||
/*──────────────────────────────────SORT subroutine───────────────────────────*/
|
||||
sort: procedure; arg nnnn; L=length(nnnn)
|
||||
|
||||
do i=1 for L /*build an array of digits from NNNN. */
|
||||
s.i=substr(nnnn, i, 1) /*this enables SORT to sort an array. */
|
||||
end /*i*/
|
||||
|
||||
do j=1 for L; _=s.j
|
||||
do k=j+1 to L
|
||||
if s.k<_ then parse value s.j s.k with s.k s.j
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
return s.1 || s.2 || s.3 || s.4
|
||||
/*──────────────────────────────────VALIDATE subroutine───────────────────────*/
|
||||
validate: parse arg y; errCode=0; _v=verify(y,digs)
|
||||
select
|
||||
when y=='' then call ger 'no digits entered.'
|
||||
when length(y)<4 then call ger 'not enough digits entered, must be four.'
|
||||
when length(y)>4 then call ger 'too many digits entered, must be four.'
|
||||
when pos(0,y)\==0 then call ger "can't use the digit 0 (zero)."
|
||||
when _v\==0 then call ger 'illegal character: ' substr(y,_v,1)
|
||||
otherwise nop
|
||||
end /*select*/
|
||||
return \errCode
|
||||
return #
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
sort: procedure; parse arg #; L=length(#); !.= /*this is a modified bin sort.*/
|
||||
do d=1 for L; _=substr(#, d, 1); !.d=!.d || _; end /*d*/
|
||||
return space(!.0 !.1 !.2 !.3 !.4 !.5 !.6 !.7 !.8 !.9, 0) /*reconstitute the #.*/
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
validate: parse arg y; OK=1; _v=verify(y,digs); DE='digits entered, there must be four.'
|
||||
select
|
||||
when y=='' then call ger "no" DE
|
||||
when length(y)<4 then call ger "not enough" DE
|
||||
when length(y)>4 then call ger "too many" DE
|
||||
when pos(0,y)\==0 then call ger "can't use the digit 0 (zero)."
|
||||
when _v\==0 then call ger "illegal character: " substr(y, _v, 1)
|
||||
otherwise nop
|
||||
end /*select*/
|
||||
return OK
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
def validate(guess, nums)
|
||||
name, error =
|
||||
{
|
||||
invalid_character: ->(str){ !str.scan(%r{[^\d\s()+*/-]}).empty? },
|
||||
wrong_number: ->(str){ str.scan(/\d/).map(&:to_i).sort != nums.sort },
|
||||
multi_digit_number: ->(str){ str.match(/\d\d/) }
|
||||
}
|
||||
.find {|name, validator| validator[guess] }
|
||||
|
||||
error ? puts("Invalid input of a(n) #{name.to_s.tr('_',' ')}!") : true
|
||||
end
|
||||
|
||||
class Guess < String
|
||||
def self.play
|
||||
nums = Array.new(4){rand(1..9)}
|
||||
loop do
|
||||
result = get(nums).evaluate!
|
||||
break if result == 24.0
|
||||
puts "Try again! That gives #{result}!"
|
||||
end
|
||||
puts "You win!"
|
||||
end
|
||||
|
||||
def self.get(nums)
|
||||
loop do
|
||||
print "\nEnter a guess using #{nums}: "
|
||||
|
|
@ -19,24 +17,24 @@ class Guess < String
|
|||
end
|
||||
end
|
||||
|
||||
def self.validate(guess, nums)
|
||||
name, error =
|
||||
{
|
||||
invalid_character: ->(str){ !str.scan(%r{[^\d\s()+*/-]}).empty? },
|
||||
wrong_number: ->(str){ str.scan(/\d/).map(&:to_i).sort != nums.sort },
|
||||
multi_digit_number: ->(str){ str.match(/\d\d/) }
|
||||
}
|
||||
.find {|name, validator| validator[guess] }
|
||||
|
||||
error ? puts("Invalid input of a(n) #{name.to_s.tr('_',' ')}!") : true
|
||||
end
|
||||
|
||||
def evaluate!
|
||||
as_rat = gsub(/(\d)/, 'Rational(\1,1)')
|
||||
begin
|
||||
eval "(#{as_rat}).to_f"
|
||||
rescue SyntaxError
|
||||
"[syntax error]"
|
||||
end
|
||||
as_rat = gsub(/(\d)/, '\1r') # r : Rational suffix
|
||||
eval "(#{as_rat}).to_f"
|
||||
rescue SyntaxError
|
||||
"[syntax error]"
|
||||
end
|
||||
end
|
||||
|
||||
def play
|
||||
nums = Array.new(4){rand(1..9)}
|
||||
loop do
|
||||
result = Guess.get(nums).evaluate!
|
||||
break if result == 24.0
|
||||
puts "Try again! That gives #{result}!"
|
||||
end
|
||||
puts "You win!"
|
||||
end
|
||||
|
||||
play
|
||||
Guess.play
|
||||
|
|
|
|||
102
Task/24-game/Rust/24-game.rust
Normal file
102
Task/24-game/Rust/24-game.rust
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
use std::io::{self,BufRead};
|
||||
extern crate rand;
|
||||
use rand::Rng;
|
||||
|
||||
fn op_type(x: char) -> i32{
|
||||
match x {
|
||||
'-' | '+' => return 1,
|
||||
'/' | '*' => return 2,
|
||||
'(' | ')' => return -1,
|
||||
_ => return 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_rpn(input: &mut String){
|
||||
|
||||
let mut rpn_string : String = String::new();
|
||||
let mut rpn_stack : String = String::new();
|
||||
let mut last_token = '#';
|
||||
for token in input.chars(){
|
||||
if token.is_digit(10) {
|
||||
rpn_string.push(token);
|
||||
}
|
||||
else if op_type(token) == 0 {
|
||||
continue;
|
||||
}
|
||||
else if op_type(token) > op_type(last_token) || token == '(' {
|
||||
rpn_stack.push(token);
|
||||
last_token=token;
|
||||
}
|
||||
else {
|
||||
while let Some(top) = rpn_stack.pop() {
|
||||
if top=='(' {
|
||||
break;
|
||||
}
|
||||
rpn_string.push(top);
|
||||
}
|
||||
if token != ')'{
|
||||
rpn_stack.push(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
while let Some(top) = rpn_stack.pop() {
|
||||
rpn_string.push(top);
|
||||
}
|
||||
|
||||
println!("you formula results in {}", rpn_string);
|
||||
|
||||
*input=rpn_string;
|
||||
}
|
||||
|
||||
fn calculate(input: &String, list : &mut [u32;4]) -> f32{
|
||||
let mut stack : Vec<f32> = Vec::new();
|
||||
let mut accumulator : f32 = 0.0;
|
||||
|
||||
for token in input.chars(){
|
||||
if token.is_digit(10) {
|
||||
let test = token.to_digit(10).unwrap() as u32;
|
||||
match list.iter().position(|&x| x == test){
|
||||
Some(idx) => list[idx]=10 ,
|
||||
_ => println!(" invalid digit: {} ",test),
|
||||
}
|
||||
stack.push(accumulator);
|
||||
accumulator = test as f32;
|
||||
}else{
|
||||
let a = stack.pop().unwrap();
|
||||
accumulator = match token {
|
||||
'-' => a-accumulator,
|
||||
'+' => a+accumulator,
|
||||
'/' => a/accumulator,
|
||||
'*' => a*accumulator,
|
||||
_ => {accumulator},//NOP
|
||||
};
|
||||
}
|
||||
}
|
||||
println!("you formula results in {}",accumulator);
|
||||
accumulator
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut list :[u32;4]=[rng.gen::<u32>()%10,rng.gen::<u32>()%10,rng.gen::<u32>()%10,rng.gen::<u32>()%10];
|
||||
|
||||
println!("form 24 with using + - / * {:?}",list);
|
||||
//get user input
|
||||
let mut input = String::new();
|
||||
io::stdin().read_line(&mut input).unwrap();
|
||||
//convert to rpn
|
||||
to_rpn(&mut input);
|
||||
let result = calculate(&input, &mut list);
|
||||
|
||||
if list.iter().any(|&list| list !=10){
|
||||
println!("and you used all numbers");
|
||||
match result {
|
||||
24.0 => println!("you won"),
|
||||
_ => println!("but your formulla doesn't result in 24"),
|
||||
}
|
||||
}else{
|
||||
println!("you didn't use all the numbers");
|
||||
}
|
||||
|
||||
}
|
||||
52
Task/24-game/ZX-Spectrum-Basic/24-game.zx
Normal file
52
Task/24-game/ZX-Spectrum-Basic/24-game.zx
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
10 LET n$=""
|
||||
20 RANDOMIZE
|
||||
30 FOR i=1 TO 4
|
||||
40 LET n$=n$+STR$ (INT (RND*9)+1)
|
||||
50 NEXT i
|
||||
60 LET i$="": LET f$="": LET p$=""
|
||||
70 CLS
|
||||
80 PRINT "24 game"
|
||||
90 PRINT "Allowed characters:"
|
||||
100 LET i$=n$+"+-*/()"
|
||||
110 PRINT AT 4,0;
|
||||
120 FOR i=1 TO 10
|
||||
130 PRINT i$(i);" ";
|
||||
140 NEXT i
|
||||
150 PRINT "(0 to end)"
|
||||
160 INPUT "Enter the formula";f$
|
||||
170 IF f$="0" THEN STOP
|
||||
180 PRINT AT 6,0;f$;" = ";
|
||||
190 FOR i=1 TO LEN f$
|
||||
200 LET c$=f$(i)
|
||||
210 IF c$=" " THEN LET f$(i)="": GO TO 250
|
||||
220 IF c$="+" OR c$="-" OR c$="*" OR c$="/" THEN LET p$=p$+"o": GO TO 250
|
||||
230 IF c$="(" OR c$=")" THEN LET p$=p$+c$: GO TO 250
|
||||
240 LET p$=p$+"n"
|
||||
250 NEXT i
|
||||
260 RESTORE
|
||||
270 FOR i=1 TO 11
|
||||
280 READ t$
|
||||
290 IF t$=p$ THEN LET i=11
|
||||
300 NEXT i
|
||||
310 IF t$<>p$ THEN PRINT INVERSE 1;"Bad construction!": BEEP 1,.1: PAUSE 0: GO TO 60
|
||||
320 FOR i=1 TO LEN f$
|
||||
330 FOR j=1 TO 10
|
||||
340 IF (f$(i)=i$(j)) AND f$(i)>"0" AND f$(i)<="9" THEN LET i$(j)=" "
|
||||
350 NEXT j
|
||||
360 NEXT i
|
||||
370 IF i$( TO 4)<>" " THEN PRINT FLASH 1;"Invalid arguments!": BEEP 1,.01: PAUSE 0: GO TO 60
|
||||
380 LET r=VAL f$
|
||||
390 PRINT r;" ";
|
||||
400 IF r<>24 THEN PRINT FLASH 1;"Wrong!": BEEP 1,1: PAUSE 0: GO TO 60
|
||||
410 PRINT FLASH 1;"Correct!": PAUSE 0: GO TO 10
|
||||
420 DATA "nononon"
|
||||
430 DATA "(non)onon"
|
||||
440 DATA "nono(non)"
|
||||
450 DATA "no(no(non))"
|
||||
460 DATA "((non)on)on"
|
||||
470 DATA "no(non)on"
|
||||
480 DATA "(non)o(non)"
|
||||
485 DATA "no((non)on)"
|
||||
490 DATA "(nonon)on"
|
||||
495 DATA "(no(non))on"
|
||||
500 DATA "no(nonon)"
|
||||
Loading…
Add table
Add a link
Reference in a new issue