1
0

aoc 25 (missing files)

This commit is contained in:
Mike Schwörer 2019-12-26 11:41:19 +01:00
parent fbaf956aec
commit 2c2a940124
3 changed files with 526 additions and 0 deletions

View File

@ -0,0 +1,24 @@
--- Day 25: Cryostasis ---
As you approach Santa's ship, your sensors report two important details:
First, that you might be too late: the internal temperature is -40 degrees.
Second, that one faint life signature is somewhere on the ship.
The airlock door is locked with a code; your best option is to send in a small droid to investigate the situation. You attach your ship to Santa's, break a small hole in the hull, and let the droid run in before you seal it up again. Before your ship starts freezing, you detach your ship and set it to automatically stay within range of Santa's ship.
This droid can follow basic instructions and report on its surroundings; you can communicate with it through an Intcode program (your puzzle input) running on an ASCII-capable computer.
As the droid moves through its environment, it will describe what it encounters. When it says Command?, you can give it a single instruction terminated with a newline (ASCII code 10). Possible instructions are:
Movement via north, south, east, or west.
To take an item the droid sees in the environment, use the command take <name of item>. For example, if the droid reports seeing a red ball, you can pick it up with take red ball.
To drop an item the droid is carrying, use the command drop <name of item>. For example, if the droid is carrying a green ball, you can drop it with drop green ball.
To get a list of all of the items the droid is currently carrying, use the command inv (for "inventory").
Extra spaces or other characters aren't allowed - instructions must be provided precisely.
Santa's ship is a Reindeer-class starship; these ships use pressure-sensitive floors to determine the identity of droids and crew members. The standard configuration for these starships is for all droids to weigh exactly the same amount to make them easier to detect. If you need to get past such a sensor, you might be able to reach the correct weight by carrying items from the environment.
Look around the ship and see if you can find the password for the main airlock.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,501 @@
namespace AdventOfCode2019_25_1
{
const DAY = 25;
const PROBLEM = 1;
export async function run()
{
let input = await AdventOfCode.getInput(DAY);
if (input == null) return;
//await runInteractive(input);
await runAuto(input);
}
async function runAuto(input: string)
{
const code = input.trim().split(",").map(p => parseInt(p.trim()));
let visited = new Set<string>();
let work: [number, Direction[]][] = [];
work.push([0, []]);
let rooms: Room[] = [];
let dest: Room = new Room(); dest.name = "Floor"; dest.path = [Direction.S, Direction.S, Direction.S, Direction.E, Direction.S, Direction.E];
let items: {[_:string]:Room} = {};
let allitems = [];
while (work.length > 0)
{
let workitem = work.pop()!;
let room = getRoom(code, workitem[1]);
if (visited.has(room.name)) continue;
visited.add(room.name);
rooms.push(room);
AdventOfCode.outputConsole(`${room.name} => ${room.path.map(p => dir_to_short_str(p)).join("")}`);
if (room.object !== null)
{
items[room.object] = room;
allitems.push(room.object);
}
for (const d of room.doors)
{
let p2 = Object.assign([], room.path);
p2.push(d);
work.push([ workitem[0]+1, p2 ]);
}
}
for (let bmap = 0; bmap < Math.pow(2, allitems.length); bmap++)
{
let packeditems = allitems.filter((v,i,a) => ( bmap & Math.pow(2, i) ) !== 0 );
let destrooms = packeditems.map(p => items[p]);
let fullpath = [];
for (const destroomm of destrooms)
{
for (const d of destroomm.path) fullpath.push(dir_to_str(d)+"\n");
fullpath.push("take "+destroomm.object+"\n");
for (const d of destroomm.path.slice().reverse()) fullpath.push(dir_to_str_inv(d)+"\n");
}
fullpath.push("inv\n");
for (const d of dest.path) fullpath.push(dir_to_str(d)+"\n");
let rnr = new Interpreter(code, fullpath.flatMap(p => p.split("").map(q => q.charCodeAt(0))));
rnr.autoRun();
let strout = rnr.output.map(p => String.fromCharCode(p)).join("");
await AdventOfCode.outputIntermed("Inv: [" + packeditems.join(" ++ ") + "]\n" + fullpath.join("") + "\n\n" + strout);
//await AdventOfCode.sleep(10*1000);
if (strout.indexOf("You can't go that way.") > 0)
{
AdventOfCode.output(DAY, PROBLEM, "ERROR");
return; // error
}
if (strout.indexOf("A loud, robotic voice says \"Alert! ") > 0) continue;
if (strout.indexOf("It is suddenly completely dark! You are eaten by a Grue!") > 0) continue;
if (strout.indexOf("You're launched into space! Bye!") > 0) continue;
if (strout.indexOf("Oh, hello! You should be able to get in by typing") > 0)
{
let lastline = strout.trim().split(new RegExp('\r?\n')).slice().reverse()[0];
let r = lastline.substring(lastline.indexOf("typing")+"typing".length).trim().split(" ")[0];
AdventOfCode.output(DAY, PROBLEM, r.trim());
return;
}
AdventOfCode.output(DAY, PROBLEM, "ERROR");
return; // error
}
}
class Room
{
name: string = "";
doors: Direction[] = [];
object: string|null = null;
path: Direction[] = [];
}
enum Direction { N, E, S, W }
function getRoom(code: number[], dirs: Direction[]): Room
{
let rnr = new Interpreter(code, dirs.map(p => dir_to_str(p) + "\n").join("").split("").map(p => p.charCodeAt(0)));
rnr.autoRun();
let lines = rnr.output
.map(p => String.fromCharCode(p))
.join("")
.split(new RegExp('\r?\n'))
.reverse();
let r_dir: Direction[] = [];
let r_obj: string|null = null;
for(let lin of lines)
{
if (lin === "Command?") continue;
if (lin === "") continue;
if (lin.startsWith("- "))
{
let obj = lin.substring(2);
if (obj === "north") r_dir.push(Direction.N);
else if (obj === "east") r_dir.push(Direction.E);
else if (obj === "south") r_dir.push(Direction.S);
else if (obj === "west") r_dir.push(Direction.W);
else r_obj = obj;
continue;
}
if (lin.startsWith("== "))
{
let name = lin.substring(3, lin.length-3);
let r = new Room();
r.doors = r_dir;
r.name = name;
r.object = r_obj;
r.path = dirs;
return r;
}
}
throw "EOD";
}
function dir_to_str(d: Direction): string
{
if (d === Direction.N) return "north";
if (d === Direction.E) return "east";
if (d === Direction.S) return "south";
if (d === Direction.W) return "west";
throw d;
}
function dir_to_str_inv(d: Direction): string
{
if (d === Direction.N) return "south";
if (d === Direction.E) return "west";
if (d === Direction.S) return "north";
if (d === Direction.W) return "east";
throw d;
}
function dir_to_short_str(d: Direction): string
{
if (d === Direction.N) return "N";
if (d === Direction.E) return "E";
if (d === Direction.S) return "S";
if (d === Direction.W) return "W";
throw d;
}
async function runInteractive(input: string)
{
AdventOfCode.showIntermedInput(true);
const code = input.trim().split(",").map(p => parseInt(p.trim()));
let rnr = new Interpreter(code, []);
let last_out = "";
for(;;)
{
rnr.autoRun();
let xout = rnr.output
.map(p => String.fromCharCode(p))
.join("")
.split(new RegExp('\r?\n'))
.reverse()
.filter((v,i,a) => i<60)
.reverse()
.join('\n');
if (last_out !== xout)
{
last_out = xout;
await AdventOfCode.outputIntermed(xout);
}
else
{
await AdventOfCode.sleep(0);
}
if (AdventOfCode.isLastInputEnter() && rnr.inputqueue.length === 0)
{
let cmd = AdventOfCode.getAndClearInput();
rnr.inputqueue = cmd.split("").map(p => p.charCodeAt(0));
rnr.inputqueue.push(10);
}
}
}
class Interpreter
{
program: InfMem;
inputqueue: number[];
instructionpointer: number;
output: number[];
relative_base: number;
blocking_io: boolean;
is_halted: boolean = false;
last_io_success: boolean = true;
constructor(prog: number[], input: number[])
{
this.program = new InfMem(prog);
this.inputqueue = input;
this.instructionpointer = 0;
this.output = [];
this.relative_base = 0;
this.blocking_io = true;
}
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;
}
autoRun() : StepResult
{
while(!this.is_halted)
{
const r = this.singleStep();
if (r === StepResult.EXECUTED) continue;
if (r === StepResult.HALTED) return StepResult.HALTED;
if (r === StepResult.WAITING_FOR_IN) return StepResult.WAITING_FOR_IN;
throw "unknown output of singleStep";
}
return StepResult.HALTED;
}
singleStep() : StepResult
{
const cmd = new Op(this.program.r(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)
{
if (this.blocking_io) return StepResult.WAITING_FOR_IN;
cmd.setParameter(this, 0, -1);
this.incInstrPtr(cmd);
this.last_io_success = false;
return StepResult.EXECUTED;
}
const pv = this.inputqueue[0];
cmd.setParameter(this, 0, pv);
this.inputqueue = this.inputqueue.slice(1);
this.incInstrPtr(cmd);
this.last_io_success = true;
return StepResult.EXECUTED;
}
else if (cmd.opcode == OpCode.OUT)
{
const p0 = cmd.getParameter(this, 0);
this.output.push(p0);
//AdventOfCode.outputConsole("# " + 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 if (cmd.opcode == OpCode.ARB)
{
const p0 = cmd.getParameter(this, 0);
this.relative_base = this.relative_base+p0;
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,
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;
}
}
}