Ai has the sigma grindset. Fake it till you make it (but most probably crash and burn without handholding) lmao
Ai has the sigma grindset. Fake it till you make it (but most probably crash and burn without handholding) lmao
Of course i know him, he’s me
something i play more frequently like factorio, i would like for that to be a regular function.
That honestly sounds like a good feature to request imo.
Are you on the steam beta? I’ve generally had a better experience there.
You could also try the low performance setting in steam. (steam settings > library > low performance mode)
You can skip shader compilation. Also, it sounds like a driver issue. Electron has gpu suppport by default so it shouldn’t be laggy.
In my case, i use multiple workspaces. Had a workspace for gaming set up and left the window on the store page. Had a busy week so I didn’t game. I usually don’t turn off my computer because I contribute to Folding@Home at night. Week flies by and I start to wonder why my ram is full and investigate :D
memory leak’s at a rate that doesn’t matter (~30mb/hour). That makes it hard to track down & reproduce. Also, solution would be to just navigate to your steam library or just not leave the window open like that :p
Just mount your swap partition on google drive. xd
Oh yeah. If you leave a steam page open, it’ll create a very slow memory leak. Left store page open for about a week, came back to 6gb steamwebhelper xd
Huh… i used specifically the Date chooser and it came out with a box. I’m sorry for misunderstanding
Works on desktop too
Works on FF android.
Tested with: https://inputtypes.com/
straight-forward
Maybe for you 😅
Maaaannnn. Today’s solution was really something. I actually got so confused initially that I unknowingly wrote the algorithm for part 2 before I even finished part 1! As an upside, however, I did expand my own Advent of Code standard library ;)
import { AdventOfCodeSolutionFunction } from "./solutions";
import { Grid } from "./utils/grids";
import { LinkedPoint } from "./utils/structures/linkedPoint";
import { makeGridFromMultilineString, SumArray } from "./utils/utils";
class TrailPoint extends LinkedPoint<number, TrailPoint> {
constructor(x: number, y: number, item: number, grid: Grid<TrailPoint>) {
super(x, y, item, grid);
}
lookAroundValid(): Array<TrailPoint> {
return this.lookAround().filter(v => v.item == this.item + 1);
}
findAllValidPeaks(): Array<TrailPoint> {
if (this.item == 9)
return [this];
// filter for distinct references (this theoretically saves time)
return [...(new Set(this.lookAroundValid().flatMap(v => v.findAllValidPeaks())))];
}
findAllValidPeaksWithReps(): Array<TrailPoint> {
if (this.item == 9)
return [this];
// don't filter
return this.lookAroundValid().flatMap(v => v.findAllValidPeaksWithReps());
}
}
export const solution_10: AdventOfCodeSolutionFunction = (input) => {
const map: Grid<TrailPoint> =
makeGridFromMultilineString(input)
.map((row) => row.map((item) => item != "." ? Number(item) : -1))
.map((row, y) => row.map((item, x) => new TrailPoint(x, y, item, undefined!)));
map.flat().forEach((v) => v.grid = map); // promise is a promise
const startNodes: Array<TrailPoint> = map.flat().filter(v => v.item == 0);
const part_1 = SumArray(startNodes.map(v => v.findAllValidPeaks().length));
const part_2 = SumArray(startNodes.map(v => v.findAllValidPeaksWithReps().length));
return {
part_1, // 557
part_2, // 1062
}
}
Actually kinda proud of my solution considering how hectic today has been! I actually didn’t spend too much time on this solution too :) Runs in ~0.5s.
import { AdventOfCodeSolutionFunction } from "./solutions";
import { MakeEmptyGenericArray } from "./utils/utils";
const pretty_print = (disk: Array<number>) => disk.reduce<string>((prev, curr) => prev + (curr == -1 ? "." : curr), "");
const checksum = (disk: Array<number>) => disk.reduce<number>((prev, curr, index) => prev + (curr == -1 ? 0 : curr * index), 0);
const findSlice = (disk: Array<number>, id: number, startFrom?: number) => {
const sectionStart = disk.indexOf(id, startFrom);
if (sectionStart == -1)
return [-1, -1];
let sectionEnd = sectionStart;
while (disk.length > ++sectionEnd && disk[sectionEnd] == id);
return [sectionStart, sectionEnd];
}
export const solution_9: AdventOfCodeSolutionFunction = (input) => {
let isFile = false;
let id = 0;
// make the disk
const disk = input.split("").flatMap((v) => {
isFile = !isFile;
const count = Number(v);
if (isFile) {
id++;
return MakeEmptyGenericArray(count, () => id - 1);
}
return MakeEmptyGenericArray(count, () => -1);
});
// make a copy of the disk
const fragmentedDisk = [...disk];
// start moving elements on the disk
let start = 0
let end = fragmentedDisk.length - 1;
while (start < end) {
if (fragmentedDisk[start] != -1) {
start++;
continue;
}
if (fragmentedDisk[end] == -1) {
end--;
continue;
}
// swap the values
fragmentedDisk[start] = fragmentedDisk[end]
fragmentedDisk[end] = -1;
start++;
end--;
}
main: while (id-- > 0) {
// find the section that has the file
const [sectionStart, sectionEnd] = findSlice(disk, id); // this will never return -1
const sectionLength = sectionEnd - sectionStart;
// find any section that can fit the file
let freeStart;
let freeEnd = 0;
do {
[freeStart, freeEnd] = findSlice(disk, -1, freeEnd);
// can't find any free spaces or too far right
if (freeStart == -1 || freeStart > sectionStart)
continue main;
} while (freeEnd - freeStart < sectionLength);
// switch places
let i = 0;
while(sectionStart + i < sectionEnd) {
disk[freeStart + i] = id;
disk[sectionStart + i++] = -1;
}
}
// calculate the checksums
return {
part_1: checksum(fragmentedDisk),
part_2: checksum(disk),
}
}
Any solution that solves the problem is a good solution :D
I was a little confuzzled with this one, but I managed to get it. :) Happy to know that I managed to reuse more of my code from previous days. I should write something to handle Vectors. It was sad to write my own basic, non-reusable thing.
import { AdventOfCodeSolutionFunction } from "./solutions";
// imported code:
export const check_coords = (grid: Array<Array<any>>, x: number, y: number) => {
return y >= grid.length ||
y < 0 ||
x >= grid[y].length ||
x < 0
}
export const makeGridFromMultilineString =
(input: string) => input.split("\n").map(st => st.trim()).map(v => v.split(""));
export const MakeEmptyGenericArray = <T>(length: number, fn: (index: number) => T) => {
const newArray = [];
let i = 0;
while (i++ < length)
newArray.push(fn(i));
return newArray;
}
export const MakeEmptyArray = (length: number) => MakeEmptyGenericArray(length, () => 0);
export const MakeEmpty2DArray = (x: number, y: number) => MakeEmptyArray(y).map(() => MakeEmptyArray(x));
// solution code
type v2 = [x: number, y: number];
const Sub = (x1: number, y1: number, x2: number, y2: number): v2 => {
return [x1 - x2, y1 - y2];
}
const Add = (x1: number, y1: number, x2: number, y2: number): v2 => {
return [x1 + x2, y1 + y2];
}
export const solution_8: AdventOfCodeSolutionFunction = (input) => {
const grid = makeGridFromMultilineString(input);
const nodes = new Map<string, Array<v2>>();
const nodeKinds: Array<string> = [];
const singleAntinodeLocations = MakeEmpty2DArray(grid.length, grid[0].length);
const resonantAntinodeLocations = MakeEmpty2DArray(grid.length, grid[0].length);
// find all the nodes
grid.forEach((row, y) => row.forEach((item, x) => {
if (item == ".")
return;
if (nodes.has(item))
nodes.get(item)!.push([x, y]);
else {
nodes.set(item, [[x, y]]);
nodeKinds.push(item);
}
}));
nodeKinds.forEach((nodeKind) => {
const nodesOfKind = nodes.get(nodeKind)!;
for (let bunn = 0; bunn < nodesOfKind.length; bunn++) {
const first = nodesOfKind[bunn];
for (let tort = bunn + 1; tort < nodesOfKind.length; tort++) {
// find antinode
const second = nodesOfKind[tort];
const diff = Sub(...first, ...second);
const [x1, y1] = Add(...first, ...diff);
const [x2, y2] = Sub(...second, ...diff);
if(!check_coords(singleAntinodeLocations, x1, y1)) singleAntinodeLocations[y1][x1]++;
if(!check_coords(singleAntinodeLocations, x2, y2)) singleAntinodeLocations[y2][x2]++;
// find all resonances
// starting
resonantAntinodeLocations[first[1]][first[0]]++;
resonantAntinodeLocations[second[1]][second[0]]++;
// go forward
let newFirst = [x1, y1] as v2;
while(!check_coords(resonantAntinodeLocations, ...newFirst)) {
let [x, y] = newFirst;
resonantAntinodeLocations[y][x]++;
newFirst = Add(...newFirst, ...diff);
}
// go back
newFirst = [x2, y2] as v2;
while(!check_coords(resonantAntinodeLocations, ...newFirst)) {
let [x, y] = newFirst;
resonantAntinodeLocations[y][x]++;
newFirst = Sub(...newFirst, ...diff);
}
}
}
});
const antinodeCount = (prev: number, curr: Array<number>) => prev + curr.reduce((prev, curr) => prev + (curr > 0 ? 1 : 0), 0);
const part_1 = singleAntinodeLocations.reduce<number>(antinodeCount, 0);
const part_2 = resonantAntinodeLocations.reduce<number>(antinodeCount, 0);
return {
part_1, //390
part_2, //1246
}
}
Loops on loops on loops on loops…
I wrote my own iterator because I’m a big dummy. Also brute forced (~8s). Might be worth adding a cache to skip all the questions that have been computed / done.
import { AdventOfCodeSolutionFunction } from "./solutions";
function MakeCombination<T>(choices: Array<T>, state: Array<number>): Array<T> {
return state.map((v) => choices[v]);
}
function MakeStateArray(length: number) {
const newArray = [];
while (length-- > 0)
newArray.push(0);
return newArray;
}
function IncrementState(state: Array<number>, max: number): [state: Array<number>, overflow: boolean] {
state[0]++;
for (let index = 0; index < state.length; index++) {
if (state[index] == max) {
state[index] = 0;
if (index + 1 == state.length)
return [state, true];
state[index + 1]++;
}
}
return [state, false];
}
function GenerateCombinations<T>(choices: Array<T>, length: number): Array<Array<T>> {
const states = MakeStateArray(length);
const combinations: Array<Array<T>> = [];
let done = false
while (!done) {
combinations.push(MakeCombination(choices, states));
done = IncrementState(states, choices.length)[1];
}
return combinations;
}
enum Op {
MUL = "*",
ADD = "+",
CON = "|",
}
function ApplyOp(a: number, b: number, op: Op): number {
switch (op) {
case Op.MUL:
return a * b;
case Op.ADD:
return a + b;
case Op.CON:
return Number(`${a}${b}`);
}
}
function ApplyOperatorsToNumbers(numbers: Array<number>, ops: Array<Op>): number {
let prev = ApplyOp(numbers[0], numbers[1], ops[0]);
for (let index = 2; index < numbers.length; index++) {
prev = ApplyOp(prev, numbers[index], ops[index - 1])
}
return prev;
}
export const solution_7: AdventOfCodeSolutionFunction = (input) => {
const numbers = // [{target: 123, numbers: [1, 2, 3, ...]}, ...]
input.split("\n")
.map(
(v) => v.trim()
.split(":")
.map(v => v.trim().split(" ").map(v => Number(v)))
).map(
(v) => {
return { target: v[0][0], numbers: v[1] }
}
);
let part_1 = 0;
let part_2 = 0;
for (let index = 0; index < numbers.length; index++) {
const target = numbers[index].target;
const numbs = numbers[index].numbers;
// GenerateCombinations(["+", "*"], 2) => [["+", "+"], ["+", "*"], ["*", "+"], ["*", "*"]]
const combinations = GenerateCombinations([Op.ADD, Op.MUL], numbs.length - 1);
// part 1 calculations
for (let combinationIndex = 0; combinationIndex < combinations.length; combinationIndex++) {
const combination = combinations[combinationIndex];
const result = ApplyOperatorsToNumbers(numbs, combination);
if (result == target) {
part_1 += result;
break;
}
}
const combinations2 = GenerateCombinations([Op.ADD, Op.MUL, Op.CON], numbs.length - 1);
// part 2 calculations
for (let combinationIndex = 0; combinationIndex < combinations2.length; combinationIndex++) {
const combination = combinations2[combinationIndex];
const result = ApplyOperatorsToNumbers(numbs, combination);
if (result == target) {
part_2 += result;
break;
}
}
}
return {
part_1,
part_2,
}
}
I actually didn’t know about these apps. very nice
import { AdventOfCodeSolutionFunction } from "./solutions";
export const check_coords = (grid: Grid, x: number, y: number) => {
return y >= grid.length ||
y < 0 ||
x >= grid[y].length ||
x < 0
}
export enum Direction {
UP,
UP_RIGHT,
RIGHT,
BOTTOM_RIGHT,
BOTTOM,
BOTTOM_LEFT,
LEFT,
UP_LEFT,
};
/**
* This function should return true if it wants the search function to continue
*/
export type SearchFindFunction = (currChar: string, x: number, y: number) => boolean;
export type Grid = Array<Array<string>>;
export enum SearchExitReason {
OUT_OF_BOUNDS,
FUNCTION_FINISHED,
INVALID_DIRECTION,
}
export const search_direction = (grid: Grid, x: number, y: number, direction: Direction, find: SearchFindFunction): SearchExitReason => {
// invalid coords
if (check_coords(grid, x, y))
return SearchExitReason.OUT_OF_BOUNDS;
// search failed
if (!find(grid[y][x], x, y))
return SearchExitReason.FUNCTION_FINISHED;
switch (direction) {
case Direction.UP:
return search_direction(grid, x, y - 1, direction, find);
case Direction.UP_RIGHT:
return search_direction(grid, x + 1, y - 1, direction, find);
case Direction.RIGHT:
return search_direction(grid, x + 1, y, direction, find);
case Direction.BOTTOM_RIGHT:
return search_direction(grid, x + 1, y + 1, direction, find);
case Direction.BOTTOM:
return search_direction(grid, x, y + 1, direction, find);
case Direction.BOTTOM_LEFT:
return search_direction(grid, x - 1, y + 1, direction, find);
case Direction.LEFT:
return search_direction(grid, x - 1, y, direction, find);
case Direction.UP_LEFT:
return search_direction(grid, x - 1, y - 1, direction, find);
default:
return SearchExitReason.INVALID_DIRECTION;
}
}
export const gridSearch = (grid: Grid, st: SearchFindFunction): [x: number, y: number] => {
for (let y = 0; y < grid.length; y++) {
const row = grid[y];
for (let x = 0; x < row.length; x++) {
const char = row[x];
if (!st(char, x, y))
return [x, y];
}
}
return [-1, -1];
}
export const makeGridFromMultilineString =
(input: string) => input.split("\n").map(st => st.trim()).map(v => v.split(""));
export const Duplicate2DArray = <T>(array: Array<Array<T>>) => {
return [...array.map((item) => [...item])];
}
const NextDirection = (dir: Direction) => {
switch (dir) {
case Direction.UP:
return Direction.RIGHT;
case Direction.RIGHT:
return Direction.BOTTOM;
case Direction.BOTTOM:
return Direction.LEFT;
case Direction.LEFT:
return Direction.UP;
default:
throw Error("Invalid direction");
}
}
/**
* @returns true if there are no loops
*/
const NoLoops = (grid: Grid, x: number, y: number, dir: Direction) => {
const visited = new Set<string>();
/**
* @returns True if not visited yet
*/
const addToVisited = (x: number, y: number, dir: Direction) => {
const log = `${x}:${y}:${dir}`;
if (visited.has(log))
return false;
visited.add(log);
return true;
}
let searchResult: SearchExitReason = SearchExitReason.FUNCTION_FINISHED;
let res = true;
let i = 0; // rate limited for API
let [lastX, lastY] = [x, y];
while (searchResult !== SearchExitReason.OUT_OF_BOUNDS && i++ < 10_000) {
searchResult = search_direction(grid, lastX, lastY, dir, (ch, currX, currY) => {
if (ch == "#")
return false;
[lastX, lastY] = [currX, currY];
res = addToVisited(currX, currY, dir);
return res;
});
if (!res)
break;
dir = NextDirection(dir);
}
return res;
}
export const solution_6: AdventOfCodeSolutionFunction = (input) => {
const grid = makeGridFromMultilineString(input);
const visited = new Map<string, [x: number, y: number, dir: Direction, prevX: number, prevY: number]>();
let [x, y] = gridSearch(grid, (ch) => ch !== "^");
const [initialX, initialY] = [x, y];
let dir: Direction = Direction.UP;
const addToVisited = (visitedX: number, visitedY: number, dir: Direction) => {
const loc = `${visitedX}:${visitedY}`;
if (!visited.has(loc))
visited.set(loc, [visitedX, visitedY, dir, x, y]);
}
addToVisited(x, y, dir);
let res: SearchExitReason = SearchExitReason.FUNCTION_FINISHED;
let i = 0; // rate limited for API
while (res !== SearchExitReason.OUT_OF_BOUNDS && i++ < 10_000) {
res = search_direction(grid, x, y, dir, (ch, currX, currY) => {
if (ch == "#")
return false;
addToVisited(currX, currY, dir);
[x, y] = [currX, currY];
return true;
});
dir = NextDirection(dir);
}
const part_1 = visited.size;
// remove starting position for part 1
visited.delete(`${initialX}:${initialY}`);
let part_2 = 0;
visited.forEach((v) => {
const [visitedX, visitedY, visitedDirection, prevX, prevY] = v;
const newGrid = Duplicate2DArray(grid);
newGrid[visitedY][visitedX] = "#"; // add a block
// look for loops
if (!NoLoops(newGrid, prevX, prevY, visitedDirection))
part_2++;
});
return {
part_1, // 4656
part_2, // 1575
}
}
I’m so surprised this runs in ~3s, expected it to take like 60s (do I have supercomputer?). Solution was similar to Pyro’s in this thread as in it simulates the walk then places an obstacle in every possible position but I speed it up by starting just before the obstacle and looking towards it. Also, I reused some code from day 4 by tweaking it slightly. Thank you for the “S” tire Advent of Code puzzle. :)
honestly, if it wasn’t so piss easy to write, i wouldn’t use it at all