From 7fce7f6de16f3566d08fcf532399920c571d1c8f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:01:16 +0000 Subject: [PATCH 1/5] Update visuals/github-metrics.svg - [Skip GitHub Action] --- visuals/github-metrics.svg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/visuals/github-metrics.svg b/visuals/github-metrics.svg index 44a167b..0b0aa8c 100644 --- a/visuals/github-metrics.svg +++ b/visuals/github-metrics.svg @@ -21,10 +21,10 @@ - - - - + + + +
@@ -54,7 +54,7 @@
- Last updated 27 Nov 2024, 10:31:03 with lowlighter/metrics@3.34.0 + Last updated 27 Nov 2024, 12:01:11 with lowlighter/metrics@3.34.0
From 096ee80bfe2a7299dc58a69a5bbfde8aae308b80 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:01:25 +0000 Subject: [PATCH 2/5] Update visuals/github-metrics-2023.svg - [Skip GitHub Action] --- visuals/github-metrics-2023.svg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/visuals/github-metrics-2023.svg b/visuals/github-metrics-2023.svg index 923e84b..fecc5ba 100644 --- a/visuals/github-metrics-2023.svg +++ b/visuals/github-metrics-2023.svg @@ -21,9 +21,9 @@ - - - + + +
@@ -47,7 +47,7 @@
- Last updated 27 Nov 2024, 10:31:03 with lowlighter/metrics@3.34.0 + Last updated 27 Nov 2024, 12:01:12 with lowlighter/metrics@3.34.0
From 74e82d81c7ac9e09b688544441c61591bc26f0af Mon Sep 17 00:00:00 2001 From: Alex | Kronox Date: Wed, 27 Nov 2024 19:34:11 +0100 Subject: [PATCH 3/5] 2021 23,24 --- 2021/23/task.ts | 407 ++++++++++++++++++++++++++++++++++-------------- 2021/24/task.ts | 164 ++++++------------- 2 files changed, 338 insertions(+), 233 deletions(-) diff --git a/2021/23/task.ts b/2021/23/task.ts index 404445d..87d04db 100644 --- a/2021/23/task.ts +++ b/2021/23/task.ts @@ -1,4 +1,4 @@ -import {Stack} from '../../base/simpleStructure' +import { Stack } from '../../base/simpleStructure' export async function taskOne(input: string[]): Promise { const initial: State = { @@ -12,27 +12,9 @@ export async function taskOne(input: string[]): Promise { ] } - const toGoalMap = new Map() - //const lastVisitedEnergy = new Map() - - const t = { - walkWay: [ - null, 'A', null, - null, null, 'B', - null, null, null, - null, null - ], - energy: 50, - holes: [ - { bottom: 'A' }, - { top: undefined, bottom: 'B' }, - { top: 'C', bottom: 'C' }, - { top: 'D', bottom: 'D' } - ] - } as State + console.log(step(initial)) - //console.log(toGoalMap) function step(q: State) { const key = getKey(q) @@ -48,11 +30,6 @@ export async function taskOne(input: string[]): Promise { let minAdd = Infinity for (const s of nextSteps) { let v = s.energy - q.energy + step(s) - if (s.energy - q.energy < 0) { - console.log(q) - console.log(s) - throw "ner" - } if (v < minAdd) minAdd = v } toGoalMap.set(key, minAdd) @@ -60,6 +37,112 @@ export async function taskOne(input: string[]): Promise { } + + interface State { + walkWay: (string|undefined)[] + holes: Hole[] + energy: number + } + + interface Hole { + bottom?: string + top?: string + } + + const walkWayAllowed = [true, true, false, true, false, true, false, true, false, true, true] + const goalHoles = {'A':0,'B':1,'C':2,'D':3} as Record + const energy = {'A':1,'B':10,'C':100,'D':1000} as Record + const holeEntry = [2,4,6,8] + const desiredAmphipot = ['A','B','C','D'] + + function getNextStates(state: State): State[] { + const newStates: State[] = [] + + // Check if anyone can go in their hole + for (let i = 0; i < state.walkWay.length; i++) { + if (state.walkWay[i] == undefined) continue + const amphipot = state.walkWay[i]! + const goalHole = goalHoles[amphipot] + + // if there is another amphipot in any position in the hole, we can not fill it + if (state.holes[goalHole].top != undefined && state.holes[goalHole].top != amphipot) continue + if (state.holes[goalHole].bottom != undefined && state.holes[goalHole].bottom != amphipot) continue + + // Check that way is free + const goalHoleEntry = holeEntry[goalHole] + const dir = Math.sign(goalHoleEntry-i) + let canGo = true; + for (let j = i +dir; j != goalHoleEntry; j += dir) { + if (state.walkWay[j] != undefined) canGo = false + } + if(!canGo) continue + + const copy = copyV(state) + // if bottom hole is free use bottom hole + if (state.holes[goalHole].bottom == undefined) { + copy.holes[goalHole].bottom = amphipot + copy.energy += 2 * energy[amphipot] + } else { + copy.holes[goalHole].top = amphipot + copy.energy += 1 * energy[amphipot] + } + copy.walkWay[i] = undefined + copy.energy += Math.abs(i - goalHoleEntry) * energy[amphipot] + newStates.push(copy) + } + + // Check if they can leave hole + for (let i = 0; i < state.holes.length; i++) { + //skip empty holes + if (state.holes[i].bottom == undefined && state.holes[i].top == undefined) continue + + // skip if in correct hole + if (state.holes[i].top == undefined) { + if (state.holes[i].bottom == desiredAmphipot[i]) continue + } else { + if (state.holes[i].top == desiredAmphipot[i] && state.holes[i].bottom == desiredAmphipot[i]) continue + } + + // walk left from hole + const possibleGoals: number[] = [] + for (let j = holeEntry[i]; j < walkWayAllowed.length; j++) { + if (state.walkWay[j] != undefined) break + if (!walkWayAllowed[j]) continue + possibleGoals.push(j) + } + for (let j = holeEntry[i]; j >= 0; j--) { + if (state.walkWay[j] != undefined) break + if (!walkWayAllowed[j]) continue + possibleGoals.push(j) + } + for (const goal of possibleGoals) { + const copy = copyV(state) + let amphipot = '' + if (copy.holes[i].top != undefined) { + amphipot = copy.holes[i].top! + copy.holes[i].top = undefined + copy.energy += 1 * energy[amphipot] + } else { + amphipot = copy.holes[i].bottom! + copy.holes[i].bottom = undefined + copy.energy += 2 * energy[amphipot] + } + copy.walkWay[goal] = amphipot + copy.energy += Math.abs(holeEntry[i] - goal) * energy[amphipot] + newStates.push(copy) + } + } + return newStates + } + + function isFinal(state: State): boolean { + for (let i = 0; i < state.holes.length; i++) { + if (state.holes[i].top != desiredAmphipot[i]) return false + if (state.holes[i].bottom != desiredAmphipot[i]) return false + } + return true + } + function getKey(s: State) { return JSON.stringify({w:s.walkWay, h:s.holes}) } @@ -67,114 +150,208 @@ export async function taskOne(input: string[]): Promise { } export async function taskTwo(input: string[]): Promise { - console.log("Unimplemented"); -} + const initial: State = { + walkWay: Array.from({length: 11}, () => undefined), + energy: 0, + holes: [ + [input[2][3], 'D', 'D', input[3][3]], + [input[2][5], 'C', 'B', input[3][5]], + [input[2][7], 'B', 'A', input[3][7]], + [input[2][9], 'A', 'C', input[3][9]], + ] + } -interface State { - walkWay: (string|undefined)[] - holes: Hole[] - energy: number -} -interface Hole { - bottom?: string - top?: string -} + const toGoalMap = new Map() + + const walkWayAllowed = [true, true, false, true, false, true, false, true, false, true, true] + const goalHoles = {'A':0,'B':1,'C':2,'D':3} as Record + const energy = {'A':1,'B':10,'C':100,'D':1000} as Record + const holeEntry = [2,4,6,8] + const desiredAmphipot = ['A','B','C','D'] + + //console.log(step(initial)) + + const Q = new Stack() + Q.push(initial) + let curMin = Infinity + + while(!Q.isEmpty()) { + const q = Q.pop() + if (q.energy > curMin) continue -const walkWayAllowed = [true, true, false, true, false, true, false, true, false, true, true] -const goalHoles = {'A':0,'B':1,'C':2,'D':3} as Record -const energy = {'A':1,'B':10,'C':100,'D':1000} as Record -const holeEntry = [2,4,6,8] -const desiredAmphipot = ['A','B','C','D'] - -function getNextStates(state: State): State[] { - const newStates: State[] = [] - - // Check if anyone can go in their hole - for (let i = 0; i < state.walkWay.length; i++) { - if (state.walkWay[i] == undefined) continue - const amphipot = state.walkWay[i]! - const goalHole = goalHoles[amphipot] - - // if there is another amphipot in any position in the hole, we can not fill it - if (state.holes[goalHole].top != undefined && state.holes[goalHole].top != amphipot) continue - if (state.holes[goalHole].bottom != undefined && state.holes[goalHole].bottom != amphipot) continue - - // Check that way is free - const goalHoleEntry = holeEntry[goalHole] - const dir = Math.sign(goalHoleEntry-i) - let canGo = true; - for (let j = i +dir; j != goalHoleEntry; j += dir) { - if (state.walkWay[j] != undefined) canGo = false + const key = getKey(q) + if (toGoalMap.has(key)) { + const old = toGoalMap.get(key)! + if (old <= q.energy) { + continue + } else { + toGoalMap.set(key, q.energy) + } + } + if (isFinal(q)) { + const total = q.energy + console.log('final', total) + if (total < curMin) { + toGoalMap.set(key, total) + curMin = total + } + continue } - if(!canGo) continue - - const copy = copyV(state) - // if bottom hole is free use bottom hole - if (state.holes[goalHole].bottom == undefined) { - copy.holes[goalHole].bottom = amphipot - copy.energy += 2 * energy[amphipot] - } else { - copy.holes[goalHole].top = amphipot - state.energy += 1 * energy[amphipot] + if (q.energy + heruristic(q) > curMin) continue + + const nextSteps = getNextStates(q) + for (const s of nextSteps) { + Q.push(s) } - copy.walkWay[i] = undefined - copy.energy += Math.abs(i - goalHoleEntry) * energy[amphipot] - newStates.push(copy) } - // Check if they can leave hole - for (let i = 0; i < state.holes.length; i++) { - //skip empty holes - if (state.holes[i].bottom == undefined && state.holes[i].top == undefined) continue + console.log(curMin) - // skip if in correct hole - if (state.holes[i].top == undefined) { - if (state.holes[i].bottom == desiredAmphipot[i]) continue - } else { - if (state.holes[i].top == desiredAmphipot[i] && state.holes[i].bottom == desiredAmphipot[i]) continue - } + interface State { + walkWay: (string|undefined)[] + holes: (string|undefined)[][] + energy: number + } - // walk left from hole - const possibleGoals: number[] = [] - for (let j = holeEntry[i]; j < walkWayAllowed.length; j++) { - if (state.walkWay[j] != undefined) break - if (!walkWayAllowed[j]) continue - possibleGoals.push(j) - } - for (let j = holeEntry[i]; j >= 0; j--) { - if (state.walkWay[j] != undefined) break - if (!walkWayAllowed[j]) continue - possibleGoals.push(j) - } - for (const goal of possibleGoals) { + + function getNextStates(state: State): State[] { + const newStates: State[] = [] + + // Check if anyone can go in their hole + for (let i = 0; i < state.walkWay.length; i++) { + if (state.walkWay[i] == undefined) continue + const amphipot = state.walkWay[i]! + const goalHole = goalHoles[amphipot] + + // if there is another amphipot in any position in the hole, we can not fill it + let foundWrongAmphi = false + for (let d = 0; d < state.holes[goalHole].length; d++) { + if (state.holes[goalHole][d] != undefined && state.holes[goalHole][d] != amphipot) { + foundWrongAmphi = true + break + } + } + if (foundWrongAmphi) continue + + // Check that way is free + const goalHoleEntry = holeEntry[goalHole] + const dir = Math.sign(goalHoleEntry-i) + let canGo = true; + for (let j = i +dir; j != goalHoleEntry; j += dir) { + if (state.walkWay[j] != undefined) canGo = false + } + if(!canGo) continue + const copy = copyV(state) - let amphipot = '' - if (copy.holes[i].top != undefined) { - amphipot = copy.holes[i].top! - copy.holes[i].top = undefined - copy.energy += 1 * energy[amphipot] - } else { - amphipot = copy.holes[i].bottom! - copy.holes[i].bottom = undefined - copy.energy += 2 * energy[amphipot] + // find lowest free hole + for (let d = 3; d >= 0; d--) { + if (state.holes[goalHole][d] == undefined) { + copy.holes[goalHole][d] = amphipot + copy.energy += (d+1) * energy[amphipot] + break; + } } - copy.walkWay[goal] = amphipot - copy.energy += Math.abs(holeEntry[i] - goal) * energy[amphipot] + copy.walkWay[i] = undefined + copy.energy += Math.abs(i - goalHoleEntry) * energy[amphipot] newStates.push(copy) } + + // Check if they can leave hole + for (let i = 0; i < state.holes.length; i++) { + //skip empty holes + let foundAmphi = false + for (let d = 0; d < state.holes[i].length; d++) { + if (state.holes[i][d] != undefined) { + foundAmphi = true + break + } + } + if (!foundAmphi) continue + + // skip if in correct hole + let allCorrect = true + for (let d = 0; d < state.holes[i].length; d++) { + if (state.holes[i][d] != undefined && state.holes[i][d] != desiredAmphipot[i]) { + allCorrect = false + break + } + } + if (allCorrect) continue + + // walk left from hole + const possibleGoals: number[] = [] + for (let j = holeEntry[i]; j < walkWayAllowed.length; j++) { + if (state.walkWay[j] != undefined) break + if (!walkWayAllowed[j]) continue + possibleGoals.push(j) + } + for (let j = holeEntry[i]; j >= 0; j--) { + if (state.walkWay[j] != undefined) break + if (!walkWayAllowed[j]) continue + possibleGoals.push(j) + } + for (const goal of possibleGoals) { + const copy = copyV(state) + let amphipot = '' + // Move top most ampiphod + for (let d = 0; d < state.holes[i].length; d++) { + if (state.holes[i][d] != undefined) { + amphipot = state.holes[i][d]! + copy.holes[i][d] = undefined + copy.energy += (d+1) * energy[amphipot] + break + } + } + + copy.walkWay[goal] = amphipot + copy.energy += Math.abs(holeEntry[i] - goal) * energy[amphipot] + newStates.push(copy) + } + } + return newStates + } + + function isFinal(state: State): boolean { + for (let i = 0; i < state.holes.length; i++) { + for (let d = 0; d < state.holes[i].length; d++) { + if (state.holes[i][d] != desiredAmphipot[i]) return false + } + } + return true } - return newStates -} -function isFinal(state: State): boolean { - for (let i = 0; i < state.holes.length; i++) { - if (state.holes[i].top != desiredAmphipot[i]) return false - if (state.holes[i].bottom != desiredAmphipot[i]) return false + function getKey(s: State) { + return JSON.stringify({w:s.walkWay, h:s.holes}) + } + + function heruristic(state: State) { + const theoryWalkway = walkWayAllowed.map(i=>[]as string[]) + let h = 0 + for (let i = 0; i < state.walkWay.length; i++) { + if (state.walkWay[i] != undefined) theoryWalkway[i].push(state.walkWay[i]!) + } + for (let i = 0; i < state.holes.length; i++) { + for (let d = 0; d < state.holes[i].length; d++) { + let a = state.holes[i][d] + if (a != undefined) { + if(goalHoles[a] == i) continue + theoryWalkway[holeEntry[i]].push(a) + h += (d+1)*energy[a] + } + } + } + + for (let i = 0; i < state.walkWay.length; i++) { + for (const a of theoryWalkway[i]) { + h += Math.abs(i - holeEntry[goalHoles[a]]) * energy[a] + } + } + return h } - return true } + function copyV(v:T):T { return JSON.parse(JSON.stringify(v)) } \ No newline at end of file diff --git a/2021/24/task.ts b/2021/24/task.ts index 0faa3c1..cb05937 100644 --- a/2021/24/task.ts +++ b/2021/24/task.ts @@ -1,129 +1,57 @@ export async function taskOne(input: string[]): Promise { - const ins = input.map(i => i.split(' ')) - - const badStates = new Set() - console.log(run(0, {'w':0,'x':0,'y':0,'z':0})) - - function run(i: number, register: Record): string|false { - const k = i + "|" + register['z'] + "|" + register['w'] - if (badStates.has(k)) { - return false - } - - while(i < ins.length) { - const task = ins[i][0] - if (task == 'inp') { - for (const n of [9,8,7,6,5,4,3,2,1]) { - register[ins[i][1]] = n - const r = run(i+1, copyReg(register)) - if (r === false) continue - else { - return `${n}${r}` - } - } - badStates.add(k) - return false - } else { - const a = ins[i][1] - const b = ins[i][2] - if (task == 'add') { - register[a] += get(b) - } else if (task == 'mul') { - register[a] *= get(b) - } else if (task == 'mod') { - register[a] %= get(b) - } else if (task == 'div') { - register[a] = Math.floor(get(a) / get(b)) - } else if (task == 'eql') { - register[a] = get(a) == get(b) ? 1:0 - } else { - throw i - } - i++ - } - } - if (register['z'] != 0) { - return false - } - return '' - - function get(x: string) { - if (x.match(/[wxyz]/)) { - return register[x] - } else { - return Number(x) - } - } - } - - function copyReg(reg: Record) { - return { - 'w': reg['w'],'x': reg['x'],'y': reg['y'],'z': reg['z'] - } - } + task(input, [9,8,7,6,5,4,3,2,1]) } - export async function taskTwo(input: string[]): Promise { - const ins = input.map(i => i.split(' ')) + task(input, [1,2,3,4,5,6,7,8,9]) +} - const badStates = new Set() - console.log(run(0, {'w':0,'x':0,'y':0,'z':0})) +export async function task(input: string[], order: number[]) { + const xAdds = [] as number[] + const yAdds = [] as number[] + const zDivs = [] as number[] - function run(i: number, register: Record): string|false { - const k = i + "|" + register['z'] + "|" + register['w'] - if (badStates.has(k)) { - return false - } + for (let d = 0; d < 14; d++) { + zDivs.push(Number(input[d*18+4].split(' ')[2])) + xAdds.push(Number(input[d*18+5].split(' ')[2])) + yAdds.push(Number(input[d*18+15].split(' ')[2])) + } + console.log(xAdds, yAdds, zDivs) - while(i < ins.length) { - const task = ins[i][0] - if (task == 'inp') { - for (const n of [1,2,3,4,5,6,7,8,9]) { - register[ins[i][1]] = n - const r = run(i+1, copyReg(register)) - if (r === false) continue - else { - return `${n}${r}` - } - } - badStates.add(k) - return false - } else { - const a = ins[i][1] - const b = ins[i][2] - if (task == 'add') { - register[a] += get(b) - } else if (task == 'mul') { - register[a] *= get(b) - } else if (task == 'mod') { - register[a] %= get(b) - } else if (task == 'div') { - register[a] = Math.floor(get(a) / get(b)) - } else if (task == 'eql') { - register[a] = get(a) == get(b) ? 1:0 - } else { - throw i - } - i++ - } - } - if (register['z'] != 0) { - return false - } - return '' - - function get(x: string) { - if (x.match(/[wxyz]/)) { - return register[x] - } else { - return Number(x) + const badStates = new Set() + console.log(run(0, 0, 0)) + + function run(depth: number, curTotal: number, lastZ: number): number|false { + if (depth >= 14) return lastZ == 0 ? curTotal:false + const k = key(depth, lastZ) + if(badStates.has(k)) return false + const t = curTotal * 10 + + for (const i of order) { + let w = i + let z = lastZ + let x = z + x %= 26 + z = Math.floor(z / zDivs[depth]) + x += xAdds[depth] + x = x == w ? 0:1 + let y = 25 + y *= x + y += 1 + z *= y + y = w + yAdds[depth] + y *= x + z += y + + const r = run(depth+1, t+i, z) + if(r !== false) { + return r } } + badStates.add(k) + return false } - function copyReg(reg: Record) { - return { - 'w': reg['w'],'x': reg['x'],'y': reg['y'],'z': reg['z'] - } - } + function key(...n: number[]) { + return n.join('|') + } } \ No newline at end of file From 2fa87aa4aa1b0b07314a939f654cce5af8a6e72a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 27 Nov 2024 18:35:20 +0000 Subject: [PATCH 4/5] Update visuals/github-metrics.svg - [Skip GitHub Action] --- visuals/github-metrics.svg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/visuals/github-metrics.svg b/visuals/github-metrics.svg index 0b0aa8c..45c970d 100644 --- a/visuals/github-metrics.svg +++ b/visuals/github-metrics.svg @@ -21,10 +21,10 @@ - - - - + + + +
@@ -54,7 +54,7 @@
- Last updated 27 Nov 2024, 12:01:11 with lowlighter/metrics@3.34.0 + Last updated 27 Nov 2024, 19:35:15 with lowlighter/metrics@3.34.0
From cbfaf07dd078cff2e8f8a08cd20c3301c9e1dacd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 27 Nov 2024 18:35:29 +0000 Subject: [PATCH 5/5] Update visuals/github-metrics-2023.svg - [Skip GitHub Action] --- visuals/github-metrics-2023.svg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/visuals/github-metrics-2023.svg b/visuals/github-metrics-2023.svg index fecc5ba..c2535ad 100644 --- a/visuals/github-metrics-2023.svg +++ b/visuals/github-metrics-2023.svg @@ -21,9 +21,9 @@ - - - + + +
@@ -47,7 +47,7 @@
- Last updated 27 Nov 2024, 12:01:12 with lowlighter/metrics@3.34.0 + Last updated 27 Nov 2024, 19:35:18 with lowlighter/metrics@3.34.0