[...document.querySelectorAll("#game > div > div")].forEach(e => e.style.transform="rotate(0deg)")
It doesn't win the game, but can at least save the "preview" clicks. [...document.querySelectorAll("#game > div > div")].forEach(e => e.style.transform="rotate(0deg)")
It doesn't win the game, but can at least save the "preview" clicks. import numpy as np
from mip import Model, xsum, minimize, BINARY
def solve(tiles):
rotations = [[[] for _ in row] for row in tiles]
rot_vars = [[[] for _ in row] for row in tiles]
model = Model("rotaboxes")
for i, row in enumerate(tiles):
for j, tile in enumerate(row):
for _ in range(3):
tile = tile.transpose((1, 0, 2))[::-1]
rotations[i][j].append(tile)
rot_vars[i][j].append(model.add_var(var_type=BINARY))
model += (xsum(rot_vars[i][j]) == 1)
costs = []
for i, row in enumerate(tiles):
for j, tile in enumerate(row):
for (di, dj) in [(0, 1), (1, 0)]:
if (i + di >= len(tiles)) or (j + dj >= len(tiles[0])):
continue
for r0, t0 in enumerate(rotations[i][j]):
for r1, t1 in enumerate(rotations[i + di][j + dj]):
if di:
a, b = t0[-1], t1[0]
else:
a, b = t0[:,-1], t1[:,0]
n = np.square(a - b).mean()
d = np.square(a[1:] - a[:1]).mean() + np.square(b[1:] - b[:1]).mean()
e = 2. * n / (d + 0.01)
v = model.add_var(var_type=BINARY)
model += (v >= rot_vars[i][j][r0] + rot_vars[i + di][j + dj][r1] - 1)
costs.append(e * v)
model.objective = minimize(xsum(costs))
model.optimize()
solution = [[[r for v, r in zip(vs, rs) if v.x >= 0.99][0] for vs, rs in zip(row0, row1)] for row0, row1 in zip(rot_vars, rotations)]
return solution document.querySelectorAll("#game > div > div").forEach(e => {
const rotation = e.style.transform.match(/(\d+)/)[0];
const clicks = 4-(rotation/90)%4;
[...Array(clicks)].forEach(i=>e.click());
});
It could be optimized to change the rotation direction depending on whether the current rotation is smaller or larger than 180deg, but that's not really necessary since running the script only counts as one click, and generates negative "overspin" numbers ;-)https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
(In python there is the "*" operator which should be equivalent: [1, 2, *arr].
Array(clicks) instantiate an array of length 'clicks', with its elements undefined.
Then "[...Array(clicks)]" takes the above array instance and spreads it as content in another array.
Seems redundant and they could've just used Array(clicks).
Not undefined elements but no elements, or "empty" elements.
> they could've just used Array(clicks).
No, because the following forEach call does nothing for such an array. You need to fill the array first with Array(clicks).fill() or shorter, [...Array(clicks)]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Array(length) creates an array that has a length but no elements (or weird, "empty" elements). The square brackets create a new array [...Array(length)] which will have undefined elements instead, as trying to access an "empty" element returns undefined.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid...
for(let i=0; i<clicks; i++){ e.click() }; document.querySelectorAll("#game > div > div").forEach(e => e.style.transform="rotate(0deg)")
Works too.(But since querySelectorAll returns a NodeList and not a regular array, some methods are unavailable, so I just have this habit of making it an array. But for iteration that's indeed not needed.)