aoc 6+7+8+9
This commit is contained in:
parent
7998f74810
commit
1fa48259cf
106
www/statics/aoc/2019/06_challenge.txt
Normal file
106
www/statics/aoc/2019/06_challenge.txt
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
--- Day 6: Universal Orbit Map ---
|
||||||
|
|
||||||
|
You've landed at the Universal Orbit Map facility on Mercury. Because navigation in space often involves transferring between orbits, the orbit maps here are useful for finding efficient routes between, for example, you and Santa. You download a map of the local orbits (your puzzle input).
|
||||||
|
|
||||||
|
Except for the universal Center of Mass (COM), every object in space is in orbit around exactly one other object. An orbit looks roughly like this:
|
||||||
|
|
||||||
|
\
|
||||||
|
\
|
||||||
|
|
|
||||||
|
|
|
||||||
|
AAA--> o o <--BBB
|
||||||
|
|
|
||||||
|
|
|
||||||
|
/
|
||||||
|
/
|
||||||
|
|
||||||
|
In this diagram, the object BBB is in orbit around AAA. The path that BBB takes around AAA (drawn with lines) is only partly shown. In the map data, this orbital relationship is written AAA)BBB, which means "BBB is in orbit around AAA".
|
||||||
|
|
||||||
|
Before you use your map data to plot a course, you need to make sure it wasn't corrupted during the download. To verify maps, the Universal Orbit Map facility uses orbit count checksums - the total number of direct orbits (like the one shown above) and indirect orbits.
|
||||||
|
|
||||||
|
Whenever A orbits B and B orbits C, then A indirectly orbits C. This chain can be any number of objects long: if A orbits B, B orbits C, and C orbits D, then A indirectly orbits D.
|
||||||
|
|
||||||
|
For example, suppose you have the following map:
|
||||||
|
|
||||||
|
COM)B
|
||||||
|
B)C
|
||||||
|
C)D
|
||||||
|
D)E
|
||||||
|
E)F
|
||||||
|
B)G
|
||||||
|
G)H
|
||||||
|
D)I
|
||||||
|
E)J
|
||||||
|
J)K
|
||||||
|
K)L
|
||||||
|
|
||||||
|
Visually, the above map of orbits looks like this:
|
||||||
|
|
||||||
|
G - H J - K - L
|
||||||
|
/ /
|
||||||
|
COM - B - C - D - E - F
|
||||||
|
\
|
||||||
|
I
|
||||||
|
|
||||||
|
In this visual representation, when two objects are connected by a line, the one on the right directly orbits the one on the left.
|
||||||
|
|
||||||
|
Here, we can count the total number of orbits as follows:
|
||||||
|
|
||||||
|
D directly orbits C and indirectly orbits B and COM, a total of 3 orbits.
|
||||||
|
L directly orbits K and indirectly orbits J, E, D, C, B, and COM, a total of 7 orbits.
|
||||||
|
COM orbits nothing.
|
||||||
|
|
||||||
|
The total number of direct and indirect orbits in this example is 42.
|
||||||
|
|
||||||
|
What is the total number of direct and indirect orbits in your map data?
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
Now, you just need to figure out how many orbital transfers you (YOU) need to take to get to Santa (SAN).
|
||||||
|
|
||||||
|
You start at the object YOU are orbiting; your destination is the object SAN is orbiting. An orbital transfer lets you move from any object to an object orbiting or orbited by that object.
|
||||||
|
|
||||||
|
For example, suppose you have the following map:
|
||||||
|
|
||||||
|
COM)B
|
||||||
|
B)C
|
||||||
|
C)D
|
||||||
|
D)E
|
||||||
|
E)F
|
||||||
|
B)G
|
||||||
|
G)H
|
||||||
|
D)I
|
||||||
|
E)J
|
||||||
|
J)K
|
||||||
|
K)L
|
||||||
|
K)YOU
|
||||||
|
I)SAN
|
||||||
|
|
||||||
|
Visually, the above map of orbits looks like this:
|
||||||
|
|
||||||
|
YOU
|
||||||
|
/
|
||||||
|
G - H J - K - L
|
||||||
|
/ /
|
||||||
|
COM - B - C - D - E - F
|
||||||
|
\
|
||||||
|
I - SAN
|
||||||
|
|
||||||
|
In this example, YOU are in orbit around K, and SAN is in orbit around I. To move from K to I, a minimum of 4 orbital transfers are required:
|
||||||
|
|
||||||
|
K to J
|
||||||
|
J to E
|
||||||
|
E to D
|
||||||
|
D to I
|
||||||
|
|
||||||
|
Afterward, the map of orbits looks like this:
|
||||||
|
|
||||||
|
G - H J - K - L
|
||||||
|
/ /
|
||||||
|
COM - B - C - D - E - F
|
||||||
|
\
|
||||||
|
I - SAN
|
||||||
|
\
|
||||||
|
YOU
|
||||||
|
|
||||||
|
What is the minimum number of orbital transfers required to move from the object YOU are orbiting to the object SAN is orbiting? (Between the objects they are orbiting - not between YOU and SAN.)
|
1860
www/statics/aoc/2019/06_input.txt
Normal file
1860
www/statics/aoc/2019/06_input.txt
Normal file
File diff suppressed because it is too large
Load Diff
71
www/statics/aoc/2019/06_solution-1.ts
Normal file
71
www/statics/aoc/2019/06_solution-1.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
namespace AdventOfCode2019_06_1
|
||||||
|
{
|
||||||
|
const DAY = 6;
|
||||||
|
const PROBLEM = 1;
|
||||||
|
|
||||||
|
class Body
|
||||||
|
{
|
||||||
|
name: string;
|
||||||
|
children: Body[] = [];
|
||||||
|
parent: Body|null = null;
|
||||||
|
|
||||||
|
constructor(n: string) { this.name = n; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class StellarSystem
|
||||||
|
{
|
||||||
|
com: Body;
|
||||||
|
bodies: { [key:string]:Body } = {};
|
||||||
|
|
||||||
|
constructor() { this.com = new Body("COM"); this.bodies["COM"] = this.com; }
|
||||||
|
|
||||||
|
private getOrCreate(name: string): Body
|
||||||
|
{
|
||||||
|
if (name in this.bodies) return this.bodies[name];
|
||||||
|
return this.bodies[name] = new Body(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public add(mastername: string, slavename: string)
|
||||||
|
{
|
||||||
|
const master = this.getOrCreate(mastername);
|
||||||
|
const slave = this.getOrCreate(slavename);
|
||||||
|
|
||||||
|
if (slave.parent !== null) throw "slave already has master";
|
||||||
|
slave.parent = master;
|
||||||
|
|
||||||
|
master.children.push(slave);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getChecksum(): number
|
||||||
|
{
|
||||||
|
return this.calcChecksum(this.com, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private calcChecksum(master: Body, depth: number): number
|
||||||
|
{
|
||||||
|
let r = depth;
|
||||||
|
for (const body of master.children)
|
||||||
|
{
|
||||||
|
r += this.calcChecksum(body, depth+1);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function run()
|
||||||
|
{
|
||||||
|
let input = await AdventOfCode.getInput(DAY);
|
||||||
|
if (input == null) return;
|
||||||
|
|
||||||
|
const data = input
|
||||||
|
.split(new RegExp('\r?\n'))
|
||||||
|
.filter(p => p.trim().length > 0)
|
||||||
|
.map(p => p.split(')'));
|
||||||
|
|
||||||
|
let sys = new StellarSystem();
|
||||||
|
|
||||||
|
for(const dat of data) sys.add(dat[0], dat[1]);
|
||||||
|
|
||||||
|
AdventOfCode.output(DAY, PROBLEM, sys.getChecksum().toString());
|
||||||
|
}
|
||||||
|
}
|
102
www/statics/aoc/2019/06_solution-2.ts
Normal file
102
www/statics/aoc/2019/06_solution-2.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
namespace AdventOfCode2019_06_2
|
||||||
|
{
|
||||||
|
const DAY = 6;
|
||||||
|
const PROBLEM = 2;
|
||||||
|
|
||||||
|
class Body
|
||||||
|
{
|
||||||
|
name: string;
|
||||||
|
children: Body[] = [];
|
||||||
|
parent: Body|null = null;
|
||||||
|
|
||||||
|
constructor(n: string) { this.name = n; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class StellarSystem
|
||||||
|
{
|
||||||
|
com: Body;
|
||||||
|
bodies: { [key:string]:Body } = {};
|
||||||
|
|
||||||
|
constructor() { this.com = new Body("COM"); this.bodies["COM"] = this.com; }
|
||||||
|
|
||||||
|
private getOrCreate(name: string): Body
|
||||||
|
{
|
||||||
|
if (name in this.bodies) return this.bodies[name];
|
||||||
|
return this.bodies[name] = new Body(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public add(mastername: string, slavename: string)
|
||||||
|
{
|
||||||
|
const master = this.getOrCreate(mastername);
|
||||||
|
const slave = this.getOrCreate(slavename);
|
||||||
|
|
||||||
|
if (slave.parent !== null) throw "slave already has master";
|
||||||
|
slave.parent = master;
|
||||||
|
|
||||||
|
master.children.push(slave);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getChecksum(): number
|
||||||
|
{
|
||||||
|
return this.calcChecksum(this.com, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private calcChecksum(master: Body, depth: number): number
|
||||||
|
{
|
||||||
|
let r = depth;
|
||||||
|
for (const body of master.children)
|
||||||
|
{
|
||||||
|
r += this.calcChecksum(body, depth+1);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTransferDistance(ba: string, bb: string)
|
||||||
|
{
|
||||||
|
let dist: { [key:string]:number } = {};
|
||||||
|
|
||||||
|
// From [BA] upwards
|
||||||
|
{
|
||||||
|
let obj = this.bodies[ba].parent;
|
||||||
|
let dctr = 0;
|
||||||
|
while(obj !== null)
|
||||||
|
{
|
||||||
|
dist[obj.name] = dctr;
|
||||||
|
dctr++;
|
||||||
|
obj = obj.parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// From [BB] upwards
|
||||||
|
{
|
||||||
|
let obj = this.bodies[bb].parent;
|
||||||
|
let dctr = 0;
|
||||||
|
while(obj !== null)
|
||||||
|
{
|
||||||
|
if (obj.name in dist) return dctr + dist[obj.name];
|
||||||
|
dctr++;
|
||||||
|
obj = obj.parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1; // no path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function run()
|
||||||
|
{
|
||||||
|
let input = await AdventOfCode.getInput(DAY);
|
||||||
|
if (input == null) return;
|
||||||
|
|
||||||
|
const data = input
|
||||||
|
.split(new RegExp('\r?\n'))
|
||||||
|
.filter(p => p.trim().length > 0)
|
||||||
|
.map(p => p.split(')'));
|
||||||
|
|
||||||
|
let sys = new StellarSystem();
|
||||||
|
|
||||||
|
for(const dat of data) sys.add(dat[0], dat[1]);
|
||||||
|
|
||||||
|
AdventOfCode.output(DAY, PROBLEM, sys.getTransferDistance("YOU", "SAN").toString());
|
||||||
|
}
|
||||||
|
}
|
83
www/statics/aoc/2019/07_challenge.txt
Normal file
83
www/statics/aoc/2019/07_challenge.txt
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
--- Day 7: Amplification Circuit ---
|
||||||
|
|
||||||
|
Based on the navigational maps, you're going to need to send more power to your ship's thrusters to reach Santa in time. To do this, you'll need to configure a series of amplifiers already installed on the ship.
|
||||||
|
|
||||||
|
There are five amplifiers connected in series; each one receives an input signal and produces an output signal. They are connected such that the first amplifier's output leads to the second amplifier's input, the second amplifier's output leads to the third amplifier's input, and so on. The first amplifier's input value is 0, and the last amplifier's output leads to your ship's thrusters.
|
||||||
|
|
||||||
|
O-------O O-------O O-------O O-------O O-------O
|
||||||
|
0 ->| Amp A |->| Amp B |->| Amp C |->| Amp D |->| Amp E |-> (to thrusters)
|
||||||
|
O-------O O-------O O-------O O-------O O-------O
|
||||||
|
|
||||||
|
The Elves have sent you some Amplifier Controller Software (your puzzle input), a program that should run on your existing Intcode computer. Each amplifier will need to run a copy of the program.
|
||||||
|
|
||||||
|
When a copy of the program starts running on an amplifier, it will first use an input instruction to ask the amplifier for its current phase setting (an integer from 0 to 4). Each phase setting is used exactly once, but the Elves can't remember which amplifier needs which phase setting.
|
||||||
|
|
||||||
|
The program will then call another input instruction to get the amplifier's input signal, compute the correct output signal, and supply it back to the amplifier with an output instruction. (If the amplifier has not yet received an input signal, it waits until one arrives.)
|
||||||
|
|
||||||
|
Your job is to find the largest output signal that can be sent to the thrusters by trying every possible combination of phase settings on the amplifiers. Make sure that memory is not shared or reused between copies of the program.
|
||||||
|
|
||||||
|
For example, suppose you want to try the phase setting sequence 3,1,2,4,0, which would mean setting amplifier A to phase setting 3, amplifier B to setting 1, C to 2, D to 4, and E to 0. Then, you could determine the output signal that gets sent from amplifier E to the thrusters with the following steps:
|
||||||
|
|
||||||
|
Start the copy of the amplifier controller software that will run on amplifier A. At its first input instruction, provide it the amplifier's phase setting, 3. At its second input instruction, provide it the input signal, 0. After some calculations, it will use an output instruction to indicate the amplifier's output signal.
|
||||||
|
Start the software for amplifier B. Provide it the phase setting (1) and then whatever output signal was produced from amplifier A. It will then produce a new output signal destined for amplifier C.
|
||||||
|
Start the software for amplifier C, provide the phase setting (2) and the value from amplifier B, then collect its output signal.
|
||||||
|
Run amplifier D's software, provide the phase setting (4) and input value, and collect its output signal.
|
||||||
|
Run amplifier E's software, provide the phase setting (0) and input value, and collect its output signal.
|
||||||
|
|
||||||
|
The final output signal from amplifier E would be sent to the thrusters. However, this phase setting sequence may not have been the best one; another sequence might have sent a higher signal to the thrusters.
|
||||||
|
|
||||||
|
Here are some example programs:
|
||||||
|
|
||||||
|
Max thruster signal 43210 (from phase setting sequence 4,3,2,1,0):
|
||||||
|
|
||||||
|
3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0
|
||||||
|
|
||||||
|
Max thruster signal 54321 (from phase setting sequence 0,1,2,3,4):
|
||||||
|
|
||||||
|
3,23,3,24,1002,24,10,24,1002,23,-1,23,
|
||||||
|
101,5,23,23,1,24,23,23,4,23,99,0,0
|
||||||
|
|
||||||
|
Max thruster signal 65210 (from phase setting sequence 1,0,4,3,2):
|
||||||
|
|
||||||
|
3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,
|
||||||
|
1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0
|
||||||
|
|
||||||
|
Try every combination of phase settings on the amplifiers. What is the highest signal that can be sent to the thrusters?
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
It's no good - in this configuration, the amplifiers can't generate a large enough output signal to produce the thrust you'll need. The Elves quickly talk you through rewiring the amplifiers into a feedback loop:
|
||||||
|
|
||||||
|
O-------O O-------O O-------O O-------O O-------O
|
||||||
|
0 -+->| Amp A |->| Amp B |->| Amp C |->| Amp D |->| Amp E |-.
|
||||||
|
| O-------O O-------O O-------O O-------O O-------O |
|
||||||
|
| |
|
||||||
|
'--------------------------------------------------------+
|
||||||
|
|
|
||||||
|
v
|
||||||
|
(to thrusters)
|
||||||
|
|
||||||
|
Most of the amplifiers are connected as they were before; amplifier A's output is connected to amplifier B's input, and so on. However, the output from amplifier E is now connected into amplifier A's input. This creates the feedback loop: the signal will be sent through the amplifiers many times.
|
||||||
|
|
||||||
|
In feedback loop mode, the amplifiers need totally different phase settings: integers from 5 to 9, again each used exactly once. These settings will cause the Amplifier Controller Software to repeatedly take input and produce output many times before halting. Provide each amplifier its phase setting at its first input instruction; all further input/output instructions are for signals.
|
||||||
|
|
||||||
|
Don't restart the Amplifier Controller Software on any amplifier during this process. Each one should continue receiving and sending signals until it halts.
|
||||||
|
|
||||||
|
All signals sent or received in this process will be between pairs of amplifiers except the very first signal and the very last signal. To start the process, a 0 signal is sent to amplifier A's input exactly once.
|
||||||
|
|
||||||
|
Eventually, the software on the amplifiers will halt after they have processed the final loop. When this happens, the last output signal from amplifier E is sent to the thrusters. Your job is to find the largest output signal that can be sent to the thrusters using the new phase settings and feedback loop arrangement.
|
||||||
|
|
||||||
|
Here are some example programs:
|
||||||
|
|
||||||
|
Max thruster signal 139629729 (from phase setting sequence 9,8,7,6,5):
|
||||||
|
|
||||||
|
3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,
|
||||||
|
27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5
|
||||||
|
|
||||||
|
Max thruster signal 18216 (from phase setting sequence 9,7,8,5,6):
|
||||||
|
|
||||||
|
3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,
|
||||||
|
-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,
|
||||||
|
53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10
|
||||||
|
|
||||||
|
Try every combination of the new phase settings on the amplifier feedback loop. What is the highest signal that can be sent to the thrusters?
|
1
www/statics/aoc/2019/07_input.txt
Normal file
1
www/statics/aoc/2019/07_input.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
3,8,1001,8,10,8,105,1,0,0,21,46,67,88,101,126,207,288,369,450,99999,3,9,1001,9,5,9,1002,9,5,9,1001,9,5,9,102,3,9,9,101,2,9,9,4,9,99,3,9,102,4,9,9,101,5,9,9,102,5,9,9,101,3,9,9,4,9,99,3,9,1001,9,3,9,102,2,9,9,1001,9,5,9,102,4,9,9,4,9,99,3,9,102,3,9,9,1001,9,4,9,4,9,99,3,9,102,3,9,9,1001,9,3,9,1002,9,2,9,101,4,9,9,102,3,9,9,4,9,99,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,99
|
211
www/statics/aoc/2019/07_solution-1.ts
Normal file
211
www/statics/aoc/2019/07_solution-1.ts
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
namespace AdventOfCode2019_07_1
|
||||||
|
{
|
||||||
|
const DAY = 7;
|
||||||
|
const PROBLEM = 1;
|
||||||
|
|
||||||
|
export async function run()
|
||||||
|
{
|
||||||
|
let input = await AdventOfCode.getInput(DAY);
|
||||||
|
if (input == null) return;
|
||||||
|
|
||||||
|
let code = input.split(",").map(p => parseInt(p.trim()));
|
||||||
|
|
||||||
|
let outputs = [];
|
||||||
|
|
||||||
|
for(let i=0; i < 5*5*5*5*5; i++)
|
||||||
|
{
|
||||||
|
let v = i;
|
||||||
|
let a1 = v%5; v = Math.floor(v/5);
|
||||||
|
let a2 = v%5; v = Math.floor(v/5);
|
||||||
|
let a3 = v%5; v = Math.floor(v/5);
|
||||||
|
let a4 = v%5; v = Math.floor(v/5);
|
||||||
|
let a5 = v%5; v = Math.floor(v/5);
|
||||||
|
|
||||||
|
if ([a1,a2,a3,a4,a5].sort((a, b) => a - b).filter((v,i,s) => s.indexOf(v)===i).length !== 5) continue;
|
||||||
|
|
||||||
|
const runner1 = new Interpreter(code, [a1, 0]);
|
||||||
|
runner1.run();
|
||||||
|
|
||||||
|
const runner2 = new Interpreter(code, [a2, runner1.output[0]]);
|
||||||
|
runner2.run();
|
||||||
|
|
||||||
|
const runner3 = new Interpreter(code, [a3, runner2.output[0]]);
|
||||||
|
runner3.run();
|
||||||
|
|
||||||
|
const runner4 = new Interpreter(code, [a4, runner3.output[0]]);
|
||||||
|
runner4.run();
|
||||||
|
|
||||||
|
const runner5 = new Interpreter(code, [a5, runner4.output[0]]);
|
||||||
|
runner5.run();
|
||||||
|
|
||||||
|
outputs.push(runner5.output[0]);
|
||||||
|
console.log([a1,a2,a3,a4,a5].toString() + " --> " + runner1.output[0] + " |> " + runner2.output[0] + " |> " + runner3.output[0] + " |> " + runner4.output[0] + " |> " + runner5.output[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const max = outputs.sort((a, b) => a - b).reverse()[0];
|
||||||
|
|
||||||
|
AdventOfCode.output(DAY, PROBLEM, max.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
class Interpreter
|
||||||
|
{
|
||||||
|
program: number[];
|
||||||
|
input: number[];
|
||||||
|
instructionpointer: number;
|
||||||
|
inputpointer: number;
|
||||||
|
output: number[];
|
||||||
|
|
||||||
|
constructor(prog: number[], input: number[])
|
||||||
|
{
|
||||||
|
this.program = prog;
|
||||||
|
this.input = input;
|
||||||
|
this.instructionpointer = 0;
|
||||||
|
this.inputpointer = 0;
|
||||||
|
this.output = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
const cmd = new Op(this.program[this.instructionpointer]);
|
||||||
|
let ipinc = true;
|
||||||
|
|
||||||
|
if (cmd.opcode == OpCode.ADD)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 + p1;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.MUL)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 * p1;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.HALT)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.IN)
|
||||||
|
{
|
||||||
|
const pv = this.input[this.inputpointer];
|
||||||
|
cmd.setParameter(this, 0, pv);
|
||||||
|
this.inputpointer++;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.OUT)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
this.output.push(p0);
|
||||||
|
//console.log("# " + p0);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.TJMP)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
if (p0 != 0) { this.instructionpointer = cmd.getParameter(this, 1); ipinc=false; }
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.FJMP)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
if (p0 == 0) { this.instructionpointer = cmd.getParameter(this, 1); ipinc=false; }
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.LT)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 < p1 ? 1 : 0;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.EQ)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 == p1 ? 1 : 0;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else throw "Unknown Op: " + cmd.opcode + " @ " + this.instructionpointer;
|
||||||
|
|
||||||
|
if (ipinc) this.instructionpointer += 1 + cmd.parametercount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum OpCode
|
||||||
|
{
|
||||||
|
ADD = 1,
|
||||||
|
MUL = 2,
|
||||||
|
IN = 3,
|
||||||
|
OUT = 4,
|
||||||
|
TJMP = 5,
|
||||||
|
FJMP = 6,
|
||||||
|
LT = 7,
|
||||||
|
EQ = 8,
|
||||||
|
HALT = 99,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ParamMode
|
||||||
|
{
|
||||||
|
POSITION_MODE = 0,
|
||||||
|
IMMEDIATE_MODE = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
class Op
|
||||||
|
{
|
||||||
|
opcode: OpCode;
|
||||||
|
modes: ParamMode[];
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
parametercount: number;
|
||||||
|
|
||||||
|
constructor(v: number)
|
||||||
|
{
|
||||||
|
this.opcode = v%100;
|
||||||
|
v = Math.floor(v/100);
|
||||||
|
this.modes = [];
|
||||||
|
for(let i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
this.modes.push(v%10);
|
||||||
|
v = Math.floor(v/10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.opcode == OpCode.ADD) { this.name="ADD"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.MUL) { this.name="MUL"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.HALT) { this.name="HALT"; this.parametercount=0; }
|
||||||
|
else if (this.opcode == OpCode.IN) { this.name="IN"; this.parametercount=1; }
|
||||||
|
else if (this.opcode == OpCode.OUT) { this.name="OUT"; this.parametercount=1; }
|
||||||
|
else if (this.opcode == OpCode.TJMP) { this.name="TJMP"; this.parametercount=2; }
|
||||||
|
else if (this.opcode == OpCode.FJMP) { this.name="FJMP"; this.parametercount=2; }
|
||||||
|
else if (this.opcode == OpCode.LT) { this.name="LT"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.EQ) { this.name="EQ"; this.parametercount=3; }
|
||||||
|
else throw "Unknown opcode: "+this.opcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
getParameter(proc: Interpreter, index: number): number
|
||||||
|
{
|
||||||
|
const prog = proc.program;
|
||||||
|
const ip = proc.instructionpointer;
|
||||||
|
|
||||||
|
let p = prog[ip+1+index];
|
||||||
|
|
||||||
|
if (this.modes[index] == ParamMode.POSITION_MODE) p = prog[p];
|
||||||
|
else if (this.modes[index] == ParamMode.IMMEDIATE_MODE) p = p;
|
||||||
|
else throw "Unknown ParamMode: "+this.modes[index];
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
setParameter(proc: Interpreter, index: number, value: number): void
|
||||||
|
{
|
||||||
|
const prog = proc.program;
|
||||||
|
const ip = proc.instructionpointer;
|
||||||
|
|
||||||
|
let p = prog[ip+1+index];
|
||||||
|
|
||||||
|
if (this.modes[index] == ParamMode.POSITION_MODE) prog[p] = value;
|
||||||
|
else if (this.modes[index] == ParamMode.IMMEDIATE_MODE) throw "Immediate mode not allowed in write";
|
||||||
|
else throw "Unknown ParamMpde: "+this.modes[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
299
www/statics/aoc/2019/07_solution-2.ts
Normal file
299
www/statics/aoc/2019/07_solution-2.ts
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
namespace AdventOfCode2019_07_2
|
||||||
|
{
|
||||||
|
const DAY = 7;
|
||||||
|
const PROBLEM = 2;
|
||||||
|
|
||||||
|
export async function run()
|
||||||
|
{
|
||||||
|
let input = await AdventOfCode.getInput(DAY);
|
||||||
|
if (input == null) return;
|
||||||
|
|
||||||
|
let code = input.split(",").map(p => parseInt(p.trim()));
|
||||||
|
|
||||||
|
let outputs: number[] = [];
|
||||||
|
|
||||||
|
for(let i=0; i < 5*5*5*5*5; i++)
|
||||||
|
{
|
||||||
|
let v = i;
|
||||||
|
let a1 = v%5 + 5; v = Math.floor(v/5);
|
||||||
|
let a2 = v%5 + 5; v = Math.floor(v/5);
|
||||||
|
let a3 = v%5 + 5; v = Math.floor(v/5);
|
||||||
|
let a4 = v%5 + 5; v = Math.floor(v/5);
|
||||||
|
let a5 = v%5 + 5; v = Math.floor(v/5);
|
||||||
|
|
||||||
|
if ([a1,a2,a3,a4,a5].sort((a, b) => a - b).filter((v,i,s) => s.indexOf(v)===i).length !== 5) continue;
|
||||||
|
|
||||||
|
const r = evalConfiguration(code, a1,a2,a3,a4,a5)
|
||||||
|
|
||||||
|
outputs.push(r);
|
||||||
|
console.log([a1,a2,a3,a4,a5].toString() + " --> " + r);
|
||||||
|
}
|
||||||
|
|
||||||
|
const max = outputs.sort((a, b) => a - b).reverse()[0];
|
||||||
|
|
||||||
|
AdventOfCode.output(DAY, PROBLEM, max.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
function evalConfiguration(code: number[], a1 : number, a2 : number, a3 : number, a4 : number, a5 : number) : number
|
||||||
|
{
|
||||||
|
const runner1 = new Interpreter(code, [a1, 0]);
|
||||||
|
const runner2 = new Interpreter(code, [a2]);
|
||||||
|
const runner3 = new Interpreter(code, [a3]);
|
||||||
|
const runner4 = new Interpreter(code, [a4]);
|
||||||
|
const runner5 = new Interpreter(code, [a5]);
|
||||||
|
|
||||||
|
let optr1 = 0;
|
||||||
|
let optr2 = 0;
|
||||||
|
let optr3 = 0;
|
||||||
|
let optr4 = 0;
|
||||||
|
let optr5 = 0;
|
||||||
|
|
||||||
|
while (!runner5.is_halted)
|
||||||
|
{
|
||||||
|
runner1.singleStep();
|
||||||
|
if (runner1.output.length > optr1)
|
||||||
|
{
|
||||||
|
runner2.inputqueue.push(runner1.output[optr1]);
|
||||||
|
optr1++;
|
||||||
|
}
|
||||||
|
|
||||||
|
runner2.singleStep();
|
||||||
|
if (runner2.output.length > optr2)
|
||||||
|
{
|
||||||
|
runner3.inputqueue.push(runner2.output[optr2]);
|
||||||
|
optr2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
runner3.singleStep();
|
||||||
|
if (runner3.output.length > optr3)
|
||||||
|
{
|
||||||
|
runner4.inputqueue.push(runner3.output[optr3]);
|
||||||
|
optr3++;
|
||||||
|
}
|
||||||
|
|
||||||
|
runner4.singleStep();
|
||||||
|
if (runner4.output.length > optr4)
|
||||||
|
{
|
||||||
|
runner5.inputqueue.push(runner4.output[optr4]);
|
||||||
|
optr4++;
|
||||||
|
}
|
||||||
|
|
||||||
|
runner5.singleStep();
|
||||||
|
if (runner5.output.length > optr5)
|
||||||
|
{
|
||||||
|
runner1.inputqueue.push(runner5.output[optr5]);
|
||||||
|
optr5++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return runner5.output.reverse()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
class Interpreter
|
||||||
|
{
|
||||||
|
program: number[];
|
||||||
|
inputqueue: number[];
|
||||||
|
instructionpointer: number;
|
||||||
|
output: number[];
|
||||||
|
|
||||||
|
is_halted: boolean = false;
|
||||||
|
|
||||||
|
constructor(prog: number[], input: number[])
|
||||||
|
{
|
||||||
|
this.program = Object.assign([], prog);
|
||||||
|
this.inputqueue = Object.assign([], input);
|
||||||
|
this.instructionpointer = 0;
|
||||||
|
this.output = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
fullRun() : number[]
|
||||||
|
{
|
||||||
|
while(!this.is_halted)
|
||||||
|
{
|
||||||
|
const r = this.singleStep();
|
||||||
|
|
||||||
|
if (r === StepResult.EXECUTED) continue;
|
||||||
|
if (r === StepResult.HALTED) return this.output;
|
||||||
|
if (r === StepResult.WAITING_FOR_IN) throw "not enough input";
|
||||||
|
|
||||||
|
throw "unknown output of singleStep";
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.output;
|
||||||
|
}
|
||||||
|
|
||||||
|
singleStep() : StepResult
|
||||||
|
{
|
||||||
|
const cmd = new Op(this.program[this.instructionpointer]);
|
||||||
|
|
||||||
|
if (cmd.opcode == OpCode.ADD)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 + p1;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
|
||||||
|
this.incInstrPtr(cmd);
|
||||||
|
|
||||||
|
return StepResult.EXECUTED;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.MUL)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 * p1;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
|
||||||
|
this.incInstrPtr(cmd);
|
||||||
|
|
||||||
|
return StepResult.EXECUTED;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.HALT)
|
||||||
|
{
|
||||||
|
this.is_halted = true;
|
||||||
|
return StepResult.HALTED;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.IN)
|
||||||
|
{
|
||||||
|
if (this.inputqueue.length == 0) return StepResult.WAITING_FOR_IN;
|
||||||
|
|
||||||
|
const pv = this.inputqueue[0];
|
||||||
|
cmd.setParameter(this, 0, pv);
|
||||||
|
this.inputqueue = this.inputqueue.slice(1);
|
||||||
|
|
||||||
|
this.incInstrPtr(cmd);
|
||||||
|
return StepResult.EXECUTED;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.OUT)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
this.output.push(p0);
|
||||||
|
|
||||||
|
this.incInstrPtr(cmd);
|
||||||
|
|
||||||
|
return StepResult.EXECUTED;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.TJMP)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
if (p0 != 0) this.instructionpointer = cmd.getParameter(this, 1);
|
||||||
|
else this.incInstrPtr(cmd);
|
||||||
|
|
||||||
|
return StepResult.EXECUTED;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.FJMP)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
if (p0 == 0) this.instructionpointer = cmd.getParameter(this, 1);
|
||||||
|
else this.incInstrPtr(cmd);
|
||||||
|
|
||||||
|
return StepResult.EXECUTED;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.LT)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 < p1 ? 1 : 0;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
|
||||||
|
this.incInstrPtr(cmd);
|
||||||
|
return StepResult.EXECUTED;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.EQ)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 == p1 ? 1 : 0;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
|
||||||
|
this.incInstrPtr(cmd);
|
||||||
|
return StepResult.EXECUTED;
|
||||||
|
}
|
||||||
|
else throw "Unknown Op: " + cmd.opcode + " @ " + this.instructionpointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private incInstrPtr(cmd: Op)
|
||||||
|
{
|
||||||
|
this.instructionpointer += 1 + cmd.parametercount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum StepResult { EXECUTED, HALTED, WAITING_FOR_IN }
|
||||||
|
|
||||||
|
enum OpCode
|
||||||
|
{
|
||||||
|
ADD = 1,
|
||||||
|
MUL = 2,
|
||||||
|
IN = 3,
|
||||||
|
OUT = 4,
|
||||||
|
TJMP = 5,
|
||||||
|
FJMP = 6,
|
||||||
|
LT = 7,
|
||||||
|
EQ = 8,
|
||||||
|
HALT = 99,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ParamMode
|
||||||
|
{
|
||||||
|
POSITION_MODE = 0,
|
||||||
|
IMMEDIATE_MODE = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
class Op
|
||||||
|
{
|
||||||
|
opcode: OpCode;
|
||||||
|
modes: ParamMode[];
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
parametercount: number;
|
||||||
|
|
||||||
|
constructor(v: number)
|
||||||
|
{
|
||||||
|
this.opcode = v%100;
|
||||||
|
v = Math.floor(v/100);
|
||||||
|
this.modes = [];
|
||||||
|
for(let i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
this.modes.push(v%10);
|
||||||
|
v = Math.floor(v/10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.opcode == OpCode.ADD) { this.name="ADD"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.MUL) { this.name="MUL"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.HALT) { this.name="HALT"; this.parametercount=0; }
|
||||||
|
else if (this.opcode == OpCode.IN) { this.name="IN"; this.parametercount=1; }
|
||||||
|
else if (this.opcode == OpCode.OUT) { this.name="OUT"; this.parametercount=1; }
|
||||||
|
else if (this.opcode == OpCode.TJMP) { this.name="TJMP"; this.parametercount=2; }
|
||||||
|
else if (this.opcode == OpCode.FJMP) { this.name="FJMP"; this.parametercount=2; }
|
||||||
|
else if (this.opcode == OpCode.LT) { this.name="LT"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.EQ) { this.name="EQ"; this.parametercount=3; }
|
||||||
|
else throw "Unknown opcode: "+this.opcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
getParameter(proc: Interpreter, index: number): number
|
||||||
|
{
|
||||||
|
const prog = proc.program;
|
||||||
|
const ip = proc.instructionpointer;
|
||||||
|
|
||||||
|
let p = prog[ip+1+index];
|
||||||
|
|
||||||
|
if (this.modes[index] == ParamMode.POSITION_MODE) p = prog[p];
|
||||||
|
else if (this.modes[index] == ParamMode.IMMEDIATE_MODE) p = p;
|
||||||
|
else throw "Unknown ParamMode: "+this.modes[index];
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
setParameter(proc: Interpreter, index: number, value: number): void
|
||||||
|
{
|
||||||
|
const prog = proc.program;
|
||||||
|
const ip = proc.instructionpointer;
|
||||||
|
|
||||||
|
let p = prog[ip+1+index];
|
||||||
|
|
||||||
|
if (this.modes[index] == ParamMode.POSITION_MODE) prog[p] = value;
|
||||||
|
else if (this.modes[index] == ParamMode.IMMEDIATE_MODE) throw "Immediate mode not allowed in write";
|
||||||
|
else throw "Unknown ParamMpde: "+this.modes[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
www/statics/aoc/2019/08_challenge.txt
Normal file
57
www/statics/aoc/2019/08_challenge.txt
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
--- Day 8: Space Image Format ---
|
||||||
|
|
||||||
|
The Elves' spirits are lifted when they realize you have an opportunity to reboot one of their Mars rovers, and so they are curious if you would spend a brief sojourn on Mars. You land your ship near the rover.
|
||||||
|
|
||||||
|
When you reach the rover, you discover that it's already in the process of rebooting! It's just waiting for someone to enter a BIOS password. The Elf responsible for the rover takes a picture of the password (your puzzle input) and sends it to you via the Digital Sending Network.
|
||||||
|
|
||||||
|
Unfortunately, images sent via the Digital Sending Network aren't encoded with any normal encoding; instead, they're encoded in a special Space Image Format. None of the Elves seem to remember why this is the case. They send you the instructions to decode it.
|
||||||
|
|
||||||
|
Images are sent as a series of digits that each represent the color of a single pixel. The digits fill each row of the image left-to-right, then move downward to the next row, filling rows top-to-bottom until every pixel of the image is filled.
|
||||||
|
|
||||||
|
Each image actually consists of a series of identically-sized layers that are filled in this way. So, the first digit corresponds to the top-left pixel of the first layer, the second digit corresponds to the pixel to the right of that on the same layer, and so on until the last digit, which corresponds to the bottom-right pixel of the last layer.
|
||||||
|
|
||||||
|
For example, given an image 3 pixels wide and 2 pixels tall, the image data 123456789012 corresponds to the following image layers:
|
||||||
|
|
||||||
|
Layer 1: 123
|
||||||
|
456
|
||||||
|
|
||||||
|
Layer 2: 789
|
||||||
|
012
|
||||||
|
|
||||||
|
The image you received is 25 pixels wide and 6 pixels tall.
|
||||||
|
|
||||||
|
To make sure the image wasn't corrupted during transmission, the Elves would like you to find the layer that contains the fewest 0 digits. On that layer, what is the number of 1 digits multiplied by the number of 2 digits?
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
Now you're ready to decode the image. The image is rendered by stacking the layers and aligning the pixels with the same positions in each layer. The digits indicate the color of the corresponding pixel: 0 is black, 1 is white, and 2 is transparent.
|
||||||
|
|
||||||
|
The layers are rendered with the first layer in front and the last layer in back. So, if a given position has a transparent pixel in the first and second layers, a black pixel in the third layer, and a white pixel in the fourth layer, the final image would have a black pixel at that position.
|
||||||
|
|
||||||
|
For example, given an image 2 pixels wide and 2 pixels tall, the image data 0222112222120000 corresponds to the following image layers:
|
||||||
|
|
||||||
|
Layer 1: 02
|
||||||
|
22
|
||||||
|
|
||||||
|
Layer 2: 11
|
||||||
|
22
|
||||||
|
|
||||||
|
Layer 3: 22
|
||||||
|
12
|
||||||
|
|
||||||
|
Layer 4: 00
|
||||||
|
00
|
||||||
|
|
||||||
|
Then, the full image can be found by determining the top visible pixel in each position:
|
||||||
|
|
||||||
|
The top-left pixel is black because the top layer is 0.
|
||||||
|
The top-right pixel is white because the top layer is 2 (transparent), but the second layer is 1.
|
||||||
|
The bottom-left pixel is white because the top two layers are 2, but the third layer is 1.
|
||||||
|
The bottom-right pixel is black because the only visible pixel in that position is 0 (from layer 4).
|
||||||
|
|
||||||
|
So, the final image looks like this:
|
||||||
|
|
||||||
|
01
|
||||||
|
10
|
||||||
|
|
||||||
|
What message is produced after decoding your image?
|
1
www/statics/aoc/2019/08_input.txt
Normal file
1
www/statics/aoc/2019/08_input.txt
Normal file
File diff suppressed because one or more lines are too long
31
www/statics/aoc/2019/08_solution-1.ts
Normal file
31
www/statics/aoc/2019/08_solution-1.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
namespace AdventOfCode2019_08_1
|
||||||
|
{
|
||||||
|
const DAY = 8;
|
||||||
|
const PROBLEM = 1;
|
||||||
|
|
||||||
|
export async function run()
|
||||||
|
{
|
||||||
|
let input = await AdventOfCode.getInput(DAY);
|
||||||
|
if (input == null) return;
|
||||||
|
|
||||||
|
let data = input.trim().split("").map(p => parseInt(p));
|
||||||
|
|
||||||
|
const layers = [];
|
||||||
|
|
||||||
|
while (data.length>0) { layers.push(data.slice(0, 25*6)); data = data.slice(25*6); }
|
||||||
|
|
||||||
|
let zc = 9999999999;
|
||||||
|
let vv = -1;
|
||||||
|
|
||||||
|
for(let i = 0; i < layers.length; i++)
|
||||||
|
{
|
||||||
|
const _zc = layers[i].filter(p => p==0).length;
|
||||||
|
const _vv = layers[i].filter(p => p==1).length * layers[i].filter(p => p==2).length;
|
||||||
|
|
||||||
|
console.log("["+i+"] => "+_zc+" ("+_vv+")");
|
||||||
|
if (_zc < zc) { zc=_zc; vv = _vv; }
|
||||||
|
}
|
||||||
|
|
||||||
|
AdventOfCode.output(DAY, PROBLEM, vv.toString());
|
||||||
|
}
|
||||||
|
}
|
43
www/statics/aoc/2019/08_solution-2.ts
Normal file
43
www/statics/aoc/2019/08_solution-2.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
namespace AdventOfCode2019_08_2
|
||||||
|
{
|
||||||
|
const DAY = 8;
|
||||||
|
const PROBLEM = 2;
|
||||||
|
|
||||||
|
export async function run()
|
||||||
|
{
|
||||||
|
let input = await AdventOfCode.getInput(DAY);
|
||||||
|
if (input == null) return;
|
||||||
|
|
||||||
|
let data = input.trim().split("").map(p => parseInt(p));
|
||||||
|
|
||||||
|
const layers = [];
|
||||||
|
|
||||||
|
while (data.length>0) { layers.push(data.slice(0, 25*6)); data = data.slice(25*6); }
|
||||||
|
|
||||||
|
let r = Array(25*6);
|
||||||
|
for(let i=0; i<25*6;i++) r[i]=2;
|
||||||
|
|
||||||
|
for(let il = layers.length-1; il >= 0 ; il--)
|
||||||
|
{
|
||||||
|
for(let i=0; i<25*6;i++)
|
||||||
|
{
|
||||||
|
if (layers[il][i] == 2) continue;
|
||||||
|
r[i] = layers[il][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let str = "";
|
||||||
|
for(let i=0; i<25*6;i++)
|
||||||
|
{
|
||||||
|
if (i>0 && i%25==0)str+="\n";
|
||||||
|
|
||||||
|
if (r[i]===0) str += " ";
|
||||||
|
if (r[i]===1) str += "#";
|
||||||
|
if (r[i]===2) str += ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(str);
|
||||||
|
|
||||||
|
AdventOfCode.output(DAY, PROBLEM, "CJZLP"); // OCR -.-
|
||||||
|
}
|
||||||
|
}
|
48
www/statics/aoc/2019/09_challenge.txt
Normal file
48
www/statics/aoc/2019/09_challenge.txt
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
--- Day 9: Sensor Boost ---
|
||||||
|
|
||||||
|
You've just said goodbye to the rebooted rover and left Mars when you receive a faint distress signal coming from the asteroid belt. It must be the Ceres monitoring station!
|
||||||
|
|
||||||
|
In order to lock on to the signal, you'll need to boost your sensors. The Elves send up the latest BOOST program - Basic Operation Of System Test.
|
||||||
|
|
||||||
|
While BOOST (your puzzle input) is capable of boosting your sensors, for tenuous safety reasons, it refuses to do so until the computer it runs on passes some checks to demonstrate it is a complete Intcode computer.
|
||||||
|
|
||||||
|
Your existing Intcode computer is missing one key feature: it needs support for parameters in relative mode.
|
||||||
|
|
||||||
|
Parameters in mode 2, relative mode, behave very similarly to parameters in position mode: the parameter is interpreted as a position. Like position mode, parameters in relative mode can be read from or written to.
|
||||||
|
|
||||||
|
The important difference is that relative mode parameters don't count from address 0. Instead, they count from a value called the relative base. The relative base starts at 0.
|
||||||
|
|
||||||
|
The address a relative mode parameter refers to is itself plus the current relative base. When the relative base is 0, relative mode parameters and position mode parameters with the same value refer to the same address.
|
||||||
|
|
||||||
|
For example, given a relative base of 50, a relative mode parameter of -7 refers to memory address 50 + -7 = 43.
|
||||||
|
|
||||||
|
The relative base is modified with the relative base offset instruction:
|
||||||
|
|
||||||
|
Opcode 9 adjusts the relative base by the value of its only parameter. The relative base increases (or decreases, if the value is negative) by the value of the parameter.
|
||||||
|
|
||||||
|
For example, if the relative base is 2000, then after the instruction 109,19, the relative base would be 2019. If the next instruction were 204,-34, then the value at address 1985 would be output.
|
||||||
|
|
||||||
|
Your Intcode computer will also need a few other capabilities:
|
||||||
|
|
||||||
|
The computer's available memory should be much larger than the initial program. Memory beyond the initial program starts with the value 0 and can be read or written like any other memory. (It is invalid to try to access memory at a negative address, though.)
|
||||||
|
The computer should have support for large numbers. Some instructions near the beginning of the BOOST program will verify this capability.
|
||||||
|
|
||||||
|
Here are some example programs that use these features:
|
||||||
|
|
||||||
|
109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99 takes no input and produces a copy of itself as output.
|
||||||
|
1102,34915192,34915192,7,4,7,99,0 should output a 16-digit number.
|
||||||
|
104,1125899906842624,99 should output the large number in the middle.
|
||||||
|
|
||||||
|
The BOOST program will ask for a single input; run it in test mode by providing it the value 1. It will perform a series of checks on each opcode, output any opcodes (and the associated parameter modes) that seem to be functioning incorrectly, and finally output a BOOST keycode.
|
||||||
|
|
||||||
|
Once your Intcode computer is fully functional, the BOOST program should report no malfunctioning opcodes when run in test mode; it should only output a single value, the BOOST keycode. What BOOST keycode does it produce?
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
You now have a complete Intcode computer.
|
||||||
|
|
||||||
|
Finally, you can lock on to the Ceres distress signal! You just need to boost your sensors using the BOOST program.
|
||||||
|
|
||||||
|
The program runs in sensor boost mode by providing the input instruction the value 2. Once run, it will boost the sensors automatically, but it might take a few seconds to complete the operation on slower hardware. In sensor boost mode, the program will output a single value: the coordinates of the distress signal.
|
||||||
|
|
||||||
|
Run the BOOST program in sensor boost mode. What are the coordinates of the distress signal?
|
1
www/statics/aoc/2019/09_input.txt
Normal file
1
www/statics/aoc/2019/09_input.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,3,1,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,1,21,1008,1101,427,0,1028,1102,23,1,1012,1101,32,0,1009,1101,37,0,1007,1102,1,892,1023,1102,27,1,1004,1102,1,38,1013,1102,1,20,1005,1101,0,29,1001,1101,0,22,1015,1102,1,35,1003,1101,0,39,1016,1102,34,1,1011,1101,899,0,1022,1102,195,1,1024,1101,36,0,1014,1101,0,24,1000,1102,1,31,1006,1101,0,28,1017,1101,422,0,1029,1102,1,33,1019,1102,1,26,1018,1102,1,0,1020,1102,25,1,1002,1102,712,1,1027,1101,0,190,1025,1101,0,715,1026,1102,1,1,1021,1101,30,0,1010,109,30,2105,1,-6,4,187,1106,0,199,1001,64,1,64,1002,64,2,64,109,-19,1206,10,211,1106,0,217,4,205,1001,64,1,64,1002,64,2,64,109,-13,1202,8,1,63,1008,63,28,63,1005,63,241,1001,64,1,64,1106,0,243,4,223,1002,64,2,64,109,8,1201,-2,0,63,1008,63,29,63,1005,63,263,1105,1,269,4,249,1001,64,1,64,1002,64,2,64,109,-9,2101,0,3,63,1008,63,24,63,1005,63,295,4,275,1001,64,1,64,1106,0,295,1002,64,2,64,109,12,2107,31,0,63,1005,63,317,4,301,1001,64,1,64,1106,0,317,1002,64,2,64,109,7,21101,40,0,0,1008,1016,43,63,1005,63,341,1001,64,1,64,1106,0,343,4,323,1002,64,2,64,109,-14,1208,-1,31,63,1005,63,363,1001,64,1,64,1106,0,365,4,349,1002,64,2,64,109,9,1208,-6,20,63,1005,63,387,4,371,1001,64,1,64,1105,1,387,1002,64,2,64,109,2,2102,1,-7,63,1008,63,31,63,1005,63,413,4,393,1001,64,1,64,1106,0,413,1002,64,2,64,109,21,2106,0,-6,4,419,1106,0,431,1001,64,1,64,1002,64,2,64,109,-25,2108,35,-6,63,1005,63,449,4,437,1106,0,453,1001,64,1,64,1002,64,2,64,109,3,21107,41,42,0,1005,1012,471,4,459,1105,1,475,1001,64,1,64,1002,64,2,64,109,7,21108,42,39,-2,1005,1017,495,1001,64,1,64,1105,1,497,4,481,1002,64,2,64,109,-8,1206,9,515,4,503,1001,64,1,64,1106,0,515,1002,64,2,64,109,4,1205,6,529,4,521,1105,1,533,1001,64,1,64,1002,64,2,64,109,-8,2107,26,-5,63,1005,63,553,1001,64,1,64,1106,0,555,4,539,1002,64,2,64,109,-6,2102,1,1,63,1008,63,26,63,1005,63,575,1105,1,581,4,561,1001,64,1,64,1002,64,2,64,109,10,2101,0,-8,63,1008,63,37,63,1005,63,601,1105,1,607,4,587,1001,64,1,64,1002,64,2,64,109,-19,1207,8,23,63,1005,63,627,1001,64,1,64,1106,0,629,4,613,1002,64,2,64,109,18,21101,43,0,3,1008,1013,43,63,1005,63,655,4,635,1001,64,1,64,1106,0,655,1002,64,2,64,109,-16,1207,6,25,63,1005,63,677,4,661,1001,64,1,64,1106,0,677,1002,64,2,64,109,25,21102,44,1,-4,1008,1015,44,63,1005,63,703,4,683,1001,64,1,64,1106,0,703,1002,64,2,64,109,17,2106,0,-9,1106,0,721,4,709,1001,64,1,64,1002,64,2,64,109,-16,1205,0,737,1001,64,1,64,1105,1,739,4,727,1002,64,2,64,109,-12,21107,45,44,5,1005,1013,759,1001,64,1,64,1106,0,761,4,745,1002,64,2,64,109,4,1201,-8,0,63,1008,63,27,63,1005,63,783,4,767,1106,0,787,1001,64,1,64,1002,64,2,64,109,-16,2108,25,4,63,1005,63,803,1105,1,809,4,793,1001,64,1,64,1002,64,2,64,109,27,21102,46,1,-5,1008,1018,43,63,1005,63,829,1106,0,835,4,815,1001,64,1,64,1002,64,2,64,109,-27,1202,8,1,63,1008,63,27,63,1005,63,857,4,841,1105,1,861,1001,64,1,64,1002,64,2,64,109,23,21108,47,47,-2,1005,1017,883,4,867,1001,64,1,64,1106,0,883,1002,64,2,64,109,-1,2105,1,5,1001,64,1,64,1106,0,901,4,889,4,64,99,21102,1,27,1,21102,915,1,0,1105,1,922,21201,1,29589,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1106,0,922,21202,1,1,-1,21201,-2,-3,1,21102,957,1,0,1105,1,922,22201,1,-1,-2,1106,0,968,21202,-2,1,-2,109,-3,2106,0,0
|
213
www/statics/aoc/2019/09_solution-1.ts
Normal file
213
www/statics/aoc/2019/09_solution-1.ts
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
namespace AdventOfCode2019_09_1
|
||||||
|
{
|
||||||
|
const DAY = 9;
|
||||||
|
const PROBLEM = 1;
|
||||||
|
|
||||||
|
export async function run()
|
||||||
|
{
|
||||||
|
let input = await AdventOfCode.getInput(DAY);
|
||||||
|
if (input == null) return;
|
||||||
|
|
||||||
|
const code = input.split(",").map(p => parseInt(p.trim()));
|
||||||
|
let runner = new Interpreter(code, [1]);
|
||||||
|
|
||||||
|
runner.run();
|
||||||
|
|
||||||
|
AdventOfCode.output(DAY, PROBLEM, runner.output.reverse()[0].toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
class Interpreter
|
||||||
|
{
|
||||||
|
program: InfMem;
|
||||||
|
input: number[];
|
||||||
|
instructionpointer: number;
|
||||||
|
inputpointer: number;
|
||||||
|
output: number[];
|
||||||
|
relative_base: number;
|
||||||
|
|
||||||
|
constructor(prog: number[], input: number[])
|
||||||
|
{
|
||||||
|
this.program = new InfMem(prog);
|
||||||
|
this.input = input;
|
||||||
|
this.instructionpointer = 0;
|
||||||
|
this.inputpointer = 0;
|
||||||
|
this.output = [];
|
||||||
|
this.relative_base = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
const cmd = new Op(this.program.r(this.instructionpointer));
|
||||||
|
let ipinc = true;
|
||||||
|
|
||||||
|
if (cmd.opcode == OpCode.ADD)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 + p1;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.MUL)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 * p1;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.HALT)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.IN)
|
||||||
|
{
|
||||||
|
const pv = this.input[this.inputpointer];
|
||||||
|
cmd.setParameter(this, 0, pv);
|
||||||
|
this.inputpointer++;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.OUT)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
this.output.push(p0);
|
||||||
|
console.log("# " + p0);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.TJMP)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
if (p0 != 0) { this.instructionpointer = cmd.getParameter(this, 1); ipinc=false; }
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.FJMP)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
if (p0 == 0) { this.instructionpointer = cmd.getParameter(this, 1); ipinc=false; }
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.LT)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 < p1 ? 1 : 0;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.EQ)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 == p1 ? 1 : 0;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.ARB)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
this.relative_base = this.relative_base+p0;
|
||||||
|
}
|
||||||
|
else throw "Unknown Op: " + cmd.opcode + " @ " + this.instructionpointer;
|
||||||
|
|
||||||
|
if (ipinc) this.instructionpointer += 1 + cmd.parametercount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum OpCode
|
||||||
|
{
|
||||||
|
ADD = 1,
|
||||||
|
MUL = 2,
|
||||||
|
IN = 3,
|
||||||
|
OUT = 4,
|
||||||
|
TJMP = 5,
|
||||||
|
FJMP = 6,
|
||||||
|
LT = 7,
|
||||||
|
EQ = 8,
|
||||||
|
ARB = 9,
|
||||||
|
HALT = 99,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ParamMode
|
||||||
|
{
|
||||||
|
POSITION_MODE = 0,
|
||||||
|
IMMEDIATE_MODE = 1,
|
||||||
|
RELATIVE_MODE = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
class Op
|
||||||
|
{
|
||||||
|
opcode: OpCode;
|
||||||
|
modes: ParamMode[];
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
parametercount: number;
|
||||||
|
|
||||||
|
constructor(v: number)
|
||||||
|
{
|
||||||
|
this.opcode = v%100;
|
||||||
|
v = Math.floor(v/100);
|
||||||
|
this.modes = [];
|
||||||
|
for(let i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
this.modes.push(v%10);
|
||||||
|
v = Math.floor(v/10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.opcode == OpCode.ADD) { this.name="ADD"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.MUL) { this.name="MUL"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.HALT) { this.name="HALT"; this.parametercount=0; }
|
||||||
|
else if (this.opcode == OpCode.IN) { this.name="IN"; this.parametercount=1; }
|
||||||
|
else if (this.opcode == OpCode.OUT) { this.name="OUT"; this.parametercount=1; }
|
||||||
|
else if (this.opcode == OpCode.TJMP) { this.name="TJMP"; this.parametercount=2; }
|
||||||
|
else if (this.opcode == OpCode.FJMP) { this.name="FJMP"; this.parametercount=2; }
|
||||||
|
else if (this.opcode == OpCode.LT) { this.name="LT"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.EQ) { this.name="EQ"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.ARB) { this.name="ARB"; this.parametercount=1; }
|
||||||
|
else throw "Unknown opcode: "+this.opcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
getParameter(proc: Interpreter, index: number): number
|
||||||
|
{
|
||||||
|
const prog = proc.program;
|
||||||
|
const ip = proc.instructionpointer;
|
||||||
|
|
||||||
|
let p = prog.r(ip+1+index);
|
||||||
|
|
||||||
|
if (this.modes[index] == ParamMode.POSITION_MODE) p = prog.r(p);
|
||||||
|
else if (this.modes[index] == ParamMode.IMMEDIATE_MODE) p = p;
|
||||||
|
else if (this.modes[index] == ParamMode.RELATIVE_MODE) p = prog.r(proc.relative_base+p);
|
||||||
|
else throw "Unknown ParamMode: "+this.modes[index];
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
setParameter(proc: Interpreter, index: number, value: number): void
|
||||||
|
{
|
||||||
|
const prog = proc.program;
|
||||||
|
const ip = proc.instructionpointer;
|
||||||
|
|
||||||
|
let p = prog.r(ip+1+index);
|
||||||
|
|
||||||
|
if (this.modes[index] == ParamMode.POSITION_MODE) prog.w(p, value);
|
||||||
|
else if (this.modes[index] == ParamMode.IMMEDIATE_MODE) throw "Immediate mode not allowed in write";
|
||||||
|
else if (this.modes[index] == ParamMode.RELATIVE_MODE) prog.w(proc.relative_base+p, value);
|
||||||
|
else throw "Unknown ParamMode: "+this.modes[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InfMem
|
||||||
|
{
|
||||||
|
private data: { [_:number]:number } = {};
|
||||||
|
|
||||||
|
constructor(v: number[])
|
||||||
|
{
|
||||||
|
for(let i=0; i<v.length;i++) this.data[i]=v[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
r(pos: number): number
|
||||||
|
{
|
||||||
|
if (!(pos in this.data)) this.data[pos] = 0;
|
||||||
|
return this.data[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
w(pos: number, val: number): number
|
||||||
|
{
|
||||||
|
return this.data[pos] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
213
www/statics/aoc/2019/09_solution-2.ts
Normal file
213
www/statics/aoc/2019/09_solution-2.ts
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
namespace AdventOfCode2019_09_2
|
||||||
|
{
|
||||||
|
const DAY = 9;
|
||||||
|
const PROBLEM = 2;
|
||||||
|
|
||||||
|
export async function run()
|
||||||
|
{
|
||||||
|
let input = await AdventOfCode.getInput(DAY);
|
||||||
|
if (input == null) return;
|
||||||
|
|
||||||
|
const code = input.split(",").map(p => parseInt(p.trim()));
|
||||||
|
let runner = new Interpreter(code, [2]);
|
||||||
|
|
||||||
|
runner.run();
|
||||||
|
|
||||||
|
AdventOfCode.output(DAY, PROBLEM, runner.output.reverse()[0].toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
class Interpreter
|
||||||
|
{
|
||||||
|
program: InfMem;
|
||||||
|
input: number[];
|
||||||
|
instructionpointer: number;
|
||||||
|
inputpointer: number;
|
||||||
|
output: number[];
|
||||||
|
relative_base: number;
|
||||||
|
|
||||||
|
constructor(prog: number[], input: number[])
|
||||||
|
{
|
||||||
|
this.program = new InfMem(prog);
|
||||||
|
this.input = input;
|
||||||
|
this.instructionpointer = 0;
|
||||||
|
this.inputpointer = 0;
|
||||||
|
this.output = [];
|
||||||
|
this.relative_base = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
const cmd = new Op(this.program.r(this.instructionpointer));
|
||||||
|
let ipinc = true;
|
||||||
|
|
||||||
|
if (cmd.opcode == OpCode.ADD)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 + p1;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.MUL)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 * p1;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.HALT)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.IN)
|
||||||
|
{
|
||||||
|
const pv = this.input[this.inputpointer];
|
||||||
|
cmd.setParameter(this, 0, pv);
|
||||||
|
this.inputpointer++;
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.OUT)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
this.output.push(p0);
|
||||||
|
console.log("# " + p0);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.TJMP)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
if (p0 != 0) { this.instructionpointer = cmd.getParameter(this, 1); ipinc=false; }
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.FJMP)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
if (p0 == 0) { this.instructionpointer = cmd.getParameter(this, 1); ipinc=false; }
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.LT)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 < p1 ? 1 : 0;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.EQ)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
const p1 = cmd.getParameter(this, 1);
|
||||||
|
const pv = p0 == p1 ? 1 : 0;
|
||||||
|
cmd.setParameter(this, 2, pv);
|
||||||
|
}
|
||||||
|
else if (cmd.opcode == OpCode.ARB)
|
||||||
|
{
|
||||||
|
const p0 = cmd.getParameter(this, 0);
|
||||||
|
this.relative_base = this.relative_base+p0;
|
||||||
|
}
|
||||||
|
else throw "Unknown Op: " + cmd.opcode + " @ " + this.instructionpointer;
|
||||||
|
|
||||||
|
if (ipinc) this.instructionpointer += 1 + cmd.parametercount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum OpCode
|
||||||
|
{
|
||||||
|
ADD = 1,
|
||||||
|
MUL = 2,
|
||||||
|
IN = 3,
|
||||||
|
OUT = 4,
|
||||||
|
TJMP = 5,
|
||||||
|
FJMP = 6,
|
||||||
|
LT = 7,
|
||||||
|
EQ = 8,
|
||||||
|
ARB = 9,
|
||||||
|
HALT = 99,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ParamMode
|
||||||
|
{
|
||||||
|
POSITION_MODE = 0,
|
||||||
|
IMMEDIATE_MODE = 1,
|
||||||
|
RELATIVE_MODE = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
class Op
|
||||||
|
{
|
||||||
|
opcode: OpCode;
|
||||||
|
modes: ParamMode[];
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
parametercount: number;
|
||||||
|
|
||||||
|
constructor(v: number)
|
||||||
|
{
|
||||||
|
this.opcode = v%100;
|
||||||
|
v = Math.floor(v/100);
|
||||||
|
this.modes = [];
|
||||||
|
for(let i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
this.modes.push(v%10);
|
||||||
|
v = Math.floor(v/10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.opcode == OpCode.ADD) { this.name="ADD"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.MUL) { this.name="MUL"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.HALT) { this.name="HALT"; this.parametercount=0; }
|
||||||
|
else if (this.opcode == OpCode.IN) { this.name="IN"; this.parametercount=1; }
|
||||||
|
else if (this.opcode == OpCode.OUT) { this.name="OUT"; this.parametercount=1; }
|
||||||
|
else if (this.opcode == OpCode.TJMP) { this.name="TJMP"; this.parametercount=2; }
|
||||||
|
else if (this.opcode == OpCode.FJMP) { this.name="FJMP"; this.parametercount=2; }
|
||||||
|
else if (this.opcode == OpCode.LT) { this.name="LT"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.EQ) { this.name="EQ"; this.parametercount=3; }
|
||||||
|
else if (this.opcode == OpCode.ARB) { this.name="ARB"; this.parametercount=1; }
|
||||||
|
else throw "Unknown opcode: "+this.opcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
getParameter(proc: Interpreter, index: number): number
|
||||||
|
{
|
||||||
|
const prog = proc.program;
|
||||||
|
const ip = proc.instructionpointer;
|
||||||
|
|
||||||
|
let p = prog.r(ip+1+index);
|
||||||
|
|
||||||
|
if (this.modes[index] == ParamMode.POSITION_MODE) p = prog.r(p);
|
||||||
|
else if (this.modes[index] == ParamMode.IMMEDIATE_MODE) p = p;
|
||||||
|
else if (this.modes[index] == ParamMode.RELATIVE_MODE) p = prog.r(proc.relative_base+p);
|
||||||
|
else throw "Unknown ParamMode: "+this.modes[index];
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
setParameter(proc: Interpreter, index: number, value: number): void
|
||||||
|
{
|
||||||
|
const prog = proc.program;
|
||||||
|
const ip = proc.instructionpointer;
|
||||||
|
|
||||||
|
let p = prog.r(ip+1+index);
|
||||||
|
|
||||||
|
if (this.modes[index] == ParamMode.POSITION_MODE) prog.w(p, value);
|
||||||
|
else if (this.modes[index] == ParamMode.IMMEDIATE_MODE) throw "Immediate mode not allowed in write";
|
||||||
|
else if (this.modes[index] == ParamMode.RELATIVE_MODE) prog.w(proc.relative_base+p, value);
|
||||||
|
else throw "Unknown ParamMode: "+this.modes[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InfMem
|
||||||
|
{
|
||||||
|
private data: { [_:number]:number } = {};
|
||||||
|
|
||||||
|
constructor(v: number[])
|
||||||
|
{
|
||||||
|
for(let i=0; i<v.length;i++) this.data[i]=v[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
r(pos: number): number
|
||||||
|
{
|
||||||
|
if (!(pos in this.data)) this.data[pos] = 0;
|
||||||
|
return this.data[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
w(pos: number, val: number): number
|
||||||
|
{
|
||||||
|
return this.data[pos] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -37,6 +37,9 @@ return
|
|||||||
['day' => 3, 'parts' => 2, 'title' => 'Crossed Wires', 'language' => 'ts', 'solutions' => ['399', '15678'] ],
|
['day' => 3, 'parts' => 2, 'title' => 'Crossed Wires', 'language' => 'ts', 'solutions' => ['399', '15678'] ],
|
||||||
['day' => 4, 'parts' => 2, 'title' => 'Secure Container', 'language' => 'ts', 'solutions' => ['979', '635'] ],
|
['day' => 4, 'parts' => 2, 'title' => 'Secure Container', 'language' => 'ts', 'solutions' => ['979', '635'] ],
|
||||||
['day' => 5, 'parts' => 2, 'title' => 'Sunny with a Chance of Asteroids', 'language' => 'ts', 'solutions' => ['8332629', '8805067'] ],
|
['day' => 5, 'parts' => 2, 'title' => 'Sunny with a Chance of Asteroids', 'language' => 'ts', 'solutions' => ['8332629', '8805067'] ],
|
||||||
|
['day' => 6, 'parts' => 2, 'title' => 'Universal Orbit Map', 'language' => 'ts', 'solutions' => ['333679', '370'] ],
|
||||||
|
['day' => 7, 'parts' => 2, 'title' => 'Amplification Circuit', 'language' => 'ts', 'solutions' => ['844468', '4215746'] ],
|
||||||
|
['day' => 8, 'parts' => 2, 'title' => 'Space Image Format', 'language' => 'ts', 'solutions' => ['2286', 'CJZLP'] ],
|
||||||
|
['day' => 9, 'parts' => 2, 'title' => 'Sensor Boost', 'language' => 'ts', 'solutions' => ['2738720997', '50894'] ],
|
||||||
],
|
],
|
||||||
];
|
];
|
Loading…
Reference in New Issue
Block a user