Skip to content

Instantly share code, notes, and snippets.

@Renari
Created December 15, 2022 22:05
Show Gist options
  • Save Renari/77a7124ffbd8ce410a7dbcf30fdb863e to your computer and use it in GitHub Desktop.
Save Renari/77a7124ffbd8ce410a7dbcf30fdb863e to your computer and use it in GitHub Desktop.
const fs = require("fs")
class Point {
x
y
constructor(x, y) {
this.x = x
this.y = y
}
}
class Sensor extends Point {
beacon
length
constructor(inputData) {
const regex = /^Sensor at x=(-?\d+), y=(-?\d+): closest beacon is at x=(-?\d+), y=(-?\d+)$/gm;
const match = regex.exec(inputData)
super(parseInt(match[1]), parseInt(match[2]))
this.beacon = new Point(parseInt(match[3]), parseInt(match[4]))
/**
* determine length of the triangle covered by this sensor
*/
let leftRightModifier = 0
let upDownModifier = 0
if (this.x > this.beacon.x) {
leftRightModifier = 1
} else if (this.x < this.beacon.x) {
leftRightModifier = -1
}
if (this.y > this.beacon.y) {
upDownModifier = -1
} else if (this.y < this.beacon.y) {
upDownModifier = 1
}
if (leftRightModifier === 0 || upDownModifier === 0) {
// the beacon is on the same line as our sensor, so it is at the furthest point
this.setLength(this.beacon)
} else {
let x = this.beacon.x
let y = this.beacon.y
while(x !== this.x && y !== this.y) {
x += leftRightModifier
y += upDownModifier
}
this.setLength(new Point(x, y))
}
}
/**
* Checks if a point is inside this sensors range
* @param point the Point to check
*/
isInside(point) {
const area = this.triangleArea(new Point(this.x, this.y), new Point(this.x + this.length, this.y), new Point(this.x, this.y + this.length))
const positiveBase = new Point(this.x + this.length, this.y)
const positiveHeight = new Point(this.x, this.y + this.length)
const negativeBase = new Point(this.x - this.length, this.y)
const negativeHeight = new Point(this.x, this.y - this.length)
// positive positive direction
if (area === this.cumulativeArea(point, positiveBase, positiveHeight)) {
return true
}
// positive negative direction
if (area === this.cumulativeArea(point, positiveBase, negativeHeight)) {
return true
}
// negative positive direction
if (area === this.cumulativeArea(point, negativeBase, positiveHeight)) {
return true
}
// negative negative direction
if (area === this.cumulativeArea(point, negativeBase, negativeHeight)) {
return true
}
return false
}
/**
* Calculate the area of a triangle given 3 points
*/
triangleArea(point1, point2, point3) {
return Math.abs((point1.x*(point2.y-point3.y) + point2.x*(point3.y-point1.y)+ point3.x*(point1.y-point2.y))/2.0)
}
cumulativeArea(point1, point2, point3) {
const area1 = this.triangleArea(point1, point2, point3)
const area2 = this.triangleArea(this, point1, point3)
const area3 = this.triangleArea(this, point2, point1)
return area1 + area2 + area3
}
/**
* Used to set the range of this sensor
* @param point the furthest location that this sensor can reach
*/
setLength(point) {
this.length = Math.sqrt(Math.pow(this.x - point.x, 2) + Math.pow(this.y - point.y, 2))
}
}
const input = fs.readFileSync("sample.txt")
const lines = input.toString().split('\r\n')
const sensors = []
for (let line of lines) {
sensors.push(new Sensor(line))
}
// since we are checking for y values get highest and smallest x locations
let maxX = 0
let minX = 0
for (let sensor of sensors) {
if (sensor.x - sensor.length < minX) {
minX = sensor.x - sensor.length
}
if (sensor.x + sensor.length > maxX) {
maxX = sensor.x + sensor.length
}
}
let coveredLocations = 0
const y = 10;
for (let x = minX; x <= maxX; x++) {
let covered = false
let symbol = "."
for (let sensor of sensors) {
if((sensor.x === x && sensor.y === y)) {
// this location cannot be covered because it's occupied by a sensor
covered = false
symbol = "S"
break
} else if (sensor.beacon.x === x && sensor.beacon.y === y) {
// this location cannot be covered because it's occupied by a beacon
covered = false
symbol = "B"
break
}
if(sensor.isInside(new Point(x, y))) {
covered = true
symbol = "#"
}
}
if (covered) {
coveredLocations++
}
process.stdout.write(symbol)
}
console.log("")
console.log(coveredLocations)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment