Skip to content

Commit 64cbe34

Browse files
committed
chore: solution draft
1 parent 8c483ad commit 64cbe34

File tree

6 files changed

+249
-67
lines changed

6 files changed

+249
-67
lines changed

solutions/typescript/2024/01/src/p1.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ export const p1 = (input: string): number => {
1212
.map(([l, r]) => Math.abs(l - r))
1313
.sum();
1414
};
15+
1516
await task(p1, packageJson.aoc); // 1722302 ~16.04ms

solutions/typescript/2024/06/src/p1.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const p1 = (input: string): number => {
2727
guardPosition.addMut(guardDirection);
2828
guardPath.add(guardPosition.toString());
2929
}
30-
//g.print((n) => (guardPath.has(n.coordinate.toString()) ? 'X' : n.toString()));
30+
g.print((n) => (guardPath.has(n.coordinate.toString()) ? 'X' : n.toString()));
3131
return guardPath.size;
3232
};
3333

Lines changed: 176 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,186 @@
1-
import { Direction, task } from '@alexaegis/advent-of-code-lib';
1+
import { BoundingBox, Direction, task, Vec2, type Vec2String } from '@alexaegis/advent-of-code-lib';
22
import packageJson from '../package.json' assert { type: 'json' };
33

4-
export const p2 = (input: string): number => {
5-
const g = input.toGridGraph({});
6-
const possibleObstructionCoordinates = g.nodeValues
7-
.filter((node) => node.value === '.')
8-
.map((node) => node.coordinate);
9-
return possibleObstructionCoordinates.filter((possibleObstructionCoordinate) => {
10-
const g = input.toGridGraph({});
11-
12-
const guardNode = g.findNode((node) => node.value === '^');
13-
if (!guardNode) {
14-
throw new Error('Guard not found');
4+
export interface PatrolResult {
5+
path: Set<Vec2String>;
6+
encounters: Set<Vec2String>;
7+
isLoop: boolean;
8+
movement: Move[];
9+
}
10+
11+
interface Move {
12+
position: Vec2;
13+
direction: Direction;
14+
}
15+
16+
export const patrol = (obscructions: Set<string>, map: BoundingBox, from: Vec2): PatrolResult => {
17+
let guardPosition = from.clone();
18+
let guardDirection = Direction.NORTH.clone();
19+
const path = new Set<Vec2String>();
20+
const encounters = new Set<Vec2String>();
21+
const guardMovement = new Set<string>();
22+
const movementPath: Move[] = [];
23+
24+
path.add(guardPosition.toString());
25+
guardMovement.add(guardPosition.toString() + '+' + guardDirection.toString());
26+
movementPath.push({ position: guardPosition, direction: guardDirection });
27+
28+
let isLoop = false;
29+
30+
while (true) {
31+
let forwardPosition = guardPosition.add(guardDirection);
32+
if (!forwardPosition.isWithin(map)) {
33+
break;
1534
}
1635

17-
const obsructionNode = g.getNode(possibleObstructionCoordinate);
18-
if (!obsructionNode) {
19-
throw new Error('Obstruction not found');
36+
if (obscructions.has(forwardPosition.toString())) {
37+
encounters.add(forwardPosition.toString());
38+
guardDirection = guardDirection.rotateLeft();
2039
}
2140

22-
obsructionNode.setValue('#');
23-
guardNode.setValue('.');
24-
let guardPosition = guardNode.coordinate;
25-
let guardDirection = Direction.NORTH.clone();
26-
const guardPath = new Set<string>();
27-
const guardMovement = new Set<string>();
28-
29-
guardPath.add(guardPosition.toString());
30-
guardMovement.add(guardPosition.toString() + '+' + guardDirection.toString());
31-
32-
let isLoop = false;
33-
let i = 0;
34-
while (true) {
35-
i++;
36-
let forwardPosition = guardPosition.add(guardDirection);
37-
let forwardNode = g.getNode(forwardPosition);
38-
if (!forwardNode) {
39-
// Not a loop
40-
break;
41-
}
42-
if (forwardNode.value === '#') {
43-
guardDirection = guardDirection.rotateLeft();
44-
}
45-
46-
const pathLengthBeforeStep = guardMovement.size;
47-
guardPosition.addMut(guardDirection);
48-
guardPath.add(guardPosition.toString());
49-
guardMovement.add(guardPosition.toString() + '+' + guardDirection.toString());
50-
51-
const pathLengthAfterStep = guardMovement.size;
52-
if (pathLengthBeforeStep === pathLengthAfterStep) {
53-
isLoop = true;
54-
break;
55-
}
41+
guardPosition.addMut(guardDirection);
42+
path.add(guardPosition.toString());
43+
const move = guardPosition.toString() + '+' + guardDirection.toString();
44+
movementPath.push({ position: guardPosition, direction: guardDirection });
45+
46+
if (guardMovement.has(move)) {
47+
isLoop = true;
48+
break;
49+
} else {
50+
guardMovement.add(move);
5651
}
57-
//g.print((n) => (guardPath.has(n.coordinate.toString()) ? 'X' : n.toString()));
58-
//console.log('--------', daysWithoutUpdate, isLoop, i);
59-
// possibleObstructionNode.setValue('.');
60-
return isLoop;
52+
}
53+
return {
54+
path,
55+
encounters,
56+
isLoop,
57+
};
58+
};
59+
60+
/**
61+
* Since the guard can only rotate right, and 90 degrees, a loop always
62+
* will look like a rectangle
63+
*/
64+
export const matchEnclosure = (
65+
position: Vec2,
66+
direction: Direction,
67+
pivotPlacement: Direction,
68+
boundingBox: BoundingBox,
69+
obscructions: Set<Vec2String>,
70+
): boolean => {
71+
const possibleObstruction = position.add(direction);
72+
if (obscructions.has(possibleObstruction.toString())) {
73+
return false; // Already obsctructed
74+
}
75+
76+
const firstCorner = position.add(direction.rotateLeft(1), {
77+
times: (v) => !obscructions.has(v.toString()) && boundingBox.contains(v),
78+
});
79+
console.log('fc', firstCorner);
80+
81+
return false;
82+
};
83+
84+
export const createParametricEnclosure =
85+
(pivot: Vec2, pivotPlacement: Direction) => (size: Vec2) => {};
86+
87+
export const createEnclosure = (pivot: Vec2, pivotPlacement: Direction, size: Vec2): Vec2[] => {
88+
const corners = [pivot];
89+
90+
const vertical = pivotPlacement.y > 0 ? new Vec2(1, -size.y) : new Vec2(-1, size.y);
91+
const horizontal = pivotPlacement.x > 0 ? new Vec2(-size.x, -1) : new Vec2(size.x, 1);
92+
// Horizontal
93+
94+
corners.push(pivot.add(vertical));
95+
corners.push(pivot.add(horizontal));
96+
97+
corners.push(pivot.add(vertical.add(horizontal)));
98+
99+
return corners;
100+
};
101+
102+
const enclosurePivotMap = {
103+
[Direction.NORTH.toString()]: Direction.NORTHWEST,
104+
[Direction.EAST.toString()]: Direction.NORTHEAST,
105+
[Direction.SOUTH.toString()]: Direction.SOUTHEAST,
106+
[Direction.WEST.toString()]: Direction.SOUTHWEST,
107+
} as const;
108+
109+
export const p2 = (input: string): number => {
110+
const g = input.toGridGraph();
111+
const boundingBox = g.boundingBox();
112+
113+
const obstructions = new Set(
114+
g.nodeValues.filter((node) => node.value === '#').map((node) => node.coordinate.toString()),
115+
);
116+
117+
const freeNodes = new Set(
118+
g.nodeValues.filter((node) => node.value === '.').map((node) => node.coordinate.toString()),
119+
);
120+
121+
const guardNode = g.findNode((node) => node.value === '^');
122+
if (!guardNode) {
123+
throw new Error('Guard not found');
124+
}
125+
126+
g.print();
127+
console.log('23332323----------------------');
128+
129+
const originalPatrolResult = patrol(obstructions, boundingBox, guardNode.coordinate);
130+
131+
const enclosure = createEnclosure(new Vec2(3, 3), Direction.SOUTHWEST, new Vec2(3, 3));
132+
133+
g.print((n) =>
134+
enclosure.map((e) => e.toString()).includes(n.coordinate.toString())
135+
? enclosure
136+
.map((e) => e.toString())
137+
.indexOf(n.coordinate.toString())
138+
.toString()
139+
: originalPatrolResult.path.has(n.coordinate.toString())
140+
? 'X'
141+
: originalPatrolResult.encounters.has(n.coordinate.toString())
142+
? 'E'
143+
: n.toString(),
144+
);
145+
146+
const result = originalPatrolResult.movement.filter((move) => {
147+
const pivotPlacement = enclosurePivotMap[move.direction.toString()];
148+
if (!pivotPlacement) {
149+
throw new Error('invalid direction');
150+
}
151+
return matchEnclosure(
152+
move.position,
153+
move.direction,
154+
pivotPlacement,
155+
boundingBox,
156+
obstructions,
157+
);
61158
}).length;
159+
160+
// const possibleObstructionCoordinates = [...originalPatrolResult.path].filter(
161+
// (p) => p !== guardNode.coordinate.toString(),
162+
// );
163+
164+
//const possibleObstructionCoordinates = [...freeNodes];
165+
//
166+
//return possibleObstructionCoordinates.filter((possibleObstructionCoordinate) => {
167+
// const newObstructions = new Set(obstructions);
168+
// newObstructions.add(possibleObstructionCoordinate);
169+
//
170+
// const patrolResult = patrol(newObstructions, map, guardNode.coordinate);
171+
//
172+
// //g.print((n) =>
173+
// // patrolResult.path.has(n.coordinate.toString())
174+
// // ? 'X'
175+
// // : n.coordinate.toString() === possibleObstructionCoordinate
176+
// // ? 'O'
177+
// // : n.toString(),
178+
// //);
179+
// // console.log('--------', patrolResult);
180+
// return patrolResult.isLoop;
181+
//}).length;
182+
return result;
62183
};
63184

64-
await task(p2, packageJson.aoc); // 4602 ~0.09ms
185+
await task(p2, packageJson.aoc); // 1563 ~0.09ms
186+
// 1563 too low

solutions/typescript/libs/lib/src/model/vector/vec2.class.spec.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,52 @@ describe('Vec2', () => {
3131
});
3232
});
3333
});
34+
35+
describe('addMut', () => {
36+
it('should add a vector to another', () => {
37+
const target = new Vec2(1, 1);
38+
const delta = new Vec2(2, 3);
39+
const expectedResult = new Vec2(3, 4);
40+
target.addMut(delta);
41+
expect(target).toEqual(expectedResult);
42+
});
43+
44+
it('should add a vector to another many times', () => {
45+
const target = new Vec2(1, 1);
46+
const delta = new Vec2(2, 3);
47+
const expectedResult = new Vec2(9, 13);
48+
target.addMut(delta, { times: 4 });
49+
expect(target).toEqual(expectedResult);
50+
});
51+
52+
it('should add a vector to another multiple times while it should', () => {
53+
const target = new Vec2(1, 1);
54+
const delta = new Vec2(2, 3);
55+
const expectedResult = new Vec2(9, 13);
56+
target.addMut(delta, {
57+
times: (_v, i) => i < 4,
58+
});
59+
expect(target).toEqual(expectedResult);
60+
});
61+
62+
it('should add a vector to another multiple times while it can', () => {
63+
const target = new Vec2(1, 1);
64+
const delta = new Vec2(2, 3);
65+
const expectedResult = new Vec2(5, 7);
66+
target.addMut(delta, {
67+
times: (v, _i) => v.x < 7,
68+
});
69+
expect(target).toEqual(expectedResult);
70+
});
71+
72+
it('should not add a vector to another multiple times if it cant', () => {
73+
const target = new Vec2(1, 1);
74+
const delta = new Vec2(2, 3);
75+
const expectedResult = new Vec2(1, 1);
76+
target.addMut(delta, {
77+
times: (v, _i) => v.x < 1,
78+
});
79+
expect(target).toEqual(expectedResult);
80+
});
81+
});
3482
});

solutions/typescript/libs/lib/src/model/vector/vec2.class.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export class Vec2 implements Vec2Like {
156156
public add(
157157
coord: Vec2Like,
158158
options?: {
159-
times?: number;
159+
times?: number | ((v: Vec2, i: number) => boolean);
160160
limit?: BoundingBox | ((v: Vec2Like) => boolean);
161161
},
162162
): Vec2 {
@@ -190,16 +190,30 @@ export class Vec2 implements Vec2Like {
190190
public addMut(
191191
v: Vec2Like,
192192
options?: {
193-
times?: number;
193+
times?: number | ((v: Vec2, i: number) => boolean);
194194
limit?: BoundingBox | ((v: Vec2Like) => boolean);
195195
flipX?: boolean;
196196
flipY?: boolean;
197197
},
198198
): this {
199199
const originalX = this.x;
200200
const originalY = this.y;
201-
const diffX = v.x * (options?.times ?? 1);
202-
const diffY = v.y * (options?.times ?? 1);
201+
202+
let diffX = 0;
203+
let diffY = 0;
204+
205+
if (typeof options?.times === 'function') {
206+
let times = 0;
207+
while (options.times(this.add(v, { times: times + 1 }), times)) {
208+
times++;
209+
}
210+
diffX = v.x * times;
211+
diffY = v.y * times;
212+
} else {
213+
const times = options?.times ?? 1;
214+
diffX = v.x * times;
215+
diffY = v.y * times;
216+
}
203217

204218
this.x += options?.flipX ? -diffX : diffX;
205219
this.y += options?.flipY ? -diffY : diffY;

solutions/typescript/libs/lib/src/platform/bench-task.function.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,12 @@ export const benchTask = async <Input, Result = string, Args = undefined>(
1515
resources: TaskResources<Input, Args>,
1616
logger?: Logger,
1717
): Promise<Result> => {
18-
// TODO: Remove the if once PerformanceObserver is implemented in bun
19-
if (process.versions['bun'] === undefined) {
20-
const obs = new PerformanceObserver((list) => {
21-
list.getEntries().forEach((entry) => {
22-
logger?.(`${entry.name}: ${roundToDecimal(entry.duration, 2)} ms`);
23-
});
18+
const obs = new PerformanceObserver((list) => {
19+
list.getEntries().forEach((entry) => {
20+
logger?.(`${entry.name}: ${roundToDecimal(entry.duration, 2)} ms`);
2421
});
25-
obs.observe({ entryTypes: ['measure'], buffered: true });
26-
}
22+
});
23+
obs.observe({ entryTypes: ['measure'], buffered: true });
2724

2825
performance.mark('runstart');
2926
const result = await runner(resources.input, resources.args);

0 commit comments

Comments
 (0)