-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharithmetic.js
106 lines (105 loc) · 3.66 KB
/
arithmetic.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// A slight modification of a JavaScript interpreter (https://esolangs.org/wiki/Talk:Arithmetic) by the esolang user PythonshellDebugwindow, which is put in the public domain.
function arithmetic(program,input)
{
const lines = program.split("\n");
let output = "";
let state = 0, currentExam = 0;
let currentProblem, currentChoice, pointsEarned;
let correctAnswer, problemPoints, answerDict;
let m; //Holds the result of RegExp matches
let currentLineNumber = 0;
for(const line of lines)
{
++currentLineNumber;
//Skip empty lines
if(line === "")
{
continue;
}
//State 0 (begin exam)
else if(state === 0)
{
if(line === `==Begin Exam ${currentExam + 1}==`)
{
++currentExam;
state = 1;
currentProblem = 1;
pointsEarned = 0;
continue;
}
}
//State 1 (begin problem, end exam)
else if(state === 1)
{
//Match a problem declaration, e.g. 1. 2+3=? (100 points)
if((m = line.match(/^([0-9]+). ([0-9]+)\+([0-9]+)=\? \(([0-9]+) points\)$/)))
{
//Must be positive integers
if((+m[2]) > 0 && (+m[3]) > 0)
{
//Check if the problem number is correct
if((+m[1]) === currentProblem)
{
++currentProblem;
answerDict = {};
currentChoice = 0;
correctAnswer = (+m[2]) + (+m[3]);
problemPoints = m[4];
++state;
continue;
}
}
}
else if(line === `==End Exam ${currentExam}==`)
{
state = 0;
output += String.fromCharCode(pointsEarned % 256);
continue;
}
}
//State 2 (problem choices)
else if(state === 2)
{
//Match the current choice letter (A, B, etc.) followed by a period, space, then number
if(m = line.match(new RegExp("^(" + String.fromCharCode(currentChoice + 65) + ")\. ([0-9]+)$")))
{
//Problems can have up to 26 choices
if(currentChoice < 26)
{
++currentChoice;
//Must be a positive integer
if(+m[2] > 0)
{
//Check for duplicate correct answers
if(!(Object.values(answerDict).indexOf(m[2]) > -1 && (+m[2]) === correctAnswer))
{
answerDict[m[1]] = m[2];
continue;
}
}
}
}
else if((m = line.match(/^Answer: ([A-Z])$/)))
{
//Check whether the chosen answer is a valid choice
if(m[1].charCodeAt(0) - 65 < currentChoice)
{
//Check whether the chosen answer is correct
if((+answerDict[m[1]]) === correctAnswer)
{
pointsEarned += (problemPoints % 256);
}
--state;
continue;
}
}
}
throw new Error("Invalid syntax on line " + currentLineNumber);
}
if(state !== 0)
{
//The last line was not the end of an exam
throw new Error("Unexpected end of input");
}
return output;
}