Dart
I'm glad I took the time to read the directions very carefully before starting coding :-)
Top Tip: my ranking of hand types relies on the fact that if you count instances of each face and sort the resulting list from high to low, you get a list that when compared with lists from other hands gives an exact correspondence with the order of the hand types as defined, so no need for a bunch of if/thens, just
var type = Multiset.from(hand).counts.sorted(descending).join('');
Otherwise it should all be pretty self-explanatory apart from where I chose to map card rank to hex digits in order to facilitate sorting, so 'b' means 'J'!
int descending(T a, T b) => b.compareTo(a);
var cToH = " 23456789TJQKA"; // used to map card rank to hex for sorting.
handType(List hand, {wildcard = false}) {
var type = Multiset.from(hand).counts.sorted(descending).join('');
var i = hand.indexOf('b');
return (!wildcard || i == -1)
? type
: '23456789acde'
.split('')
.map((e) => handType(hand.toList()..[i] = e, wildcard: true))
.fold(type, (s, t) => s.compareTo(t) >= 0 ? s : t);
}
solve(List lines, {wildcard = false}) => lines
.map((e) {
var l = e.split(' ');
var hand =
l.first.split('').map((e) => cToH.indexOf(e).toRadixString(16));
var type = handType(hand.toList(), wildcard: wildcard);
if (wildcard) hand = hand.map((e) => e == 'b' ? '0' : e);
return (hand.join(), type, int.parse(l.last));
})
.sorted((a, b) {
var c = a.$2.compareTo(b.$2);
return (c == 0) ? a.$1.compareTo(b.$1) : c;
})
.indexed(offset: 1)
.map((e) => e.value.$3 * e.index)
.sum;
part1(List lines) => solve(lines);
part2(List lines) => solve(lines, wildcard: true);