Skip to content

Instantly share code, notes, and snippets.

@jakcharvat
Created December 7, 2019 19:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jakcharvat/818c477ca284e8cc6a571d02a2b60885 to your computer and use it in GitHub Desktop.
Save jakcharvat/818c477ca284e8cc6a571d02a2b60885 to your computer and use it in GitHub Desktop.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
class IntcodeComputer {
IntcodeComputer(this._memory, {this.inputStream, this.outputStream})
: _broadcastStream = inputStream?.asBroadcastStream() {
_broadcastStream?.listen((item) => _inputs.add(item));
}
List<int> _memory;
final Stream inputStream;
final StreamController outputStream;
final _broadcastStream;
final List<int> _inputs = [];
void reset(mem) {
_memory = mem;
}
List<int> getOperationArguments(List<int> params, int modes) {
if (modes == null) return [_memory[params[1]], _memory[params[2]]];
// Immediate mode
String modesS = modes.toString();
int modeOne;
if (modesS.length - 1 >= 0)
modeOne = int.parse(modesS[modesS.length - 1]);
else
modeOne = 0;
int modeTwo;
if (modesS.length - 2 >= 0)
modeTwo = int.parse(modesS[modesS.length - 2]);
else
modeTwo = 0;
int numOne = modeOne == 1 ? params[1] : _memory[params[1]];
int numTwo = modeTwo == 1 ? params[2] : _memory[params[2]];
return [numOne, numTwo];
}
// Add
int opcode1(List<int> params, int modes, int pointer) {
var nums = getOperationArguments(params, modes);
_memory[params[3]] = nums.first + nums.last;
return pointer + 4;
}
// Multiply
int opcode2(List<int> params, int modes, int pointer) {
var nums = getOperationArguments(params, modes);
_memory[params[3]] = nums.first * nums.last;
return pointer + 4;
}
// Input
Future<int> opcode3(List<int> params, _, int pointer) async {
int val;
if (inputStream == null) {
stdout.write('input: ');
val =
int.parse(stdin.readLineSync(encoding: Encoding.getByName('utf-8')));
} else val = await getInputFromStream();
_memory[params[1]] = val;
return pointer + 2;
}
// Output
int opcode4(List<int> params, int modes, int pointer) {
int val;
if (modes != null) val = params[1];
else val = _memory[params[1]];
if (outputStream == null) print(val);
else outputStream.sink.add(val);
return pointer + 2;
}
// Jump if true
int opcode5(List<int> params, int modes, int pointer) {
var parameters = getOperationArguments(params, modes);
if (parameters.first != 0) return parameters.last;
return pointer + 3;
}
// Jump if false
int opcode6(List<int> params, int modes, int pointer) {
var parameters = getOperationArguments(params, modes);
if (parameters.first == 0) return parameters.last;
return pointer + 3;
}
// Less than
int opcode7(List<int> params, int modes, int pointer) {
var nums = getOperationArguments(params, modes);
_memory[params[3]] = nums.first < nums.last ? 1 : 0;
return pointer + 4;
}
// Equality
int opcode8(List<int> params, int modes, int pointer) {
var nums = getOperationArguments(params, modes);
_memory[params[3]] = nums.first == nums.last ? 1 : 0;
return pointer + 4;
}
Future<int> getPointer(int modes, int pointer, int opcode) async {
switch (opcode) {
case 1:
return opcode1(_memory.sublist(pointer, pointer + 4), modes, pointer);
break;
case 2:
return opcode2(_memory.sublist(pointer, pointer + 4), modes, pointer);
break;
case 3:
return await opcode3(_memory.sublist(pointer, pointer + 2), modes, pointer);
break;
case 4:
return opcode4(_memory.sublist(pointer, pointer + 2), modes, pointer);
break;
case 5:
return opcode5(_memory.sublist(pointer, pointer + 3), modes, pointer);
break;
case 6:
return opcode6(_memory.sublist(pointer, pointer + 3), modes, pointer);
break;
case 7:
return opcode7(_memory.sublist(pointer, pointer + 4), modes, pointer);
break;
case 8:
return opcode8(_memory.sublist(pointer, pointer + 4), modes, pointer);
break;
default:
return null;
}
}
Future<int> getInputFromStream() async {
if (_inputs.isNotEmpty) return Future.value(_inputs.removeAt(0));
await for (int val in _broadcastStream) {
_inputs.removeAt(0);
return val;
}
return null;
}
void run() async {
int pointer = 0, modes = null, opcode = _memory[0];
while (opcode != 99) {
pointer = await getPointer(modes, pointer, opcode);
if (pointer == null) {
print('Something went wrong. Offending opcode: ${opcode}');
break;
}
int newOpcode = _memory[pointer];
if (newOpcode <= 99) {
opcode = newOpcode;
modes = null;
} else {
opcode = int.parse(
newOpcode.toString().substring(newOpcode.toString().length - 2));
modes = int.parse(
newOpcode.toString().substring(0, newOpcode.toString().length - 2));
}
}
}
int get first => _memory.first;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment