122 lines
4.4 KiB
C#
122 lines
4.4 KiB
C#
using AdventOfCode.Core;
|
|
|
|
namespace AdventOfCode.Solutions._2023
|
|
{
|
|
public class Day07(InputReader reader) : IChallange
|
|
{
|
|
private readonly InputReader _inputReader = reader;
|
|
|
|
private static readonly List<char> CardValues = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'];
|
|
private static readonly List<char> CardValuesJoker = ['J', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A'];
|
|
private enum SetRanks { High, OnePair, TwoPair, ThreeKind, FullHouse, FourKind, FiveKind }
|
|
|
|
public async Task<string> GetSolutionPart1()
|
|
{
|
|
return (await _inputReader.ReadAsArrayString())
|
|
.Select(l => new Hand(l))
|
|
.Order()
|
|
.Select((h, i) => h.Bid * (i + 1))
|
|
.Sum()
|
|
.ToString();
|
|
}
|
|
|
|
public async Task<string> GetSolutionPart2()
|
|
{
|
|
return (await _inputReader.ReadAsArrayString())
|
|
.Select(l => new Hand(l, true))
|
|
.Order()
|
|
.Select((h, i) => h.Bid * (i + 1))
|
|
.Sum()
|
|
.ToString();
|
|
}
|
|
|
|
private record Hand : IComparable<Hand>
|
|
{
|
|
public int Bid { get; set; }
|
|
public SetRanks Rank { get; set; }
|
|
public string Source { get; set; }
|
|
public string JokerSource { get; set; } = string.Empty;
|
|
public List<char> CharCompairList => string.IsNullOrEmpty(JokerSource) ? CardValues : CardValuesJoker;
|
|
|
|
public Hand(string line, bool jokerMode = false)
|
|
{
|
|
string[] splitted = line.Split(' ');
|
|
Source = splitted[0];
|
|
Bid = int.Parse(splitted[1]);
|
|
|
|
string finalTestLine = Source;
|
|
if (jokerMode)
|
|
{
|
|
JokerSource = Source;
|
|
if (finalTestLine.Contains('J') && finalTestLine.Any(c => c != 'J'))
|
|
{
|
|
// fun time
|
|
char toReplace = finalTestLine.Where(c => c != 'J').GroupBy(c => c).OrderByDescending(g => g.Count()).First().Key;
|
|
finalTestLine = finalTestLine.Replace('J', toReplace);
|
|
JokerSource = finalTestLine;
|
|
}
|
|
}
|
|
|
|
var grouped = finalTestLine.GroupBy(c => c).OrderByDescending(g => g.Count());
|
|
|
|
switch(grouped.Count())
|
|
{
|
|
case 1:
|
|
Rank = SetRanks.FiveKind;
|
|
break;
|
|
case 4:
|
|
Rank = SetRanks.OnePair;
|
|
break;
|
|
case 5:
|
|
Rank = SetRanks.High;
|
|
break;
|
|
case 3:
|
|
if (grouped.Skip(1).First().Count() == 2)
|
|
Rank = SetRanks.TwoPair;
|
|
else
|
|
Rank = SetRanks.ThreeKind;
|
|
break;
|
|
case 2:
|
|
if (grouped.First().Count() == 4)
|
|
Rank = SetRanks.FourKind;
|
|
else
|
|
Rank = SetRanks.FullHouse;
|
|
break;
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{JokerSource} [{Source}] {Rank} {Bid}";
|
|
}
|
|
|
|
public int CompareTo(Hand? other)
|
|
{
|
|
if (other == null)
|
|
return 1;
|
|
|
|
if (this.Rank == other.Rank && this.Source == other.Source)
|
|
return 0;
|
|
|
|
if (this.Rank > other.Rank)
|
|
return 1;
|
|
if (this.Rank < other.Rank)
|
|
return -1;
|
|
|
|
for (int i = 0; i < Source.Length; i++)
|
|
{
|
|
if (this.Source[i] == other.Source[i])
|
|
continue;
|
|
if (CharCompairList.IndexOf(this.Source[i]) > CharCompairList.IndexOf(other.Source[i]))
|
|
return 1;
|
|
if (CharCompairList.IndexOf(this.Source[i]) < CharCompairList.IndexOf(other.Source[i]))
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
} |