Published
Edited
Dec 5, 2019
Insert cell
Insert cell
Insert cell
rightMove = start => (_,i) => ({x: start.x + i + 1, y: start.y})
Insert cell
leftMove = start => (_,i) => ({x: start.x - i - 1, y: start.y})
Insert cell
upMove = start => (_,i) => ({x: start.x, y: start.y - i - 1})
Insert cell
downMove = start => (_,i) => ({x: start.x, y: start.y + i + 1})
Insert cell
parseMove = (command, start) => {
const dir = command.charAt(0)
const move = dir == "R" ? rightMove : dir == "L" ? leftMove : dir == "U" ? upMove : downMove
return Array.from({length: parseInt(command.substring(1))}, move(start))
}
Insert cell
lines = instructions =>
instructions
.map(d => d.split(","))
.map(d => d.reduce((acc, inc) => acc.concat(parseMove(inc, acc[acc.length-1])), [{x: 0, y: 0}]))
Insert cell
intersections = xs => {
const clone1 = xs[0].slice(0).map(d => `${d.x},${d.y}`).sort() // flatten point objects to string to compare
const clone2 = xs[1].slice(0).map(d => `${d.x},${d.y}`).sort() // flatten point objects to string to compare
// remove duplicates, which represent self-intersections
let dedupe1 = []
for(let i = 0; i < clone1.length-1; i++) {
if(clone1[i]!=clone1[i+1]) dedupe1.push(clone1[i]) // duplicates are next to each because array is sorted
}
// remove duplicates, which represent self-intersections
let dedupe2 = []
for(let i = 0; i < clone2.length-1; i++) {
if(clone2[i]!=clone2[i+1]) dedupe2.push(clone2[i]) // duplicates are next to each because array is sorted
}
return dedupe1.concat(dedupe2)
.sort() // for the function below
.reduce((acc, cur, idx, src) => idx > src.length-1 ? acc : src[idx]==src[idx+1] ? acc.concat(cur) : acc, []) // reduce array to just values that appear more than once (intersections)
.map(d => { const str = d.split(","); return ({x: str[0], y: str[1]})}) // convert back to object
.filter(d => !(d.x == 0 && d.y ==0))
}
Insert cell
manhattan = p1 => p2 => Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y)
Insert cell
manhattanFromCenter = manhattan({x: 0, y:0})
Insert cell
solve1 = d =>
intersections(lines(d))
.map(manhattanFromCenter)
.reduce((acc,inc) => Math.min(acc,inc), Infinity)
Insert cell
testSolutions = tests
.map(solve1)
Insert cell
solve1(data)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
solve2 = x =>
{
const pointToString = obj => `${obj.x},${obj.y}` // flatten point objs for easy comparison
const wires = lines(x)
const crosses = intersections(wires)
return crosses
.map(cross => // for each intersection
wires
.map(wire => wire.map(pointToString))
.map(wire => wire.indexOf(pointToString(cross))) // find dist along each wire to that point
)
.map(dists => dists.reduce((acc, inc) => acc + inc, 0)) // sum the dists of the two wires
.reduce((acc, inc) => Math.min(acc, inc), Infinity) // find the shortest total dist
}
Insert cell
testSolutions2 = tests2.map(solve2)
Insert cell
solve2(data)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more