dkl9 commited on 2025-209 17:15:36
Showing 1 changed files, with 50 additions and 32 deletions.
| ... | ... |
@@ -4,7 +4,7 @@ |
| 4 | 4 |
<style> |
| 5 | 5 |
body { font-family: sans-serif; }
|
| 6 | 6 |
#plot { border: 1px solid #000; }
|
| 7 |
- #grid { border-collapse: collapse; margin-top: 10px; }
|
|
| 7 |
+ #grid { border-collapse: separate; border-spacing: 5px 10px; margin-top: 10px; }
|
|
| 8 | 8 |
#grid td { width: 40px; height: 40px; border: 1px solid #ccc; text-align: center; vertical-align: middle; font-weight: bold; }
|
| 9 | 9 |
.grey { background: #787c7e; color: #fff; }
|
| 10 | 10 |
.yellow { background: #c9b458; color: #fff; }
|
| ... | ... |
@@ -32,8 +32,51 @@ |
| 32 | 32 |
unary: ["^2", "^3", "sin", "exp", "ln"], |
| 33 | 33 |
binary: ["+", "-", "*", "/"] |
| 34 | 34 |
}; |
| 35 |
- const target = ["x", "sin", "1", "1", "+", "*"]; // 2*sin(x) |
|
| 36 |
- const tl = target.length; |
|
| 35 |
+ const allTokens = [...allowed.terminals, ...allowed.unary, ...allowed.binary]; |
|
| 36 |
+ const tl = 6; |
|
| 37 |
+ |
|
| 38 |
+ function evalPostfix(tokens, x) {
|
|
| 39 |
+ const s = []; |
|
| 40 |
+ for (const t of tokens) {
|
|
| 41 |
+ if (t === "x") s.push(x); |
|
| 42 |
+ else if (t === "1") s.push(1); |
|
| 43 |
+ else if (t === "2") s.push(2); |
|
| 44 |
+ else if (allowed.unary.includes(t)) {
|
|
| 45 |
+ if (s.length < 1) throw 0; |
|
| 46 |
+ const v = s.pop(); |
|
| 47 |
+ if (t === "^2") s.push(v ** 2); |
|
| 48 |
+ if (t === "^3") s.push(v ** 3); |
|
| 49 |
+ if (t === "sin") s.push(Math.sin(v)); |
|
| 50 |
+ if (t === "exp") s.push(Math.exp(v)); |
|
| 51 |
+ if (t === "ln") s.push(Math.log(v)); |
|
| 52 |
+ } else if (allowed.binary.includes(t)) {
|
|
| 53 |
+ if (s.length < 2) throw 0; |
|
| 54 |
+ const b = s.pop(), a = s.pop(); |
|
| 55 |
+ if (t === "+") s.push(a + b); |
|
| 56 |
+ if (t === "-") s.push(a - b); |
|
| 57 |
+ if (t === "*") s.push(a * b); |
|
| 58 |
+ if (t === "/") s.push(a / b); |
|
| 59 |
+ } else throw 0; |
|
| 60 |
+ } |
|
| 61 |
+ if (s.length !== 1) throw 0; |
|
| 62 |
+ return s[0]; |
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ function generateTarget() {
|
|
| 66 |
+ while (true) {
|
|
| 67 |
+ const cand = []; |
|
| 68 |
+ for (let i = 0; i < tl; i++) {
|
|
| 69 |
+ cand.push(allTokens[Math.floor(Math.random() * allTokens.length)]); |
|
| 70 |
+ } |
|
| 71 |
+ try {
|
|
| 72 |
+ // test on a sample of x values to ensure valid |
|
| 73 |
+ for (let xTest of [0, 1, -1]) evalPostfix(cand, xTest); |
|
| 74 |
+ return cand; |
|
| 75 |
+ } catch (e) { continue; }
|
|
| 76 |
+ } |
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ const target = generateTarget(); |
|
| 37 | 80 |
const maxGuesses = 6; |
| 38 | 81 |
let currentRow = 0; |
| 39 | 82 |
const width = 400, height = 400; |
| ... | ... |
@@ -57,13 +101,11 @@ |
| 57 | 101 |
const x0 = mapX(0); |
| 58 | 102 |
ctx.moveTo(x0, 0); |
| 59 | 103 |
ctx.lineTo(x0, height); |
| 60 |
- // ticks at (1,0) and (-1,0) |
|
| 61 | 104 |
[1, -1].forEach(val => {
|
| 62 | 105 |
const px = mapX(val); |
| 63 | 106 |
ctx.moveTo(px, y0 - 5); |
| 64 | 107 |
ctx.lineTo(px, y0 + 5); |
| 65 | 108 |
}); |
| 66 |
- // ticks at (0,1) and (0,-1) |
|
| 67 | 109 |
[1, -1].forEach(val => {
|
| 68 | 110 |
const py = mapY(val); |
| 69 | 111 |
ctx.moveTo(x0 - 5, py); |
| ... | ... |
@@ -90,9 +134,10 @@ |
| 90 | 134 |
drawCurve(ys, color); |
| 91 | 135 |
}); |
| 92 | 136 |
} |
| 93 |
- // initial draw |
|
| 137 |
+ |
|
| 94 | 138 |
drawAxes(); |
| 95 | 139 |
drawCurve(targetYs, "green"); |
| 140 |
+ |
|
| 96 | 141 |
const grid = document.getElementById("grid");
|
| 97 | 142 |
for (let i = 0; i < maxGuesses; i++) {
|
| 98 | 143 |
const tr = document.createElement("tr");
|
| ... | ... |
@@ -110,7 +156,7 @@ |
| 110 | 156 |
return; |
| 111 | 157 |
} |
| 112 | 158 |
for (const t of inp) {
|
| 113 |
- if (![...allowed.terminals, ...allowed.unary, ...allowed.binary].includes(t)) {
|
|
| 159 |
+ if (!allTokens.includes(t)) {
|
|
| 114 | 160 |
document.getElementById("message").textContent = "Invalid token: " + t;
|
| 115 | 161 |
return; |
| 116 | 162 |
} |
| ... | ... |
@@ -137,31 +183,7 @@ |
| 137 | 183 |
document.getElementById("submitBtn").disabled = true;
|
| 138 | 184 |
} |
| 139 | 185 |
}; |
| 140 |
- function evalPostfix(tokens, x) {
|
|
| 141 |
- const s = []; |
|
| 142 |
- for (const t of tokens) {
|
|
| 143 |
- if (t === "x") s.push(x); |
|
| 144 |
- else if (t === "1") s.push(1); |
|
| 145 |
- else if (t === "2") s.push(2); |
|
| 146 |
- else if (allowed.unary.includes(t)) {
|
|
| 147 |
- const v = s.pop(); |
|
| 148 |
- if (t === "^2") s.push(v ** 2); |
|
| 149 |
- if (t === "^3") s.push(v ** 3); |
|
| 150 |
- if (t === "sin") s.push(Math.sin(v)); |
|
| 151 |
- if (t === "exp") s.push(Math.exp(v)); |
|
| 152 |
- if (t === "ln") s.push(Math.log(v)); |
|
| 153 |
- } else {
|
|
| 154 |
- const b = s.pop(), a = s.pop(); |
|
| 155 |
- if (t === "+") s.push(a + b); |
|
| 156 |
- if (t === "-") s.push(a - b); |
|
| 157 |
- if (t === "*") s.push(a * b); |
|
| 158 |
- if (t === "/") s.push(a / b); |
|
| 159 |
- } |
|
| 160 |
- if (s.length < 0) throw 0; |
|
| 161 |
- } |
|
| 162 |
- if (s.length !== 1) throw 0; |
|
| 163 |
- return s[0]; |
|
| 164 |
- } |
|
| 186 |
+ |
|
| 165 | 187 |
function closeEnough(a, b) {
|
| 166 | 188 |
for (let i = 0; i < a.length; i++) {
|
| 167 | 189 |
if (isNaN(a[i]) || Math.abs(a[i] - b[i]) > 0.1 * (Math.abs(b[i]) + 1)) return false; |
| 168 | 190 |