DEV Community

Discussion on: Advent of Code 2019 Solution Megathread - Day 7: Amplification Circuit

Collapse
 
jakcharvat profile image
Jakub Charvat • Edited

Well, today was definitely fun. Continuing in Python from previous days, part one was fairly easy as the modifications to my existing Intcode computer were minimal and the task itself was fairly straight-forward, but part two was interesting.

For part two, I chose to rewrite my whole Intcode computer in dart, as that is the language I am most familiar with, and I'm happy I did so. I then gave each amplifier a StreamController as its output and the BroadcastStream of the previous amplifier's StreamController as its input and had them listen to each other in async. Probably not the easiest way to do it, but very fun and interesting to write.

Here's the code for part 2:

import 'dart:async';
import 'dart:io';
import 'dart:math' as math;

import './tools/intcode_computer.dart';
import './tools/permutations.dart';

//! Part 1 of day 7 is in day_7.py

void main() async {
  var input = (await File('inputs/day_7.txt').readAsString())
      .split(',')
      .map((a) => int.parse(a))
      .toList();

  run(input);
}

void run(input) async {
  var permutations = findAllPermutations('56789');

  int max;
  for (var permutation in permutations) {
    var out = await runCycle(input, permutation);

    max = math.max(max ?? 0, out);
  }

  print(max);
}

Future<int> runCycle(input, String permutation) async {
  var controllers = List.generate(5, (_) => StreamController());

  /// Creating a list of the broadcast streams of the controllers so that I can subscribe to them from here
  var streams = List.generate(
    5,
    (i) => controllers[i].stream.asBroadcastStream(),
  );

  /// Create a list of intcode computers - the amplifiers
  var comps = List.generate(
    5,
    (i) => IntcodeComputer(List.from(input),

        /// Giving each computer the broadcast stream at its index as the input stream and the controller
        /// of an index one higher as the output stream, which means the computer will output to the next
        /// computer's input stream. The last computer outputs to the first computer's stream
        inputStream: streams[i],
        outputStream: controllers[i + 1 < 5 ? i + 1 : 0]),
  );

  var split = permutation.trim().split('');

  /// Add the phase setting of the computer to that computer's input stream as the first input
  for (int i = 0; i < 5; i++) {
    controllers[i].sink.add(int.parse(split[i]));
  }

  /// Provide the first computer with the input signal 0
  controllers[0].sink.add(0);

  /// Keep track of every input to the first computer (ie every output of the last computer). The
  /// last value this will have will be the last value of the operation
  int last;
  streams.first.listen((output) => last = output);

  /// Run all computers, but keep a reference of the last computer run so that we can wait until it
  /// finishes before closing the stream controllers and returning the last value
  for (int i = 0; i < comps.length - 1; i++) comps[i].run();
  var run4 = comps[4].run();
  await run4;

  /// Close all stream controllers to prevent memory leaks
  for (var controller in controllers) controller.close();

  return last;
}

And the code for my dart Intcode Computer: gist.github.com/jakcharvat/818c477...