diff --git a/index.html b/index.html index 683ebb38..eef78ebd 100644 --- a/index.html +++ b/index.html @@ -6262,7 +6262,7 @@ - + @@ -6280,7 +6280,7 @@ - + diff --git a/modules/burgs-and-states.js b/modules/burgs-and-states.js index f3f5164e..449e48a0 100644 --- a/modules/burgs-and-states.js +++ b/modules/burgs-and-states.js @@ -496,25 +496,20 @@ window.BurgsAndStates = (function () { paths.push([s.i, relaxed]); function getHull(start, state, maxLake) { - const queue = [start], - hull = new Set(); + const queue = [start]; + const hull = new Set(); while (queue.length) { const q = queue.pop(); - const nQ = cells.c[q].filter(c => cells.state[c] === state); + const sameStateNeibs = cells.c[q].filter(c => cells.state[c] === state); cells.c[q].forEach(function (c, d) { const passableLake = features[cells.f[c]].type === "lake" && features[cells.f[c]].cells < maxLake; - if (cells.b[c] || (cells.state[c] !== state && !passableLake)) { - hull.add(cells.v[q][d]); - return; - } - const nC = cells.c[c].filter(n => cells.state[n] === state); - const intersected = common(nQ, nC).length; - if (hull.size > 20 && !intersected && !passableLake) { - hull.add(cells.v[q][d]); - return; - } + if (cells.b[c] || (cells.state[c] !== state && !passableLake)) return hull.add(cells.v[q][d]); + + const hasCoadjacentSameStateCells = sameStateNeibs.some(neib => cells.c[c].includes(neib)); + if (hull.size > 20 && !hasCoadjacentSameStateCells && !passableLake) return hull.add(cells.v[q][d]); + if (used[c]) return; used[c] = 1; queue.push(c); diff --git a/utils/arrayUtils.js b/utils/arrayUtils.js index b59d48e3..a7f0c35f 100644 --- a/utils/arrayUtils.js +++ b/utils/arrayUtils.js @@ -6,45 +6,39 @@ function last(array) { return array[array.length - 1]; } -// return array of values common for both array a and array b -function common(a, b) { - const setB = new Set(b); - return [...new Set(a)].filter(a => setB.has(a)); -} - function unique(array) { return [...new Set(array)]; } // deep copy for Arrays (and other objects) function deepCopy(obj) { - const id = x=>x; + const id = x => x; const dcTArray = a => a.map(id); - const dcObject = x => Object.fromEntries(Object.entries(x).map(([k,d])=>[k,dcAny(d)])); - const dcAny = x => x instanceof Object ? (cf.get(x.constructor)||id)(x) : x; + const dcObject = x => Object.fromEntries(Object.entries(x).map(([k, d]) => [k, dcAny(d)])); + const dcAny = x => (x instanceof Object ? (cf.get(x.constructor) || id)(x) : x); // don't map keys, probably this is what we would expect - const dcMapCore = m => [...m.entries()].map(([k,v])=>[k, dcAny(v)]); + const dcMapCore = m => [...m.entries()].map(([k, v]) => [k, dcAny(v)]); const cf = new Map([ - [Int8Array, dcTArray], - [Uint8Array, dcTArray], - [Uint8ClampedArray, dcTArray], - [Int16Array, dcTArray], - [Uint16Array, dcTArray], - [Int32Array, dcTArray], - [Uint32Array, dcTArray], - [Float32Array, dcTArray], - [Float64Array, dcTArray], - [BigInt64Array, dcTArray], - [BigUint64Array, dcTArray], - [Map, m => new Map(dcMapCore(m))], - [WeakMap, m => new WeakMap(dcMapCore(m))], - [Array, a => a.map(dcAny)], - [Set, s => [...s.values()].map(dcAny)], - [Date, d => new Date(d.getTime())], - [Object, dcObject], - // other types will be referenced - // ... extend here to implement their custom deep copy + [Int8Array, dcTArray], + [Uint8Array, dcTArray], + [Uint8ClampedArray, dcTArray], + [Int16Array, dcTArray], + [Uint16Array, dcTArray], + [Int32Array, dcTArray], + [Uint32Array, dcTArray], + [Float32Array, dcTArray], + [Float64Array, dcTArray], + [BigInt64Array, dcTArray], + [BigUint64Array, dcTArray], + [Map, m => new Map(dcMapCore(m))], + [WeakMap, m => new WeakMap(dcMapCore(m))], + [Array, a => a.map(dcAny)], + [Set, s => [...s.values()].map(dcAny)], + [Date, d => new Date(d.getTime())], + [Object, dcObject] + // other types will be referenced + // ... extend here to implement their custom deep copy ]); return dcAny(obj);