Merge: nitunit: Use markdown2
[nit.git] / examples / rosettacode / 24_game.nit
1 #!/usr/bin/env nit
2 #
3 # This file is part of NIT ( http://www.nitlanguage.org ).
4 # This program is public domain
5
6 # Task: 24 game
7 # SEE: <http://rosettacode.org/wiki/24_game>
8
9 redef class Char
10 fun is_op: Bool do return "-+/*".has(self)
11 end
12
13 # Get `numbers` and `operands` from string `operation` collect with `gets` in `main` function
14 # Fill `numbers` and `operands` array with previous extraction
15 fun exportation(operation: String, numbers: Array[Int], operands: Array[Char]) do
16 var previous_char: nullable Char = null
17 var number: nullable Int = null
18 var negative = false
19
20 for i in operation.length.times do
21 var current_char = operation[i]
22 var current_int = current_char.to_i
23
24 if (previous_char == null or previous_char.is_op) and current_char == '-' then
25 negative = true
26 continue
27 end
28
29 if current_char.is_digit then
30 if number == null then
31 number = current_int
32 else
33 number = number * 10 + current_int
34 end
35 end
36
37 if negative and (current_char.is_op or i == operation.length - 1) then
38 number = number - number * 2
39 negative = false
40 end
41
42 if (current_char.is_op or i == operation.length - 1) and number != null then
43 numbers.add(number)
44 number = null
45 end
46
47 if not negative and current_char.is_op then
48 operands.add(current_char)
49 end
50 previous_char = current_char
51 end
52 # Update `numbers` and `operands` array in main function with pointer
53 end
54
55 # Create random numbers between 1 to 9
56 fun random: Array[Int] do
57 return [for i in 4.times do 1 + 9.rand]
58 end
59
60 # Make mathematical operation with `numbers` and `operands` and add the operation result into `random_numbers`
61 fun calculation(random_numbers, numbers: Array[Int], operands: Array[Char]) do
62 var number = 0
63 var temp_numbers = numbers.clone
64
65 while temp_numbers.length > 1 do
66 var operand = operands.shift
67 var a = temp_numbers.shift
68 var b = temp_numbers.shift
69
70 if operand == '+' then number = a + b
71 if operand == '-' then number = a - b
72 if operand == '*' then number = a * b
73 if operand == '/' then number = a / b
74
75 temp_numbers.unshift(number)
76 end
77 if number != 0 then random_numbers.add(number)
78 end
79
80 # Check if used `numbers` exist in the `random_numbers` created
81 fun numbers_exists(random_numbers, numbers: Array[Int]): Bool do
82 for number in numbers do
83 if not random_numbers.count(number) >= numbers.count(number) then return false
84 end
85 return true
86 end
87
88 # Remove `numbers` when they are used
89 fun remove_numbers(random_numbers, numbers: Array[Int]) do
90 for number in numbers do random_numbers.remove(number)
91 end
92
93 # Check if the mathematical `operation` is valid
94 fun check(operation: String): Bool do
95 var previous_char: nullable Char = null
96 var next_char: nullable Char = null
97 var next_1_char: nullable Char = null
98
99 for i in operation.length.times do
100 var current_char = operation[i]
101
102 if i + 1 < operation.length then
103 next_char = operation[i + 1]
104 if i + 2 < operation.length then
105 next_1_char = operation[i + 2]
106 else
107 next_1_char = null
108 end
109 else
110 next_char = null
111 end
112
113 if not current_char.is_op and not current_char.is_digit then return false
114 if next_char == null and current_char.is_op then return false
115
116 if previous_char == null then
117 if next_char == null or next_1_char == null then return false
118 if current_char == '-' and not next_char.is_digit then return false
119 if current_char != '-' and not current_char.is_digit then return false
120 else
121 if next_char != null then
122 if previous_char.is_digit and current_char.is_op and
123 not (next_char == '-' and next_1_char != null and
124 next_1_char.is_digit or next_char.is_digit) then
125 return false
126 end
127 end
128 end
129 previous_char = current_char
130 end
131 return true
132 end
133
134 var random_numbers = new Array[Int]
135 var operation = ""
136
137 random_numbers = random
138 while not random_numbers.has(24) and random_numbers.length > 1 do
139 var numbers = new Array[Int]
140 var operands = new Array[Char]
141
142 print "numbers: " + random_numbers.join(", ")
143 operation = gets
144 if check(operation) then
145 exportation(operation, numbers, operands)
146 if numbers_exists(random_numbers, numbers) then
147 calculation(random_numbers, numbers, operands)
148 remove_numbers(random_numbers, numbers)
149 else
150 print "NUMBERS ERROR!"
151 end
152 else
153 print "STRING ERROR!"
154 end
155 end
156
157 if random_numbers.has(24) then print "CONGRATULATIONS" else print "YOU LOSE"