-
-
Save jakcharvat/818c477ca284e8cc6a571d02a2b60885 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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