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 @@
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 @@
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 @@
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 @@