Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (() => {
- const pi2 = Math.PI * 2
- const getRingSize = (ring) => ring === 0 ? 1 : ring * 8
- let getRingStart = (ring) => {
- if(ring === 0) return 0
- let currSum = 0
- for(let i = 1; i < ring; i++) currSum += i * 8
- return currSum + 2
- }
- const getAngle = (dX, dY) => (Math.atan2(dY, dX) + pi2) % pi2
- const getCoords = (n) => {
- if(n === 1) return [0, 0]
- let ring = 1
- while(getRingStart(ring + 1) <= n) ring += 1
- const ringSize = getRingSize(ring)
- const ringPos = n - getRingStart(ring)
- const angle = ((ringPos / ringSize) - (ring - 1) / ringSize) * pi2
- const opposite = Math.abs((ringPos % (ring * 2)) - (ring - 1))
- const diag = Math.sqrt(Math.pow(ring, 2) + Math.pow(opposite, 2))
- return [
- Math.round(Math.cos(angle) * diag) + 0,
- Math.round(Math.sin(angle) * diag) + 0
- ]
- }
- const cache = {}
- const getIndex = (() => (x, y) => {
- const cacheKey = `${x}/${y}`
- if(x === 0 && y === 0) return 1
- if(cache[cacheKey]) return cache[cacheKey]
- const ring = Math.max(Math.abs(x), Math.abs(y))
- const ringAdjust = ring - 1
- const ringSize = getRingSize(ring)
- const ringStart = getRingStart(ring)
- const angle = getAngle(x, y)
- const ringPos = (Math.round((angle / pi2) * ringSize) + ringAdjust) % ringSize
- return cache[cacheKey] = ringStart + ringPos
- })()
- const getAdjacent = (n) => {
- const [x, y] = getCoords(n)
- const adj = [
- [x - 1, y + 1], [x, y + 1], [x + 1, y + 1],
- [x - 1, y] , [x + 1, y],
- [x - 1, y - 1], [x, y - 1], [x + 1, y - 1],
- ]
- return adj.map(([x, y]) => getIndex(x, y))
- }
- const cache2 = []
- const calcIndex = (index) => {
- if(index === 1) return 1
- if(cache2[index]) return cache2[index]
- const adjacent = getAdjacent(index).filter((adjIndex) => adjIndex <= index).sort((a, b) => a < b ? -1 : 1)
- return cache2[index] = adjacent.reduce((sum, adjIndex) => { return sum + calcIndex(adjIndex)}, 0)
- }
- let i = 0, result
- console.time('run')
- while((result = calcIndex(++i)) < 289326) {}
- console.timeEnd('run')
- console.log(result)
- })()
Add Comment
Please, Sign In to add comment