You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
4.9 KiB
Dart

import 'package:aoc2020/aocbase.dart';
import 'package:aoc2020/model/readdata.dart';
class Bag {
final String color;
int count;
Bag parent;
List<Bag> children;
Bag({this.color, this.parent, this.count, List<Bag> children}) : children = [];
Bag.copy(Bag source)
: color = source.color,
count = source.count,
parent = Bag(color: source.color),
children = List.from(source.children);
@override
String toString() => 'Bag($color, parent: ${parent?.color ?? 'TOP'}, count: $count, with: ${children.map((child) => '${child.count}:${child.color}')})';
}
class AOC20201207 extends AOCBase {
// Create a List of all the leaves, then piece together all the trees
List<Bag> leaves;
List<Bag> trees;
void parseLine(String line) {
// Split line by "bags contain" first part is color of holding bag, second part is contents
// split contents by ", " List of number and color of content bag(s)
var split_one = line.split('bags contain');
var holdingBagColor = split_one[0].trim();
var holdingBag = Bag(color: holdingBagColor);
var split_two = split_one[1].substring(0, split_one[1].length - 1).trim().split(',');
for (var _bag in split_two) {
var split_three = _bag.trim().split(' ');
if (split_three[0] != 'no') {
var numBags = int.parse(split_three[0]);
var childColor = split_three[1] + ' ' + split_three[2];
var child = Bag(color: childColor);
child.count = numBags;
child.parent = holdingBag;
// leaves.add(child);
holdingBag.children.add(child);
}
}
leaves.add(holdingBag);
}
Set<String> findTops() {
var leavesWithParents = <String>{};
var allLeaves = <String>{};
for (var leaf in leaves.where((bag) => bag.children.isNotEmpty)) {
leavesWithParents.addAll(leaf.children.map((child) => child.color));
}
allLeaves.addAll(leaves.map((leaf) => leaf.color));
return allLeaves.difference(leavesWithParents);
}
Bag constructTreeFromTopBag({Bag top, int count, int level = 0}) {
// var topBag = leaves.firstWhere((bag) => bag.color == top);
var _newBag = top;
var _newChildren = <Bag>[];
// print(''.padLeft(level * 4) + 'Top = $top');
for (var child in top.children) {
var _firstChild = leaves.firstWhere((bag) => bag.color == child.color, orElse: () => null);
var _newChild = Bag.copy(_firstChild);
if (_newChild != null) {
_newChild.parent = top;
_newChild.count = child.count;
// print(''.padLeft(level * 4) + 'newChild = $_newChild $child');
_newChildren.add(constructTreeFromTopBag(top: _newChild, level: level + 1));
}
}
_newBag.children = _newChildren;
// print(''.padLeft(level * 4) + 'newBag = $_newBag');
return _newBag;
}
List<Bag> findAll({String color, Set<String> tops}) {
var _bags = <Bag>[];
void _find({String findColor, Bag findTop}) {
if (findTop.color == findColor) _bags.add(findTop);
for (var child in findTop.children) {
_find(findColor: findColor, findTop: child);
}
}
for (var top in tops) {
var topBag = leaves.firstWhere((bag) => bag.color == top);
_find(findColor: color, findTop: topBag);
}
return _bags;
}
int countContents(Bag top) {
var _count = 0;
if (top.children.isEmpty) return 0;
for (var child in top.children) {
_count += child.count;
_count += child.count * countContents(child);
}
return _count;
}
@override
Future<void> a({bool test}) async {
var mylist = await ReadData.readFile<String>(classString, test: test);
leaves = []; // Zero out list
trees = [];
for (var line in mylist) {
parseLine(line);
}
var tops = findTops();
for (var top in tops) {
var topBag = leaves.firstWhere((bag) => bag.color == top);
trees.add(constructTreeFromTopBag(top: topBag));
}
// print('Number of Tops = ${tops.length}');
var _uniqueParents = <String>{};
void _setUniqueParents(Bag bag) {
if (bag.parent != null) {
_uniqueParents.add(bag.parent.color);
_setUniqueParents(bag.parent);
}
}
_uniqueParents = {};
for (var bag in findAll(color: 'shiny gold', tops: tops)) {
_setUniqueParents(bag);
}
answerA = _uniqueParents.length;
}
@override
Future<void> b({bool test}) async {
var mylist = await ReadData.readFile<String>(classString, test: test);
leaves = []; // Zero out list
trees = [];
for (var line in mylist) {
parseLine(line);
}
var tops = findTops();
for (var top in tops) {
var topBag = leaves.firstWhere((bag) => bag.color == top);
trees.add(constructTreeFromTopBag(top: topBag));
}
// print('Number of Tops = ${tops.length}');
var _bags = findAll(color: 'shiny gold', tops: tops);
var _shiny = _bags.first;
answerB = countContents(_shiny);
}
}