Advent of Code 2023

Es gibt 103 Antworten in diesem Thema. Der letzte Beitrag () ist von nogood.

    Part 2 fühlt sich zwar sehr dirty an, aber das Ergebnis passt zumindest
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend Class ValueCalculatorForDay7
    2. Private ReadOnly CardDecks As New List(Of CardDeck)
    3. Function GetValueFor(FilePath As String, Part As Integer) As Integer
    4. Dim RawDataLines = GetRawDataFrom(FilePath)
    5. ParseRawData(RawDataLines, Part)
    6. SetRanksForCardDecks(Part)
    7. Return GetValueForGame()
    8. End Function
    9. Private Function GetRawDataFrom(FilePath As String) As IEnumerable(Of String)
    10. Return IO.File.ReadAllLines(FilePath)
    11. End Function
    12. Private Sub ParseRawData(RawDataLines As IEnumerable(Of String), Part As Integer)
    13. RawDataLines.ToList.ForEach(Sub(x) CardDecks.Add(New CardDeck(x.Split, Part)))
    14. End Sub
    15. Private Sub SetRanksForCardDecks(Part As Integer)
    16. Dim OrderedCardDeck = CardDecks.OrderBy(Function(x) x.CardDeckType).ThenBy(Function(x) x.TranslatedCardOrder(Part = 2))
    17. For i = 0 To OrderedCardDeck.Count - 1
    18. OrderedCardDeck(i).RankInGame = i + 1
    19. Next
    20. End Sub
    21. Private Function GetValueForGame() As Integer
    22. Return CardDecks.OrderBy(Function(x) x.RankInGame).Sum(Function(x) x.GetValue)
    23. End Function
    24. End Class
    25. Friend Enum CardDeckType
    26. HighCard
    27. OnePair
    28. TwoPair
    29. ThreeOfAKind
    30. FullHouse
    31. FourOfAKind
    32. FiveOfAKind
    33. End Enum
    34. Friend Class CardDeck
    35. Property CardOrder As String
    36. Property CardDeckType As CardDeckType
    37. Property Bid As Integer
    38. Property RankInGame As Integer
    39. Private ReadOnly CardValueMappingsForPart1 As New Dictionary(Of Char, Char) From {{"2"c, "A"c}, {"3"c, "B"c}, {"4"c, "C"c}, {"5"c, "D"c}, {"6"c, "E"c}, {"7"c, "F"c}, {"8"c, "G"c}, {"9"c, "H"c}, {"T"c, "I"c}, {"J"c, "J"c}, {"Q"c, "K"c}, {"K"c, "L"c}, {"A"c, "M"c}}
    40. Private ReadOnly CardValueMappingsForPart2 As New Dictionary(Of Char, Char) From {{"J"c, "A"c}, {"2"c, "B"c}, {"3"c, "C"c}, {"4"c, "D"c}, {"5"c, "E"c}, {"6"c, "F"c}, {"7"c, "G"c}, {"8"c, "H"c}, {"9"c, "I"c}, {"T"c, "J"c}, {"Q"c, "K"c}, {"K"c, "L"c}, {"A"c, "M"c}}
    41. Sub New(RawData As IEnumerable(Of String), Part As Integer)
    42. CardOrder = RawData(0)
    43. Bid = Integer.Parse(RawData(1))
    44. DetermineCardDeckType(Part)
    45. End Sub
    46. Private Sub DetermineCardDeckType(Part As Integer)
    47. Dim IndexPacks As New List(Of IndexPack)
    48. CardOrder.ToList.ForEach(Sub(x) If Not IndexPacks.Any(Function(y) y.Character = x) Then IndexPacks.Add(New IndexPack With {.Character = x, .Occurences = GetOccurencesIn(CardOrder, x)}))
    49. If IndexPacks.Where(Function(x) x.Occurences = 2).Count = 1 Then CardDeckType = CardDeckType.OnePair
    50. If IndexPacks.Where(Function(x) x.Occurences = 2).Count = 2 Then CardDeckType = CardDeckType.TwoPair
    51. If IndexPacks.Any(Function(x) x.Occurences = 3) Then CardDeckType = CardDeckType.ThreeOfAKind
    52. If IndexPacks.Any(Function(x) x.Occurences = 3) AndAlso IndexPacks.Any(Function(x) x.Occurences = 2) Then CardDeckType = CardDeckType.FullHouse
    53. If IndexPacks.Any(Function(x) x.Occurences = 4) Then CardDeckType = CardDeckType.FourOfAKind
    54. If IndexPacks.Any(Function(x) x.Occurences = 5) Then CardDeckType = CardDeckType.FiveOfAKind
    55. If Part = 2 AndAlso CardDeckType <> CardDeckType.FiveOfAKind AndAlso CardOrder.IndexOf("J"c) > -1 Then
    56. If CardDeckType = CardDeckType.FourOfAKind Then CardDeckType = CardDeckType.FiveOfAKind
    57. If CardDeckType = CardDeckType.FullHouse Then CardDeckType = CardDeckType.FiveOfAKind
    58. If CardDeckType = CardDeckType.ThreeOfAKind Then CardDeckType = CardDeckType.FourOfAKind
    59. If CardDeckType = CardDeckType.TwoPair AndAlso IndexPacks.Single(Function(x) x.Occurences = 1).Character = "J"c Then CardDeckType = CardDeckType.FullHouse
    60. If CardDeckType = CardDeckType.TwoPair AndAlso IndexPacks.Any(Function(x) x.Occurences = 2 AndAlso x.Character = "J"c) Then CardDeckType = CardDeckType.FourOfAKind
    61. If CardDeckType = CardDeckType.TwoPair AndAlso IndexPacks.Any(Function(x) x.Occurences = 1 AndAlso x.Character = "J"c) Then CardDeckType = CardDeckType.ThreeOfAKind
    62. If CardDeckType = CardDeckType.OnePair Then CardDeckType = CardDeckType.ThreeOfAKind
    63. If CardDeckType = CardDeckType.HighCard Then CardDeckType = CardDeckType.OnePair
    64. End If
    65. End Sub
    66. Private Function GetOccurencesIn(Text As String, Character As Char) As Integer
    67. Dim Occurences = 0
    68. For i = 0 To Text.Length - 1
    69. If Text(i) = Character Then Occurences += 1
    70. Next
    71. Return Occurences
    72. End Function
    73. Function TranslatedCardOrder(Part As Integer) As String
    74. Dim CardValueMappingsToUse = If(Part = 1, CardValueMappingsForPart1, CardValueMappingsForPart2)
    75. Return CardOrder.Select(Function(x) CardValueMappingsToUse.Single(Function(y) y.Key = x).Value).ToArray
    76. End Function
    77. Function GetValue() As Integer
    78. Return Bid * RankInGame
    79. End Function
    80. End Class
    81. Friend Class IndexPack
    82. Property Character As Char
    83. Property Occurences As Integer
    84. End Class


    Bald ist meine arbeitsfreie Woche rum, dann hat sich's mit meinen zeitnahen Posts.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VaporiZed“ ()

    Also heute war eigentlich einfach... Allerdings hab ich mich bei Part02 glaub ich etwas dumm angestellt. (Im Spoiler warum)
    Bin gespannt auf deine Lösung @VaporiZed

    /EDIT// @VaporiZed geil da hat jemand genau die gleiche idee gehabt wie ich. Ich hab keine andere Lösung gefunden für Part2 als das so hinzuschreiben.
    Ich schau jetzt mal im Reddit vorbei was da abgeht.

    Spoiler anzeigen

    Ich habe bei Part2 erst gedacht ich könnte einfach nur die "J" zählen und hab gewonnen.
    Allerdings ging das dann nicht auf. Also habe ich erstmal ohne das als Joker zu sehen
    bestimmt was das nun ist für eine Hand. Und danach dann anhand der Anzahl der J und oder der Hand entschieden den Gewinntype zu ändern.
    Gibt es da ne bessere Methode als da selbst die verschiedenen Möglichkeiten zu bestimmen?

    C#-Quellcode

    1. using System.Text.RegularExpressions;
    2. namespace Tag07
    3. {
    4. internal class Program
    5. {
    6. static void Main(string[] args)
    7. {
    8. string[] exampleFile = File.ReadAllLines("Example.txt");
    9. string[] inputFile = File.ReadAllLines("Input.txt");
    10. Game gameExample = new Game();
    11. gameExample.ParseFile(exampleFile);
    12. Game gameInput = new Game();
    13. gameInput.ParseFile(inputFile);
    14. Console.WriteLine($"Example: {gameExample.Calculate()}");
    15. Console.WriteLine($"Example2: {gameExample.Calculate(true)}");
    16. Console.WriteLine($"Input Part 1: {gameInput.Calculate()}");
    17. Console.WriteLine($"Input Part 2: {gameInput.Calculate(true)}");
    18. }
    19. }
    20. public class Game
    21. {
    22. public List<Hand> Hands;
    23. public List<Char> Cards = new List<char>() { '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' };
    24. public Dictionary<char, char> CardMappingP1 = new Dictionary<char, char>()
    25. {
    26. {'2', 'A'},
    27. {'3', 'B'},
    28. {'4', 'C'},
    29. {'5', 'D'},
    30. {'6', 'E'},
    31. {'7', 'F'},
    32. {'8', 'G'},
    33. {'9', 'H'},
    34. {'T', 'I'},
    35. {'J', 'J'},
    36. {'Q', 'K'},
    37. {'K', 'L'},
    38. {'A', 'M'}
    39. };
    40. public Dictionary<char, char> CardMappingP2 = new Dictionary<char, char>()
    41. {
    42. {'J', 'A'},
    43. {'2', 'B'},
    44. {'3', 'C'},
    45. {'4', 'D'},
    46. {'5', 'E'},
    47. {'6', 'F'},
    48. {'7', 'G'},
    49. {'8', 'H'},
    50. {'9', 'I'},
    51. {'T', 'J'},
    52. {'Q', 'K'},
    53. {'K', 'L'},
    54. {'A', 'M'}
    55. };
    56. public void ParseFile(string[] lines)
    57. {
    58. Hands = new List<Hand>();
    59. foreach(string line in lines)
    60. {
    61. Hand hand = new Hand();
    62. Match match = Regex.Match(line, "(.*) (\\d+)");
    63. hand.Cards = match.Groups[1].Value;
    64. hand.Value = Int32.Parse(match.Groups[2].Value);
    65. Hands.Add(hand);
    66. }
    67. }
    68. public int Calculate(bool part2 = false)
    69. {
    70. int maxRank = Hands.Count;
    71. int sum = 0;
    72. foreach (Hand hand in Hands)
    73. {
    74. hand.UniqueCards = new Dictionary<char, int>();
    75. hand.WinnerType = WinnerType.HighCard;
    76. foreach(char ch in Cards)
    77. {
    78. hand.UniqueCards.Add(ch, hand.Cards.ToArray().Count(x => x == ch));
    79. }
    80. hand.SetWinnerType(part2);
    81. }
    82. Dictionary<char, char> mapping = (part2) ? CardMappingP2 : CardMappingP1;
    83. foreach (Hand hand in Hands.OrderByDescending(x => x.WinnerType)
    84. .ThenByDescending(x => x.GetCardOrder(mapping)))
    85. {
    86. int tmp = maxRank * hand.Value;
    87. sum+= tmp;
    88. maxRank--;
    89. }
    90. return sum;
    91. }
    92. }
    93. public enum WinnerType
    94. {
    95. FiveOfAKind = 6,
    96. FourOfAKind = 5,
    97. FullHouse = 4,
    98. ThreeOfAKind = 3,
    99. TwoPair = 2,
    100. OnePair = 1,
    101. HighCard = 0,
    102. }
    103. public class Hand
    104. {
    105. public string Cards { get; set; }
    106. public int Value { get; set; }
    107. public Dictionary<char, int> UniqueCards { get; set; } = new Dictionary<char, int>();
    108. public WinnerType WinnerType { get; set; }
    109. public int Rank { get; set; }
    110. public string GetCardOrder(Dictionary<char, char> mapping)
    111. {
    112. return String.Join("", Cards.Select(x =>
    113. mapping.Single(y => y.Key == x)
    114. .Value).ToArray()) ;
    115. }
    116. public void SetWinnerType(bool part2 = false)
    117. {
    118. if (UniqueCards.Max(x => x.Value) == 5)
    119. {
    120. WinnerType = WinnerType.FiveOfAKind;
    121. }
    122. if (UniqueCards.Max(x => x.Value) == 4)
    123. {
    124. WinnerType = WinnerType.FourOfAKind;
    125. }
    126. if (UniqueCards.ContainsValue(3) && UniqueCards.ContainsValue(2))
    127. {
    128. WinnerType = WinnerType.FullHouse;
    129. }
    130. if (UniqueCards.Max(x => x.Value) == 3 && UniqueCards.Count(x => x.Value == 1) == 2)
    131. {
    132. WinnerType = WinnerType.ThreeOfAKind;
    133. }
    134. if (UniqueCards.Count(x => x.Value == 2) == 2)
    135. {
    136. WinnerType = WinnerType.TwoPair;
    137. }
    138. if (UniqueCards.Count(x => x.Value == 2) == 1 && UniqueCards.Count(x => x.Value == 1) == 3)
    139. {
    140. WinnerType = WinnerType.OnePair;
    141. }
    142. if (UniqueCards.Count(x => x.Value == 1) == 5)
    143. {
    144. WinnerType = WinnerType.HighCard;
    145. }
    146. if(part2 && Cards.Contains('J'))
    147. {
    148. if (WinnerType == WinnerType.FourOfAKind) WinnerType = WinnerType.FiveOfAKind;
    149. if (WinnerType == WinnerType.FullHouse) WinnerType = WinnerType.FiveOfAKind;
    150. if (WinnerType == WinnerType.ThreeOfAKind) WinnerType = WinnerType.FourOfAKind;
    151. if (WinnerType == WinnerType.TwoPair)
    152. {
    153. if (UniqueCards['J'] == 2)
    154. { //A A J J B => A A A A B
    155. WinnerType = WinnerType.FourOfAKind;
    156. }
    157. if (UniqueCards['J'] == 1)
    158. { //A A B B J => A A A B B
    159. WinnerType = WinnerType.FullHouse;
    160. }
    161. }
    162. if (WinnerType == WinnerType.OnePair) WinnerType = WinnerType.ThreeOfAKind;
    163. if (WinnerType == WinnerType.HighCard) WinnerType = WinnerType.OnePair;
    164. }
    165. }
    166. }
    167. }
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen
    Wenn zwei Leute unabhängig drauf kommen, kann es nur der richtige Weg sein
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „VaporiZed“ ()

    D7 Part1
    Die ThenBy-Funktion hab ich vergessen xD. Bei mir ein schöner Umweg über: die zweite Reihenfolge zuerst, GroupBy.OrderBy.SelectMany...

    VB.NET-Quellcode

    1. Private CardValue As New Dictionary(Of Char, Integer) From {
    2. {"2"c, 0}, {"3"c, 1}, {"4"c, 2}, {"5"c, 3}, {"6"c, 4},
    3. {"7"c, 5}, {"8"c, 6}, {"9"c, 7}, {"T"c, 8}, {"J"c, 9},
    4. {"Q"c, 10}, {"K"c, 11}, {"A"c, 12}}
    5. Sub Main()
    6. Dim input = IO.File.ReadAllLines(FilePathOfData)
    7. Dim Plays = input.Select(Function(l) New Play(l.Split(" "c)))
    8. Dim PlaysOrderedByRank = Plays.OrderBy(AddressOf HandOrderValue).GroupBy(Function(p) p.Type).OrderBy(Function(g) g.Key).SelectMany(Function(g) g)
    9. Dim result = PlaysOrderedByRank.Select(Function(p, r) (r + 1) * p.Bid).Sum
    10. End Sub
    11. Private Function HandOrderValue(p As Play) As Integer
    12. Dim retVal As Integer
    13. For i = 0 To 4
    14. retVal = retVal * 13 + CardValue(p.Hand(i))
    15. Next
    16. Return retVal
    17. End Function
    18. Friend Class Play
    19. Protected chars As Char()
    20. Public Property Hand As String
    21. Public Property Bid As Integer
    22. Public Property Type As HandType
    23. Sub New(from As String())
    24. _Hand = from(0)
    25. _Bid = from(1)
    26. chars = _Hand.ToCharArray
    27. _Type = GetHandType()
    28. End Sub
    29. Private Function GetHandType() As HandType
    30. If IsHighCard() Then Return HandType.HighCard
    31. If IsOnePair() Then Return HandType.OnePair
    32. If IsFullHouse() Then Return HandType.FullHouse
    33. If IsTwoPair() Then Return HandType.TwoPair
    34. Return NTuplet()
    35. End Function
    36. Protected Overridable Function IsHighCard() As Boolean
    37. Return chars.Distinct.Count = 5
    38. End Function
    39. Private Function IsOnePair() As Boolean
    40. Return chars.Distinct.Count = 4
    41. End Function
    42. Protected Overridable Function IsFullHouse() As Boolean
    43. Array.Sort(chars)
    44. Select Case chars.Count(Function(c) c = chars(0))
    45. Case 2
    46. Return chars.FirstOrDefault(Function(c) chars.Count(Function(c1) c1 = c) = 3) <> Nothing
    47. Case 3
    48. Return chars.FirstOrDefault(Function(c) chars.Count(Function(c1) c1 = c) = 2) <> Nothing
    49. Case Else
    50. Return False
    51. End Select
    52. End Function
    53. Protected Overridable Function IsTwoPair() As Boolean
    54. Return chars.Length - chars.Distinct.Count = 2 AndAlso Not chars.Any(Function(c) chars.Count(Function(c1) c1 = c) = 3)
    55. End Function
    56. Protected Overridable Function NTuplet() As HandType
    57. Dim n = chars.Length - chars.Distinct.Count
    58. Return If(n > 2, n + 3, HandType.ThreeKind)
    59. End Function
    60. End Class
    61. Friend Enum HandType
    62. HighCard = 1
    63. OnePair
    64. TwoPair
    65. ThreeKind
    66. FullHouse
    67. FourKind
    68. FiveKind
    69. End Enum

    D7 Part2
    In CardValue die Werte anpassen und in Zeile 8 Play durch Play2 ersetzen.

    VB.NET-Quellcode

    1. Friend Class Play2
    2. Inherits Play
    3. Sub New(from As String())
    4. MyBase.New(from)
    5. chars = Hand.ToCharArray.Where(Function(c) c <> "J"c).ToArray
    6. Type = GetHandType()
    7. End Sub
    8. Protected Overrides Function IsHighCard() As Boolean
    9. If chars.Length = 5 Then Return MyBase.IsHighCard
    10. Return False
    11. End Function
    12. Protected Overrides Function IsFullHouse() As Boolean
    13. If chars.Length = 5 Then Return MyBase.IsFullHouse
    14. If chars.Length = 4 Then Return MyBase.IsTwoPair
    15. Return False
    16. End Function
    17. Protected Overrides Function IsTwoPair() As Boolean
    18. If chars.Length = 5 Then Return MyBase.IsTwoPair
    19. Return False
    20. End Function
    21. Protected Overrides Function NTuplet() As HandType
    22. If chars.Length = 5 Then Return MyBase.NTuplet
    23. If chars.Length > 1 Then
    24. Select Case chars.Distinct.Count
    25. Case 1
    26. Return HandType.FiveKind
    27. Case 2
    28. Return HandType.FourKind
    29. Case 3
    30. Return HandType.ThreeKind
    31. End Select
    32. End If
    33. Return HandType.FiveKind
    34. End Function
    35. End Class

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Part 1

    C#-Quellcode

    1. private static void Part01()
    2. {
    3. var withjoker = false;
    4. var cr = CardRank(withjoker);
    5. var hands = Source(FileName).Select(x => x.Split(' ', StringSplitOptions.RemoveEmptyEntries))
    6. .Select(x => new Hands()
    7. {
    8. Id = int.Parse(x[1]),
    9. Cards = x[0],
    10. CardRank = CardRank(withjoker),
    11. Type = ToRank(x[0], withjoker),
    12. CardsPriority = string.Join("", x[0].Select(c => cr[c]))
    13. }).ToArray();
    14. List<Hands> orderhand = [];
    15. foreach (var type in Enum.GetValues<HandType>())
    16. orderhand.AddRange(hands.Where(x => x.Type == type)
    17. .OrderBy(hand => hand.CardsPriority).ToList());
    18. var result = orderhand.Select((x,i) => x.Id * (orderhand.Count - i)).Sum();
    19. Console.WriteLine($"{nameof(Part01)}: {result}");
    20. }

    Part 2

    C#-Quellcode

    1. private static void Part02()
    2. {
    3. var withjoker = true;
    4. var cr = CardRank(withjoker);
    5. var hands = Source(FileName).Select(x => x.Split(' ', StringSplitOptions.RemoveEmptyEntries))
    6. .Select(x => new Hands()
    7. {
    8. Id = int.Parse(x[1]),
    9. Cards = x[0],
    10. Type = ToRank(x[0], withjoker),
    11. CardRank = CardRank(withjoker),
    12. CardsPriority = string.Join("", x[0].Select(c => cr[c]))
    13. }).ToArray();
    14. List<Hands> orderhand = [];
    15. foreach (var type in Enum.GetValues<HandType>())
    16. orderhand.AddRange(hands.Where(x => x.Type == type)
    17. .OrderBy(x => x.CardsPriority).ToList());
    18. var result = orderhand.Select((x, i) => x.Id * (orderhand.Count - i)).Sum();
    19. Console.WriteLine($"{nameof(Part02)}: {result}");
    20. }

    Methoden/Classes

    C#-Quellcode

    1. private static HandType ToRank(string cards, bool withjoker) =>
    2. withjoker ? ToRankWithJoker(cards) : ToRank(cards);
    3. private static HandType ToRank(string cards)
    4. {
    5. if (cards.Length != 5)
    6. throw new ArgumentOutOfRangeException(nameof(cards));
    7. var max = 5;
    8. var group = cards.OrderBy(ch => ch).GroupBy(x => x).ToArray();
    9. var length = group.Length;
    10. return max switch
    11. {
    12. var b when length == 1 => HandType.FiveOfAKind,
    13. var b when length == 2 && group.Count(x => x.Count() == 4) == 1 => HandType.FourOfAKind,
    14. var b when length == 2 && group.Count(x => x.Count() == 3) == 1 => HandType.FullHouse,
    15. var b when length == 3 && group.Count(x => x.Count() == 3) == 1 => HandType.ThreeOfAKind,
    16. var b when length == 3 && group.Count(x => x.Count() == 2) == 2 => HandType.TwoPairs,
    17. var b when length == 4 && group.Count(x => x.Count() == 2) == 1 => HandType.OnePair,
    18. _ => HandType.HighCard,
    19. };
    20. }
    21. private static HandType ToRankWithJoker(string cards)
    22. {
    23. var mintype = int.MaxValue;
    24. var result = HandType.HighCard;
    25. foreach (var card in CardRank(true).Keys.Where(x => x != 'J'))
    26. {
    27. var type = ToRank(cards.Replace("J", card.ToString()));
    28. if ((int)type < mintype)
    29. {
    30. mintype = (int)type;
    31. result = type;
    32. }
    33. }
    34. return result;
    35. }
    36. private readonly static string CARDS = "AKQJT98765432";
    37. private static Dictionary<HandTypes, List<Hands>> HandClasses()
    38. {
    39. var values = Enum.GetValues<HandTypes>();
    40. return values.Select(v => (v, new List<Hands>())).ToDictionary();
    41. }
    42. private static Dictionary<char, char> CardRank(bool with_jocker)
    43. {
    44. var result = CARDS.Select((ch, i) => (ch, (char)('a' + i))).ToDictionary();
    45. if (with_jocker) { result.Remove('J'); result.Add('J', 'o'); }
    46. return result;
    47. }
    48. private class Hands
    49. {
    50. public int Id = 0;
    51. public HandType Type = 0;
    52. public string Cards = string.Empty;
    53. public Dictionary<char, char>? CardRank;
    54. public string CardsPriority = string.Empty;
    55. }
    56. public enum HandType
    57. {
    58. FiveOfAKind ,
    59. FourOfAKind ,
    60. FullHouse ,
    61. ThreeOfAKind ,
    62. TwoPairs ,
    63. OnePair ,
    64. HighCard
    65. }

    Source

    C#-Quellcode

    1. private static string[] Source() =>
    2. [
    3. "32T3K 765",
    4. "T55J5 684",
    5. "KK677 28",
    6. "KTJJT 220",
    7. "QQQJA 483",
    8. ];
    D8 Part 1

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllText(FilePathOfData).Split(vbCrLf & vbCrLf)
    3. Dim LeftRight = input(0).Replace("L"c, "0").Replace("R"c, "1").Select(AddressOf Integer.Parse).ToArray
    4. input(1) = input(1).Replace("("c, String.Empty).Replace(")"c, String.Empty).Replace(" "c, String.Empty)
    5. Dim Mappings = New Dictionary(Of String, String())
    6. For Each line In input(1).Split(vbCrLf)
    7. Dim keyAndValue = line.Split("="c)
    8. Mappings.Add(keyAndValue(0), keyAndValue(1).Split(","c))
    9. Next
    10. Dim MappingKeys = Mappings.Keys
    11. Dim currentMapping = "AAA"
    12. Dim result As Integer
    13. While currentMapping <> "ZZZ"
    14. currentMapping = Mappings(currentMapping)(LeftRight(result Mod LeftRight.Length))
    15. result += 1
    16. End While
    17. End Sub

    Part 2 braucht mit diesem Ansatz wieder signifikant lange... Daher heißts abwarten, ob es überhaupt funktioniert. Jo funktioniert nicht in unter 28 Jahren Rechenzeit

    D8 Part 2

    VB.NET-Quellcode

    1. 'ab Zeile 12
    2. Dim currentMappings = MappingKeys.Where(Function(s) s.EndsWith("A"c)).ToArray
    3. Dim PathResults As New List(Of Long)
    4. For i = 0 To currentMappings.Length - 1
    5. Dim PathResult As Long = 0
    6. While Not currentMappings(i).EndsWith("Z"c)
    7. currentMappings(i) = Mappings(currentMappings(i))(LeftRight(PathResult Mod LeftRight.Length))
    8. PathResult += 1
    9. End While
    10. PathResults.Add(PathResult)
    11. Next
    12. Dim result = PathResults.Aggregate(Function(x, y) x * y / GGT(x, y)) 'aka kgV
    13. Private Function GGT(a As Long, b As Long) As Long
    14. While b <> 0
    15. Dim temp As Long = b
    16. b = a Mod b
    17. a = temp
    18. End While
    19. Return a
    20. End Function

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Part 1

    C#-Quellcode

    1. private static void Part01()
    2. {
    3. var src = Source1().Split("");
    4. var cmds = src.First().First().ToArray();
    5. var map = src.Last().Select(x =>
    6. x.Split(" =,()".ToCharArray(),
    7. StringSplitOptions.RemoveEmptyEntries))
    8. .ToDictionary(x => x.First(), x => new[] { x[1], x[2] });
    9. var directions = new[] { ('L', 0), ('R', 1) }.ToDictionary();
    10. var iter = 0;
    11. var length = cmds.Length;
    12. string end = "ZZZ", start = "AAA";
    13. while (!start.SequenceEqual(end))
    14. start = map[start][directions[cmds[iter++ % length]]];
    15. Console.WriteLine($"{nameof(Part01)}: {iter}");
    16. }

    Part 2

    C#-Quellcode

    1. private static void Part02()
    2. {
    3. var src = Source2().Split("");
    4. var cmds = src.First().First().ToArray();
    5. var map = src.Last().Select(x =>
    6. x.Split(" =,()".ToCharArray(),
    7. StringSplitOptions.RemoveEmptyEntries))
    8. .ToDictionary(x => x.First(), x => new[] { x[1], x[2] });
    9. var directions = new[] { ('L', 0), ('R', 1) }.ToDictionary();
    10. var startvalues = map.Keys.Where(x => x.EndsWith('A')).ToArray();
    11. var result = new long[startvalues.Length];
    12. var length = cmds.Length;
    13. for (int i = 0; i < startvalues.Length; i++)
    14. {
    15. var iter = 0;
    16. while (!startvalues[i].EndsWith('Z'))
    17. startvalues[i] = map[startvalues[i]][directions[cmds[iter++ % length]]];
    18. result[i] = iter;
    19. }
    20. Console.WriteLine($"{nameof(Part02)}: {Lcm(result)}");
    21. }

    Methodes

    C#-Quellcode

    1. private static long Gcd(long left, long right)
    2. {
    3. if (right == 0) return left;
    4. else return Gcd(right, left % right);
    5. }
    6. private static long Lcm(long[] values) =>
    7. values.Aggregate((a, b) => a * b / Gcd(a, b));

    Source

    C#-Quellcode

    1. private static string[] Source1() =>
    2. [
    3. "LLR",
    4. "",
    5. "AAA = (BBB, BBB)",
    6. "BBB = (AAA, ZZZ)",
    7. "ZZZ = (ZZZ, ZZZ)",
    8. ];
    9. private static string[] Source2() =>
    10. [
    11. "LR",
    12. "",
    13. "11A = (11B,XXX)",
    14. "11B = (XXX, 11Z)",
    15. "11Z = (11B,XXX)",
    16. "22A = (22B,XXX)",
    17. "22B = (22C,22C)",
    18. "22C = (22Z,22Z)",
    19. "22Z = (22B,22B)",
    20. ",XXX = (XXX, XXX)",
    21. ];

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „exc-jdbi“ ()

    Mit BruteForce hätte es wohl Tage für Part2 gedauert …
    Part1 ist mit BruteForce gelöst.
    Zum Glück hat es beim ersten Part2-BruteForceDurchgang zwischendurch irgendwann Klick gemacht und das Ergebnis ist nach Codekorrektur in weniger als 1 Sekunde da.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend Class ValueCalculatorForDay7
    2. Private ReadOnly StepSequence As New List(Of Integer)
    3. Private ReadOnly Checkpoints As New Dictionary(Of String, String())
    4. Private StepsToReachExit As Long
    5. Function GetValuesFor(FilePath As String) As (Long, Long)
    6. Dim RawDataLines = GetRawDataFrom(FilePath)
    7. ParseRawData(RawDataLines)
    8. FollowPathAsHuman()
    9. Dim Part1Value = StepsToReachExit
    10. StepsToReachExit = 0
    11. FollowPathsAsGhost()
    12. Dim Part2Value = StepsToReachExit
    13. Return (Part1Value, Part2Value)
    14. End Function
    15. Private Function GetRawDataFrom(FilePath As String) As IEnumerable(Of String)
    16. Return IO.File.ReadAllLines(FilePath)
    17. End Function
    18. Private Sub ParseRawData(RawDataLines As IEnumerable(Of String))
    19. For Each Character In RawDataLines(0)
    20. If Character = "L" Then StepSequence.Add(0)
    21. If Character = "R" Then StepSequence.Add(1)
    22. Next
    23. For Each RawDataLine In RawDataLines.Skip(2)
    24. Dim RawData = RawDataLine.Split({"=", "(", ")", ","c, " "c}, StringSplitOptions.RemoveEmptyEntries)
    25. Checkpoints.Add(RawData(0), {RawData(1), RawData(2)})
    26. Next
    27. End Sub
    28. Private Sub FollowPathAsHuman()
    29. Dim CurrentCheckpointMarkers = Checkpoints.Where(Function(x) x.Key = "AAA").Select(Function(x) x.Key).ToArray
    30. Do
    31. For Each SingleStep In StepSequence
    32. For i = 0 To CurrentCheckpointMarkers.Count - 1
    33. Dim PossibleDestinations = Checkpoints(CurrentCheckpointMarkers(i))
    34. CurrentCheckpointMarkers(i) = PossibleDestinations(SingleStep)
    35. Next
    36. StepsToReachExit += 1
    37. If CurrentCheckpointMarkers.All(Function(x) x = "ZZZ") Then Exit Do
    38. Next
    39. Loop
    40. End Sub
    41. Private Sub FollowPathsAsGhost()
    42. Dim CurrentCheckpointMarkers = Checkpoints.Where(Function(x) x.Key(2) = "A"c).Select(Function(x) x.Key).ToArray
    43. Dim StepsToTakeForAll As New List(Of Integer)
    44. For i = 0 To CurrentCheckpointMarkers.Count - 1
    45. Dim TempStepsToReachExit = 0
    46. Do
    47. For Each SingleStep In StepSequence
    48. CurrentCheckpointMarkers(i) = Checkpoints(CurrentCheckpointMarkers(i))(SingleStep)
    49. Next
    50. TempStepsToReachExit += 1
    51. If CurrentCheckpointMarkers(i)(2) = "Z" Then
    52. StepsToTakeForAll.Add(TempStepsToReachExit)
    53. Exit Do
    54. End If
    55. Loop
    56. Next
    57. StepsToReachExit = 1
    58. For Each StepsToTakeForAllForOnePath In StepsToTakeForAll
    59. StepsToReachExit *= StepsToTakeForAllForOnePath
    60. Next
    61. StepsToReachExit *= StepSequence.Count
    62. End Sub
    63. End Class


    btw: Ich glaube, dass die Rätsel so ausgelegt sind, dass man auf die Ergebnisse immer in wenigen Sekunden (< 5) kommt. Tag 5 Teil 2 war ja bisher übel, aber laut diesem youtube-Video geht es wohl auch fix. Wenn man blickt, was da passiert :S
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    VaporiZed schrieb:

    Tag 5 Teil 2 war ja bisher übel, aber laut diesem youtube-Video geht es wohl auch fix.
    Auch laut mir, siehe Post 60 bzw. mein aktualisierter Tag 5^^

    @VaporiZed
    Spoiler anzeigen
    Ah, die Lösung ist kgV der einzelnen Lösungswege natürlich. Ob so ein Trick bei Tag 5 vielleicht die eigentliche Lösung ist?

    VaporiZed schrieb:

    btw: Ich glaube, dass die Rätsel so ausgelegt sind, dass man auf die Ergebnisse immer in wenigen Sekunden (< 5) kommt. Tag 5 Teil 2 war ja bisher übel, aber laut diesem youtube-Video geht es wohl auch fix. Wenn man blickt, was da passiert


    Nunja es gibt IMMER irgendeinen Algo um die Sachen super schnell zu machen.
    Oder irgendeine Logik wo man direkt 90% der Daten gar nicht durchsuchen muss.
    Da muss man aber dann erstmal drauf kommen. Gibt die supercracks die natürlich jeden Algo im Kopf haben und das direkt sehen.
    Auch einer der Gründe den AoC zu machen - man lernt dabei sehr viel grad durch die Lösungen von anderen.
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen
    Tag 8
    Alles wild durcheinander bei mir. Ich stelle fest, dass ich die Aufgaben nicht genau genug lese, wodurch sich meine Lösung zu lange hinzieht :D. Ich poste mal nur Part 2.
    Spoiler anzeigen

    C#-Quellcode

    1. using System.Collections.Frozen;
    2. using System.Numerics;
    3. List<string> startKeys = new();
    4. string directions = string.Empty;
    5. var lookupSet = ReadFile().ToFrozenDictionary();
    6. List<long> v = new();
    7. foreach (string k in startKeys)
    8. {
    9. v.Add(Find(k));
    10. }
    11. long result = v.LeastCommonMultiple();
    12. System.Console.WriteLine(result);
    13. int Find(string k)
    14. {
    15. ReadOnlySpan<char> d = directions.AsSpan();
    16. int steps = 0;
    17. int commandLen = d.Length;
    18. bool found = false;
    19. while (!found)
    20. {
    21. switch (d[steps % commandLen])
    22. {
    23. case 'L':
    24. k = lookupSet[k][0];
    25. break;
    26. case 'R':
    27. k = lookupSet[k][1];
    28. break;
    29. }
    30. found = k.EndsWith('Z');
    31. ++steps;
    32. }
    33. return steps;
    34. }
    35. Dictionary<string, string[]> ReadFile()
    36. {
    37. using FileStream fs = File.OpenRead(@"C:\Dev\dotnet\AdventOfCode\2023\Day8\input.txt");
    38. using StreamReader sr = new(fs);
    39. Dictionary<string, string[]> dict = new();
    40. int i = 0;
    41. while (!sr.EndOfStream)
    42. {
    43. var lineSpan = sr.ReadLine().AsSpan();
    44. if (directions.Length == 0)
    45. directions = lineSpan.ToString();
    46. else if (lineSpan.Length > 0)
    47. {
    48. string x = lineSpan[0..3].ToString();
    49. dict.Add(x, [lineSpan[7..10].ToString(), lineSpan[12..15].ToString()]);
    50. if (lineSpan[2] == 'A')
    51. startKeys.Add(x);
    52. ++i;
    53. }
    54. }
    55. return dict;
    56. }
    57. public static class MathHelpers
    58. {
    59. public static T GreatestCommonDivisor<T>(T a, T b) where T : INumber<T>
    60. {
    61. while (b != T.Zero)
    62. {
    63. var temp = b;
    64. b = a % b;
    65. a = temp;
    66. }
    67. return a;
    68. }
    69. public static T LeastCommonMultiple<T>(T a, T b) where T : INumber<T>
    70. => a / GreatestCommonDivisor(a, b) * b;
    71. public static T LeastCommonMultiple<T>(this IEnumerable<T> values) where T : INumber<T>
    72. => values.Aggregate(LeastCommonMultiple);
    73. }
    @Haudruferzappeltnoch: Oh, hatte ich wohl übersehen. Zieh ich mir bei Gelegenheit nochmal rein.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ich denke ich muss mal schauen.. Part1 läuft seit 15 Minuten und noch kein Ergebnis.
    Manchmal will man einfach auf nen Spoiler drücken aber durchhalten irgendwo ist die denk Blockade die mich noch abhält glaub ich.
    /EDIT/ Geil... Richtig hart rein gesch.... Hab einfach mal ein extrem wichtiges Element übersehen... Part1 ist erledigt... auf zu Part2
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „xChRoNiKx“ ()

    @Haudruferzappeltnoch nene ich meine Part1.... Im Spoiler mal mein "versagen"

    Spoiler anzeigen

    Ich habe das ERSTE Element genommen aus dem Input als Startelement.... Ich muss aber doch AAA als erstes nehmen.
    Mit AAA als Startelement gings dann in na sekunde oder drunter durch.

    Part2 klingt Interessant... Ich bastel mal.
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen
    Ich hatte bei meinem Part2-BruteForce-Versuch 2x nach mehreren Minuten (5, 15) pausiert und das Zwischenergebnis bei AoC reingestellt. Da beides Mal kam, dass das Ergebnis zu klein ist, wusste ich, dass da was sehr großes rauskommt und dass ich einen besseren Weg finden musste. Dann kam dann der Geistesblitz.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Das war auch nicht zwangsläufig so vorgesehen. Da ich aber
    Spoiler anzeigen
    mit dem kgV aller Pfadschrittzahlen immer noch auf einen zu niedrigen Wert gekommen bin, wurde mir klar, dass dieses Ergebnis nur dann Sinn ergeben würde, wenn es in der Schrittsequenz immer nur einen Schritt geben würde. Da die Schrittfolge aber sehr lang ist, wurde mir bewusst, dass bei zig Schritten alle Pfade woanders rauskommen, selbst bei deren kgV. Daher hab ich (auf gut Glück) noch die Schrittzahl der Sequenz aufmultipliziert und zum Glück das richtige Ergebnis gehabt. Ansonsten hätte ich noch geschaut, ob es nicht noch n kleineres kgV von allen gäbe.
    Hatte mir zwischendurch noch überlegt, einen kgV-Rechner für x Zahlen zu schreiben, aber das wäre erst relevant geworden, wenn AoC mir gesagt hätte, dass mein Ergebnis wieder nicht stimmt. Von daher: Schwein gehabt.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Oooookey.... Wasn Krampf... Part1 und Part2 in einem... Ohne lange warten. Einfach mal den Kopf richtig nutzen.
    Jetzt freu ich mich erstmal drauf auch andere Lösungen mal anzuschauen.

    Spoiler anzeigen

    Nachdem mein Kopf dann mal gesehen hat das ich hier einfach mit LCM/GCF ( ehm deutsche abkürzungen weiß ich nicht aber größten gemeinsamen teiler und dem kleinsten gemeinsamen vielfachen? ) rechnen kann gings dann nochmal neu mit code los..
    Also einfach Steps zählen bis ende und ab einmal drüber rechnen lassen.
    Hat mich jetzt viel Zeit gekostet weil ich einfach die Möglichkeit nicht gesehen habe.

    C#-Quellcode

    1. using System.Text.RegularExpressions;
    2. using System.Timers;
    3. namespace Tag08
    4. {
    5. internal class Program
    6. {
    7. static void Main(string[] args)
    8. {
    9. string[] exampleFile = File.ReadAllLines("Example.txt");
    10. string[] exampleFile2 = File.ReadAllLines("Example2.txt");
    11. string[] inputFile = File.ReadAllLines("Input.txt");
    12. Wasteland example = new Wasteland(exampleFile);
    13. Wasteland example2 = new Wasteland(exampleFile2);
    14. Wasteland input = new Wasteland(inputFile);
    15. Console.WriteLine($"Example: {example.CalculateSteps().Aggregate(lcm)}");
    16. Console.WriteLine($"Example 2: {example2.CalculateSteps(true).Aggregate(lcm)}");
    17. Console.WriteLine($"Input Part 1: {input.CalculateSteps().Aggregate(lcm)}");
    18. Console.WriteLine($"Input Part 2: {input.CalculateSteps(true).Aggregate(lcm)}");
    19. }
    20. static long gcf(long a, long b)
    21. {
    22. while (b != 0)
    23. {
    24. long temp = b;
    25. b = a % b;
    26. a = temp;
    27. }
    28. return a;
    29. }
    30. static long lcm(long a, long b)
    31. {
    32. return (a / gcf(a, b)) * b;
    33. }
    34. }
    35. public class Wasteland
    36. {
    37. HashSet<Place> map = new HashSet<Place>();
    38. public string DirectionPattern = "";
    39. public Wasteland(string[] lines)
    40. {
    41. DirectionPattern = lines[0];
    42. foreach (string line in lines.Skip(2))
    43. {
    44. var matches = Regex.Matches(line, "(\\w+)");
    45. Place place = new Place();
    46. Instruction inst = new Instruction();
    47. place.Name = matches[0].Value;
    48. inst.Left = matches[1].Value;
    49. inst.Right = matches[2].Value;
    50. place.Instruction = inst;
    51. map.Add(place);
    52. }
    53. }
    54. public List<long> CalculateSteps(bool part2 = false)
    55. {
    56. int directionCount = 0;
    57. int directionPatternLength = DirectionPattern.Length - 1;
    58. List<long> listOfStepsToFinish = new List<long>();
    59. List<Place> places = new List<Place>();
    60. if (part2)
    61. {
    62. places = map.Where(x => x.Name.EndsWith('A')).ToList();
    63. }
    64. else
    65. {
    66. places = map.Where(x => x.Name == "AAA").ToList();
    67. }
    68. foreach (Place place in places)
    69. {
    70. long steps = 0;
    71. Place currentPlace = place;
    72. while(!currentPlace.Name.EndsWith('Z'))
    73. {
    74. if (DirectionPattern[directionCount] == 'L')
    75. {
    76. currentPlace = map.First(x => x.Name == currentPlace.Instruction.Left);
    77. }
    78. else
    79. {
    80. currentPlace = map.First(x => x.Name == currentPlace.Instruction.Right);
    81. }
    82. steps++;
    83. if (directionCount >= directionPatternLength)
    84. {
    85. directionCount = 0;
    86. }
    87. else
    88. {
    89. directionCount++;
    90. }
    91. }
    92. listOfStepsToFinish.Add(steps);
    93. }
    94. return listOfStepsToFinish;
    95. }
    96. }
    97. public class Place
    98. {
    99. public string Name { get; set; }
    100. public Instruction Instruction { get; set; }
    101. }
    102. public class Instruction
    103. {
    104. public string Left { get; set; }
    105. public string Right { get; set; }
    106. }
    107. }
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen