Giter VIP home page Giter VIP logo

adventofcode's People

Contributors

dependabot[bot] avatar werner77 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

adventofcode's Issues

Typescript?

No worries if you don't have time or desire to peek, but I'm writing my solutions in typescript. Part 2 is beyond me, even after watching your video lol. The VAST majority of solutions/explanations out there are simply using Python/sympy which I conceptually understand but obviously don't have sympy avail to me. I tried converting your code to typescript, but even for the test data the attempt to Project to z-axis fails.

If you are feeling like it and want to see if you spot anything in the code, let me know if you spot anything.

  1. I used typescript/javascript built in bigint.
  2. I couldn't directly decompose the results from findRockPositionAndVelocity so I manually assigned them. But I haven't even hit that code yet, so that isn't the (ultimate) problem.

Thanks in advance.

interface LongCoordinate { x: number; y: number; }
interface Coordinate3D { x: number; y: number; z: number; }
/**
 * Stone projected unto some axis (basically eliminating the projected axis, being x, y or z).
 */
class ProjectedStone {
	a: bigint; b: bigint; c: bigint;

	constructor(public position: LongCoordinate, public velocity: LongCoordinate) {
		this.a = BigInt(velocity.y);
		this.b = BigInt(-velocity.x);
		this.c = BigInt(velocity.y * position.x - velocity.x * position.y);
	}
	
	addingVelocity(delta: LongCoordinate): ProjectedStone {
		return new ProjectedStone(this.position, { x: this.velocity.x + delta.x, y: this.velocity.y + delta.y });
	}
}
class Stone {
	constructor(public position: Coordinate3D, public velocity: Coordinate3D) { }

	projected(component: number): ProjectedStone {
		switch (component) {
			case 0: return new ProjectedStone({ x: this.position.y, y: this.position.z }, { x: this.velocity.y, y: this.velocity.z });
			case 1: return new ProjectedStone({ x: this.position.x, y: this.position.z }, { x: this.velocity.x, y: this.velocity.z });
			case 2: return new ProjectedStone({ x: this.position.x, y: this.position.y }, { x: this.velocity.x, y: this.velocity.y });
			default: throw new Error(`Invalid component: ${component}`);
		}
	}
}

// Solve two linear equations for x and y
// Equations of the form: ax + by = c
function solveLinearEquation(a1: bigint, b1: bigint, c1: bigint, a2: bigint, b2: bigint, c2: bigint): LongCoordinate | undefined {
	const d = b2 * a1 - b1 * a2;
	if (d == BigInt(0) ) return undefined;
	const x = (b2 * c1 - b1 * c2) / d;
	const y = (c2 * a1 - c1 * a2) / d;
	return { x: Number(x), y: Number(y) };
}
/**
 * Processes all pairs of stones by projecting them unto the specified component (0 == x, 1 == y, 2 == z).
 *
 * Optionally a delta velocity is applied to each stone.
 *
 * If the processing block returns false this function immediately exits
 */
function processPairs(stones: Stone[], projectedComponent: number, deltaSpeed: LongCoordinate = { x: 0, y: 0 }, process: (arg: LongCoordinate | null) => boolean) {
	for (let i = 0; i < stones.length; i++) {
		for (let j = i + 1; j < stones.length; j++) {
			const firstStone = stones[i].projected(projectedComponent).addingVelocity(deltaSpeed);
			const secondStone = stones[j].projected(projectedComponent).addingVelocity(deltaSpeed);
			let intersection = solveLinearEquation(firstStone.a, firstStone.b, firstStone.c, secondStone.a, secondStone.b, secondStone.c);
			if (intersection != undefined && [firstStone, secondStone].every(it => Math.sign(intersection!.y - it.position.y) === Math.sign(it.velocity.y))) {
				if (!process(intersection)) return;
			}
		}
	}
}
/**
 * Searches for multiple intersection position using the specified projected component (x, y or z-axis).
 *
 * Brute forces over combinations of vx, vy to find a possible solution.
 *
 * The key insight is that a minus delta velocity can be applied to any stone and assume the rock to remain stationary (speed zero).
 * Because the rock has to collide with every stone, the stone paths should all have an intersection (which is the position of the rock).
 *
 * Returns a pair of position to velocity of the rock found for the projection, or null if no solution could be found.
 */
function findRockPositionAndVelocity(stones: Stone[], component: number): [LongCoordinate, LongCoordinate] | null {
	const maxValue = 400;
	const minResultCount = 5;
	for (let vx = -maxValue; vx <= maxValue; vx++) {
		for (let vy = -maxValue; vy <= maxValue; vy++) {
			const deltaV = { x: vx, y: vy };
			const matchingPositions: LongCoordinate[] = [];
			let resultCount = 0;
			processPairs(stones, component, deltaV, intersection => {
				if (intersection) {
					matchingPositions.push(intersection);
					resultCount++;
					return resultCount < minResultCount;
				} else {
					return false;
				}
			});
			if (matchingPositions.length === 1 && resultCount >= Math.min(minResultCount, stones.length / 2)) {
				return [matchingPositions[0], { x: -deltaV.x, y: -deltaV.y }];
			}
		}
	}
	return null;
}
  
const solve = (rawInput: string, isPart1: boolean, testName?: string) => {
	const input = parseInput(rawInput);
	const hailstones = input.hailstones;
	const stones = input.stones;
	const testAreaMin = testName != undefined ? 7 : 200000000000000;
	const testAreaMax = testName != undefined ? 27 : 400000000000000;

        // Project to z-axis
        const result1 = findRockPositionAndVelocity(stones, 2);
        if (!result1) throw new Error("Could not find result");
        
        // Project to x-axis
        const result2 = findRockPositionAndVelocity(stones, 0);
        if (!result2) throw new Error("Could not find result");
        
        // Project to y-axis
        const result3 = findRockPositionAndVelocity(stones, 1);
        if (!result3) throw new Error("Could not find result");
        
        /*
        const [x1, y1] = result1[0];
        const [y2, z1] = result2[0];
        const [x2, z2] = result3[0];
        const [vx1, vy1] = result1[1];
        const [vy2, vz1] = result2[1];
        const [vx2, vz2] = result3[1];
        */
        const x1 = result1[0].x;
        const y1 = result1[0].y;
        const y2 = result2[0].x;
        const z1 = result2[0].y;
        const x2 = result3[0].x;
        const z2 = result3[0].y;
        const vx1 = result1[1].x;
        const vy1 = result1[1].y;
        const vy2 = result2[1].x;
        const vz1 = result2[1].y;
        const vx2 = result3[1].x;
        const vz2 = result3[1].y;
        
        if (y1 !== y2 || x1 !== x2 || z1 !== z2) {
	        throw new Error("Expected positions to match");
        }
        if (vy1 !== vy2 || vx1 !== vx2 || vz1 !== vz2) {
	        throw new Error("Expected velocities to match");
        }
        
        console.log(`Found rock position and velocity: ${x1},${y1},${z1} @ ${vx1},${vy1},${vz1}`);
        
        console.log(x1 + y1 + z1);
};

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.