Advent of Code 2023

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

    Part 1

    C#-Quellcode

    1. private static void Part01()
    2. {
    3. var src = Source(FileName)
    4. .Select(x => x.Split(" ",
    5. StringSplitOptions.RemoveEmptyEntries)
    6. .Select(int.Parse).ToArray());
    7. var result = 0;
    8. foreach (var numbers in src)
    9. result += ToAllZeroDifferences(numbers)
    10. .ToArray().Reverse().Sum(x => x.Last());
    11. Console.WriteLine($"{nameof(Part01)}: {result}");
    12. }

    Part 2

    C#-Quellcode

    1. private static void Part02()
    2. {
    3. var src = Source(FileName)
    4. .Select(x => x.Split(" ",
    5. StringSplitOptions.RemoveEmptyEntries)
    6. .Select(int.Parse).ToArray());
    7. var result = 0;
    8. foreach (var numbers in src)
    9. {
    10. var sum = 0;
    11. var tmp = ToAllZeroDifferences(numbers)
    12. .ToArray().Reverse().ToArray();
    13. for (var i = 1; i < tmp.Length; i++)
    14. sum = tmp[i].First() - sum;
    15. result += sum;
    16. }
    17. Console.WriteLine($"{nameof(Part02)}: {result}");
    18. }

    Methoden

    C#-Quellcode

    1. private static List<List<int>> ToAllZeroDifferences(int[] numbers)
    2. {
    3. var result = new List<List<int>> { numbers.ToList() };
    4. while (true)
    5. {
    6. var tmp = new List<int>();
    7. for (var i = 1; i < result.Last().Count; i++)
    8. tmp.Add(result.Last()[i] - result.Last()[i - 1]);
    9. result.Add(tmp);
    10. if (tmp.Sum() == 0) return result;
    11. }
    12. }

    Source

    C#-Quellcode

    1. private static string[] Source() =>
    2. [
    3. "0 3 6 9 12 15",
    4. "1 3 6 10 15 21",
    5. "10 13 16 21 30 45",
    6. ];

    Optimized

    C#-Quellcode

    1. private static void Part01_20_LINQ()
    2. {
    3. static int[][] Differences(int[] numbers)
    4. {
    5. var result = new List<int[]> { numbers };
    6. while (result.Last().Sum() != 0) result.Add(Difference(result.Last()));
    7. return [.. result];
    8. }
    9. static int[] Difference(int[] numbers) =>
    10. numbers.Zip(numbers.Skip(1)).Select(p => p.Second - p.First).ToArray();
    11. var part_1 = Source()
    12. .Select(x => x.Split(" ",
    13. StringSplitOptions.RemoveEmptyEntries)
    14. .Select(int.Parse).ToArray()).Select(Differences).ToArray()
    15. .Select(x => x.Reverse().Sum(y=>y.Last())).Sum();
    16. Console.WriteLine($"{nameof(Part01)}: {part_1}");
    17. var part_2 = Source()
    18. .Select(x => x.Split(" ",
    19. StringSplitOptions.RemoveEmptyEntries)
    20. .Select(int.Parse).ToArray()).Select(Differences).ToArray()
    21. .Select(x => x.Reverse().Aggregate(0, (a, b) => -a + b.First())).Sum();
    22. Console.WriteLine($"{nameof(Part02)}: {part_2}");
    23. }

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

    Mist, ich dachte, es würde etwas bringen, wenn man weiß, dass
    Spoiler anzeigen
    es sich letztenendes um polynomische Gleichungen handelt.

    Aber wurscht, hat trotzdem geklappt.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend Class ValueCalculatorForDay8
    2. Private ReadOnly Sequences As New List(Of IEnumerable(Of Long))
    3. Private ReadOnly SequencePacks As New Stack(Of SequencePack)
    4. Private Part1Value As Long
    5. Private Part2Value As Long
    6. Function GetValuesFor(FilePath As String) As (Long, Long)
    7. Dim RawDataLines = GetRawDataFrom(FilePath)
    8. ParseRawDataLines(RawDataLines)
    9. CalculatePart1Values()
    10. CalculatePart2Values()
    11. Return (Part1Value, Part2Value)
    12. End Function
    13. Private Function GetRawDataFrom(FilePath As String) As IEnumerable(Of String)
    14. Return IO.File.ReadAllLines(FilePath)
    15. End Function
    16. Private Sub ParseRawDataLines(RawDataLines As IEnumerable(Of String))
    17. For Each RawDataLine In RawDataLines
    18. Sequences.Add(RawDataLine.Split.Select(Function(x) Long.Parse(x)).ToArray)
    19. Next
    20. End Sub
    21. Private Sub CalculatePart1Values()
    22. For Each Sequence In Sequences
    23. CalculatePart1ValueFor(Sequence)
    24. Next
    25. End Sub
    26. Private Sub CalculatePart1ValueFor(Sequence As IEnumerable(Of Long))
    27. AddNewSequencePack(Sequence)
    28. Dim AdderOfPreviousSequence = 0L
    29. Do
    30. Dim TopSequencePack = SequencePacks.Pop()
    31. Dim NextValue = TopSequencePack.GetNextValueFrom(AdderOfPreviousSequence)
    32. AdderOfPreviousSequence = NextValue
    33. If SequencePacks.Count = 0 Then
    34. Part1Value += NextValue
    35. Exit Do
    36. End If
    37. Loop
    38. End Sub
    39. Private Sub CalculatePart2Values()
    40. For Each Sequence In Sequences
    41. CalculatePart2ValueFor(Sequence)
    42. Next
    43. End Sub
    44. Private Sub CalculatePart2ValueFor(Sequence As IEnumerable(Of Long))
    45. AddNewSequencePack(Sequence)
    46. Dim AdderOfPreviousSequence = 0L
    47. Do
    48. Dim TopSequencePack = SequencePacks.Pop()
    49. Dim PreviousValue = TopSequencePack.GetPreviousValueFrom(AdderOfPreviousSequence)
    50. AdderOfPreviousSequence = PreviousValue
    51. If SequencePacks.Count = 0 Then
    52. Part2Value += PreviousValue
    53. Exit Do
    54. End If
    55. Loop
    56. End Sub
    57. Private Sub AddNewSequencePack(Sequence As IEnumerable(Of Long))
    58. Dim NewSequencePack = New SequencePack(Sequence)
    59. SequencePacks.Push(NewSequencePack)
    60. If Not NewSequencePack.HasEqualAdders Then AddNewSequencePack(GetCurrentAddersFor(Sequence))
    61. End Sub
    62. Private Function GetCurrentAddersFor(Sequence As IEnumerable(Of Long)) As IEnumerable(Of Long)
    63. Dim CurrentAdders As New List(Of Long)
    64. For i = 1 To Sequence.Count - 1
    65. CurrentAdders.Add(Sequence(i) - Sequence(i - 1))
    66. Next
    67. Return CurrentAdders
    68. End Function
    69. End Class
    70. Friend Class SequencePack
    71. Property Sequence As New List(Of Long)
    72. Sub New(Sequence As IEnumerable(Of Long))
    73. Me.Sequence.AddRange(Sequence)
    74. End Sub
    75. Function HasEqualAdders() As Boolean
    76. Return Sequence.Distinct.Count = 1
    77. End Function
    78. Function GetNextValueFrom(Adder As Long) As Long
    79. Return Sequence(Sequence.Count - 1) + Adder
    80. End Function
    81. Function GetPreviousValueFrom(Adder As Long) As Long
    82. Return Sequence(0) - Adder
    83. End Function
    84. End Class

    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.
    Tag 9

    Part 1
    Spoiler anzeigen

    C#-Quellcode

    1. using FileStream fs = File.OpenRead(@"C:\Dev\dotnet\AdventOfCode\2023\Day9\input.txt");
    2. using StreamReader sr = new(fs);
    3. int total = 0;
    4. while (!sr.EndOfStream)
    5. {
    6. var lineSpan = sr.ReadLine().AsSpan();
    7. int[] values = ParseValues(SplitLine(lineSpan), lineSpan);
    8. Dictionary<int, IEnumerable<int>> differences = new();
    9. int iter = 0;
    10. differences.Add(iter++, values);
    11. bool endReached = false;
    12. while (!endReached)
    13. {
    14. List<int> l = new();
    15. for (int i = 0; i < values.Length - 1; ++i)
    16. {
    17. // l.Add(Math.Abs(values[i] - values[i + 1]));
    18. l.Add(values[i + 1] - values[i]);
    19. }
    20. endReached = l.All(i => i == 0);
    21. values = l.ToArray();
    22. differences.Add(iter, l);
    23. ++iter;
    24. }
    25. int last = 0;
    26. for (int i = iter - 2; i >= 0; --i)
    27. {
    28. last += differences[i].Last();
    29. }
    30. total += last;
    31. }
    32. System.Console.WriteLine(total);
    33. Range[] SplitLine(ReadOnlySpan<char> lines)
    34. {
    35. Range[] ranges = new Range[lines.Count(' ') + 1];
    36. lines.Split(ranges, ' ');
    37. return ranges;
    38. }
    39. int[] ParseValues(Range[] ranges, ReadOnlySpan<char> line)
    40. {
    41. int[] values = new int[ranges.Length];
    42. for (int i = 0; i < ranges.Length; ++i)
    43. {
    44. values[i] = int.Parse(line[ranges[i]]);
    45. }
    46. return values;
    47. }​


    Part 2
    Spoiler anzeigen

    C#-Quellcode

    1. int total = 0;
    2. while (!sr.EndOfStream)
    3. {
    4. var lineSpan = sr.ReadLine().AsSpan();
    5. int[] values = ParseValues(SplitLine(lineSpan), lineSpan);
    6. Dictionary<int, IEnumerable<int>> differences = new();
    7. int iter = 0;
    8. differences.Add(iter++, values);
    9. bool endReached = false;
    10. while (!endReached)
    11. {
    12. List<int> l = new();
    13. for (int i = 0; i < values.Length - 1; ++i)
    14. {
    15. l.Add(values[i + 1] - values[i]);
    16. }
    17. endReached = l.All(i => i == 0);
    18. values = l.ToArray();
    19. if (!endReached)
    20. {
    21. differences.Add(iter, l);
    22. ++iter;
    23. }
    24. }
    25. int last = differences[iter - 1].First();
    26. for (int i = iter - 2; i >= 0; --i)
    27. {
    28. last = differences[i].First() - last;
    29. }
    30. total += last;
    31. }​
    D9 Part 1

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllLines(FilePathOfData) '21 Elemente pro Line
    3. Dim Arrays = input.Select(Function(s) s & " 0").Select(Function(l) l.Split(" "c).Select(AddressOf Integer.Parse).ToArray).ToArray
    4. For i = 0 To Arrays.Length - 1
    5. Arrays(i)(21) = BuildLastIndex(Arrays(i).Take(21).ToArray)
    6. Next
    7. Dim result = Arrays.Sum(Function(a) a.Last)
    8. End Sub
    9. Private Function BuildLastIndex(a As Integer()) As Integer
    10. Return a.Last + BreakDown(a).Last
    11. End Function
    12. Private Function BreakDown(a As Integer()) As Integer()
    13. Dim lastidx = a.Length - 1
    14. Dim b(lastidx) As Integer
    15. For i = 0 To b.Length - 2
    16. b(i) = a(i + 1) - a(i)
    17. Next
    18. Dim reducedb = b.Take(lastidx).ToArray
    19. b(lastidx) = If(reducedb.Distinct.Count = 1, b.First, BuildLastIndex(reducedb))
    20. Return b
    21. End Function

    Part 2 wirkt erstmal stumpf, mal schauen, ob es wirklich so ist.
    D9 Part2
    Jo, wär wahrscheinlich schöner beides gleichzeitig zu berechnen

    VB.NET-Quellcode

    1. Dim Arrays = input.Select(Function(s) "0 " & s).Select(Function(l) l.Split(" "c).Select(AddressOf Integer.Parse).ToArray).ToArray
    2. For i = 0 To Arrays.Length - 1
    3. Arrays(i)(0) = BuildFirstIndex(Arrays(i).TakeLast(21).ToArray)
    4. Next
    5. Dim result = Arrays.Sum(Function(a) a.First)
    6. Private Function BuildFirstIndex(a As Integer()) As Integer
    7. Return a.First - BreakDown(a).First
    8. End Function
    9. Private Function BreakDown(a As Integer()) As Integer()
    10. Dim lastidx = a.Length - 1
    11. Dim b(lastidx) As Integer
    12. For i = 1 To b.Length - 1
    13. b(i) = a(i) - a(i - 1)
    14. Next
    15. Dim reducedb = b.TakeLast(lastidx).ToArray
    16. b(0) = If(reducedb.Distinct.Count = 1, b.Last, BuildFirstIndex(reducedb))
    17. Return b
    18. End Function

    @VaporiZed
    Spoiler anzeigen
    Mit Polynomen hat es ja zu tun, aber ich weiß nicht ob der Ansatz einfacher wäre. Taylorreihen kann ich nicht einfach aus dem Stehgreif hincoden.

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

    Omg, dieses Jahr hab ich total darauf vergessen, war auch schon lange nicht mehr hier.
    Glaub' für mich wird das nichts dieses Jahr, aber euch wünsche ich viel Spaß. :)
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------
    Teil1 habe ich, aber Teil 2 kommt mir vor wie bei einem Malprogramm: Fülle alles aus, was innerhalb des unrandeten Bereichs liegt und zähl die Pixel :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.
    Mein erster Versuch bei Part 1 ging in die Hose und ich weiß nicht warum. Da steht in der Aufgabe es gäbe nur eine einzige Schleife. Ich habe ein paar Mini-Schleifen drin, gut vielleicht Zufall, die konnte ich entfernen, aber gibt es da vielleicht noch andere kleine Schleifen > Länge 4? Das wäre zumindest eine mögliche Ursache, die ich begreife. Doofer Fehler habe erst ganz anders gezählt und dabei eben auch verzählt.
    D10 Part 1
    Die "Corrected" Data wurde von Mini-Schleifen "F7JL" befreit. Man kann die Anzahl die dadurch verkehrt wird aber auch mit demselben Code berechnen, wenn man in den Connections das "S"c weglässt. Dann wäre Error = 2*result - 1

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllLines(FilePathOfCorrectedData)
    3. 'width 142
    4. Dim Chars = input.Select(Function(s) s.ToCharArray).ToArray
    5. Dim compareSequence = Chars.SelectMany(Function(s) s)
    6. Dim ConnectLeft = {"-"c, "L"c, "F"c, "S"c}
    7. Dim ConnectRight = {"-"c, "7"c, "J"c, "S"c}
    8. Dim ConnectUp = {"|"c, "7"c, "F"c, "S"c}
    9. Dim ConnectDown = {"|"c, "J"c, "L"c, "S"c}
    10. Dim prevSequence = Array.Empty(Of Char)
    11. While Not prevSequence.SequenceEqual(compareSequence)
    12. prevSequence = Chars.SelectMany(Function(s) s).ToArray
    13. For x = 1 To 140
    14. For y = 1 To Chars.Length - 2
    15. Select Case Chars(y)(x)
    16. Case "F"c
    17. If Not ConnectRight.Contains(Chars(y)(x + 1)) OrElse Not ConnectDown.Contains(Chars(y + 1)(x)) Then Chars(y)(x) = "."c
    18. Case "J"c
    19. If Not ConnectLeft.Contains(Chars(y)(x - 1)) OrElse Not ConnectUp.Contains(Chars(y - 1)(x)) Then Chars(y)(x) = "."c
    20. Case "-"c
    21. If Not ConnectLeft.Contains(Chars(y)(x - 1)) OrElse Not ConnectRight.Contains(Chars(y)(x + 1)) Then Chars(y)(x) = "."c
    22. Case "|"c
    23. If Not ConnectUp.Contains(Chars(y - 1)(x)) OrElse Not ConnectDown.Contains(Chars(y + 1)(x)) Then Chars(y)(x) = "."c
    24. Case "7"c
    25. If Not ConnectLeft.Contains(Chars(y)(x - 1)) OrElse Not ConnectDown.Contains(Chars(y + 1)(x)) Then Chars(y)(x) = "."c
    26. Case "L"c
    27. If Not ConnectUp.Contains(Chars(y - 1)(x)) OrElse Not ConnectRight.Contains(Chars(y)(x + 1)) Then Chars(y)(x) = "."c
    28. End Select
    29. Next
    30. Next
    31. End While
    32. Dim result = compareSequence.Count(Function(c) c <> "."c) / 2
    33. End Sub

    D10 Part2
    Entgegen der ursprünglichen Idee, hier etwas zur Pfadverfolgung.
    Wenn man die Lösung aus Part 1 in eine Datei ausgibt und diese als input verwendet, dann wird hier widerum eine Datei ausgeben die alle eigeschlossenen Fläche mit I umrandet.
    Große Flächen beinhalten weiterhin .. Die sind aber abzählbar

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllLines(FilePathOfInvalidTilesClearedData)
    3. Dim Chars = input.Select(Function(s) s.ToCharArray).ToArray
    4. Dim CharsAsSequence = Chars.SelectMany(Function(s) s).ToArray
    5. Dim y = 31 'Position S
    6. Dim x = 111 'Position S
    7. Dim dir = Direction.Down
    8. Dim system As New List(Of Tile) From {New Tile(Chars(y)(x), dir)}
    9. While Chars(y + 1)(x) <> "S"c
    10. Dim T = New Tile(Chars(y)(x), dir)
    11. system.Add(T)
    12. Select Case True
    13. Case Chars(y)(x) = "7"c AndAlso dir = Direction.Right
    14. If Chars(y - 1)(x) = "."c Then Chars(y - 1)(x) = "I"c
    15. If Chars(y)(x + 1) = "."c Then Chars(y)(x + 1) = "I"c
    16. Case Chars(y)(x) = "F"c AndAlso dir = Direction.Up
    17. If Chars(y - 1)(x) = "."c Then Chars(y - 1)(x) = "I"c
    18. If Chars(y)(x - 1) = "."c Then Chars(y)(x - 1) = "I"c
    19. Case Chars(y)(x) = "-"c
    20. If dir = Direction.Right AndAlso Chars(y - 1)(x) = "."c Then Chars(y - 1)(x) = "I"c
    21. If dir = Direction.Left AndAlso Chars(y + 1)(x) = "."c Then Chars(y + 1)(x) = "I"c
    22. Case Chars(y)(x) = "|"c
    23. If dir = Direction.Up AndAlso Chars(y)(x - 1) = "."c Then Chars(y)(x - 1) = "I"c
    24. If dir = Direction.Down AndAlso Chars(y)(x + 1) = "."c Then Chars(y)(x + 1) = "I"c
    25. Case Chars(y)(x) = "J"c AndAlso dir = Direction.Down
    26. If Chars(y + 1)(x) = "."c Then Chars(y + 1)(x) = "I"c
    27. If Chars(y)(x + 1) = "."c Then Chars(y)(x + 1) = "I"c
    28. Case Chars(y)(x) = "L"c AndAlso dir = Direction.Left
    29. If Chars(y + 1)(x) = "."c Then Chars(y + 1)(x) = "I"c
    30. If Chars(y)(x - 1) = "."c Then Chars(y)(x - 1) = "I"c
    31. End Select
    32. dir = T.ExitDirection
    33. Select Case dir
    34. Case Direction.Up
    35. y -= 1
    36. Case Direction.Down
    37. y += 1
    38. Case Direction.Left
    39. x -= 1
    40. Case Direction.Right
    41. x += 1
    42. End Select
    43. End While
    44. IO.File.WriteAllLines(FilePathOfResult, Chars.Select(Function(s) String.Join("", s)))
    45. End Sub
    46. Friend Enum Direction
    47. Right
    48. Down
    49. Left
    50. Up
    51. End Enum
    52. Friend Class Tile
    53. ReadOnly Property [Char] As Char
    54. ReadOnly Property EntryDirection As Direction
    55. ReadOnly Property ExitDirection As Direction
    56. Sub New(c As Char, entering As Direction)
    57. _Char = c
    58. _EntryDirection = entering
    59. _ExitDirection = GetExit()
    60. End Sub
    61. Private Function GetExit() As Direction
    62. Select Case _Char
    63. Case "7"c
    64. Return If(_EntryDirection = Direction.Right, Direction.Down, Direction.Left)
    65. Case "F"c
    66. Return If(_EntryDirection = Direction.Left, Direction.Down, Direction.Right)
    67. Case "-"c
    68. Return If(_EntryDirection = Direction.Right, Direction.Right, Direction.Left)
    69. Case "|"c
    70. Return If(_EntryDirection = Direction.Down, Direction.Down, Direction.Up)
    71. Case "J"c
    72. Return If(_EntryDirection = Direction.Down, Direction.Left, Direction.Up)
    73. Case "L"c, "S"c
    74. Return If(_EntryDirection = Direction.Down, Direction.Right, Direction.Up)
    75. Case Else
    76. Throw New Exception("Invalid Data")
    77. End Select
    78. End Function
    79. End Class



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

    Prime Directive

    C#-Quellcode

    1. using Map = Dictionary<(int X, int Y), char>;

    Part 1

    C#-Quellcode

    1. private static void Part01()
    2. {
    3. var (route, _) = FollowRoute(ToMap(Source()));
    4. Console.WriteLine($"{nameof(Part01)}: {route.Count / 2}");
    5. }

    Part 2

    C#-Quellcode

    1. private static void Part02()
    2. {
    3. var map = ToMap(Source());
    4. var (route, turns) = FollowRoute(map);
    5. var result = FindInnerTiles(map, route, turns > 0);
    6. Console.WriteLine($"{nameof(Part02)}: {result.Count}");
    7. }

    Methodes

    C#-Quellcode

    1. private static (HashSet<(int X, int Y)> Route, int Turns) FollowRoute(Map map)
    2. {
    3. // - Start S suchen
    4. // - Alle möglichen directionen festlegen.
    5. // - Alle möglichen directionen in der aktuellen Position der Map
    6. // prüfen, ob sie als Kacheln vorhanden sind, und wenn ja, nimm
    7. // den ersten für die "route"
    8. // - Folge der gegebenen Route bis der Startpunkt wieder erreicht wird.
    9. // Hinweis: Da die 90°-Wendungen definiert sind, wird immer eine Route
    10. // gefunden, sofern eine Route vorhanden ist.
    11. var result = new HashSet<(int x, int y)>();
    12. var start = map.Keys.Single(key => map[key] == 'S');
    13. (int X, int Y)[] directions = new[] { (0, -1), (1, 0), (0, 1), (-1, 0) };
    14. var next = directions.FirstOrDefault(d => Tile(map[Addition(start, d)]).Contains(d));
    15. var turns = 0;
    16. while (!result.Contains(start))
    17. {
    18. var prev = start;
    19. result.Add(start);
    20. start = Addition(start, next);
    21. if (map[start] == 'S') break;
    22. next = Tiles(map[start]).Single(til => Negate(til) != next);
    23. turns += Clockwise(map[start], Addition(start, next), prev);
    24. }
    25. return (result, turns);
    26. }
    27. private static HashSet<(int x, int y)> FindInnerTiles(
    28. Map map, HashSet<(int X, int Y)> route, bool isclockwise)
    29. {
    30. var r = route.ToList();
    31. var result = new HashSet<(int x, int y)>();
    32. for (var i = 1; i < route.Count; i++)
    33. {
    34. var (pos, prev) = (r[i], r[i - 1]);
    35. var isleft = map[pos] switch
    36. {
    37. '|' => pos == Addition(prev, (0, -1)) ^ isclockwise,
    38. 'F' => pos == Addition(prev, (0, -1)) ^ isclockwise,
    39. 'L' => pos == Addition(prev, (-1, 0)) ^ isclockwise,
    40. _ => false
    41. };
    42. if (isleft)
    43. {
    44. if (result.Contains(Addition(pos, (-1, 0))) || route.Contains(Addition(pos, (-1, 0)))) continue;
    45. result.UnionWith(Recursiv(route, Addition(pos, (-1, 0))));
    46. }
    47. }
    48. return result;
    49. }
    50. private static HashSet<(int X, int Y)> Recursiv(
    51. HashSet<(int x, int y)> route, (int x, int y) startpos)
    52. {
    53. HashSet<(int x, int y)> result = [];
    54. var directions = new[] { (0, -1), (1, 0), (0, 1), (-1, 0) };
    55. void R((int x, int y) pos)
    56. {
    57. result.Add(pos);
    58. foreach (var direct in directions)
    59. {
    60. var xy = Addition(pos, direct);
    61. if (result.Contains(xy) || route.Contains(xy)) continue;
    62. R(xy);
    63. }
    64. }
    65. R(startpos);
    66. return result;
    67. }
    68. private static Map ToMap(string[] grid)
    69. {
    70. var map = new Map();
    71. for (var r = 0; r < grid.Length; r++)
    72. for (var c = 0; c < grid[r].Length; c++)
    73. map[(c, r)] = grid[r][c];
    74. return map;
    75. }
    76. private static (int X, int Y) Negate((int x, int y) xy) => (-xy.x, -xy.y);
    77. private static (int X, int Y) Addition((int x, int y) left, (int x, int y) right) =>
    78. (left.x + right.x, left.y + right.y);
    79. private static (int X, int Y) Subtraction((int x, int y) left, (int x, int y) right) =>
    80. (left.x - right.x, left.y - right.y);
    81. private static (int X, int Y)[] Tile(char ch) =>
    82. Tiles(ch).Select(Negate).ToArray();
    83. private static (int X, int Y)[] Tiles(char ch) =>
    84. ch switch
    85. {
    86. '7' => [(-1, 0), (0, 1)],
    87. 'F' => [(1, 0), (0, 1)],
    88. 'L' => [(0, -1), (1, 0)],
    89. 'J' => [(0, -1), (-1, 0)],
    90. '|' => [(0, -1), (0, 1)],
    91. '-' => [(-1, 0), (1, 0)],
    92. 'S' => [(0, -1), (0, 1), (-1, 0), (1, 0)],
    93. _ => []
    94. };
    95. private static int Clockwise(char ch, (int x, int y) start, (int x, int y) prev) =>
    96. ch switch
    97. {
    98. '7' => Subtraction(start, prev) == (1, 1) ? 1 : -1,
    99. 'F' => Subtraction(start, prev) == (1, -1) ? 1 : -1,
    100. 'L' => Subtraction(start, prev) == (-1, -1) ? 1 : -1,
    101. 'J' => Subtraction(start, prev) == (-1, 1) ? 1 : -1,
    102. _ => 0,
    103. };

    Source

    C#-Quellcode

    1. private static string[] Source() =>
    2. [
    3. ".F----7F7F7F7F-7....",
    4. ".|F--7||||||||FJ....",
    5. ".||.FJ||||||||L7....",
    6. "FJL7L7LJLJ||LJ.L-7..",
    7. "L--J.L7...LJS7F-7L7.",
    8. "....F-J..F7FJ|L7L7L7",
    9. "....L7.F7||L7|.L7L7|",
    10. ".....|FJLJ|FJ|F7|.LJ",
    11. "....FJL-7.||.||||...",
    12. "....L---J.LJ.LJLJ...",
    13. ];

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

    :cursing: Diese verfluchte Erkennung, ob man in der Loop ist oder nicht …
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend Class ValueCalculatorForDay8
    2. Private ReadOnly Map As New Map
    3. Function GetValuesFor(FilePath As String) As (Long, Long)
    4. Dim RawDataLines = GetRawDataFrom(FilePath)
    5. ParseRawDataLines(RawDataLines)
    6. FindNextPipe()
    7. CountTilesInLoop()
    8. DrawMapIn("map.txt")
    9. Return (Map.PositionsAlreadyVisited.Count \ 2, Map.TilesInLoop)
    10. End Function
    11. Private Function GetRawDataFrom(FilePath As String) As IEnumerable(Of String)
    12. Return IO.File.ReadAllLines(FilePath)
    13. End Function
    14. Private Sub ParseRawDataLines(RawDataLines As IEnumerable(Of String))
    15. ReDim Map.Tiles(RawDataLines(0).Count - 1, RawDataLines.Count - 1)
    16. For y = 0 To RawDataLines.Count - 1
    17. For x = 0 To RawDataLines(y).Count - 1
    18. Dim PipeSymbol = RawDataLines(y)(x)
    19. Select Case PipeSymbol
    20. Case "|"c : Map.Tiles(x, y) = New Tile("│"c, 0, -1, 0, 1, TileType.Pipe)
    21. Case "-"c : Map.Tiles(x, y) = New Tile("─"c, -1, 0, 1, 0, TileType.Pipe)
    22. Case "L"c : Map.Tiles(x, y) = New Tile("└"c, 0, -1, 1, 0, TileType.Pipe)
    23. Case "J"c : Map.Tiles(x, y) = New Tile("┘"c, 0, -1, -1, 0, TileType.Pipe)
    24. Case "7"c : Map.Tiles(x, y) = New Tile("┐"c, -1, 0, 0, 1, TileType.Pipe)
    25. Case "F"c : Map.Tiles(x, y) = New Tile("┌"c, 1, 0, 0, 1, TileType.Pipe)
    26. Case "."c : Map.Tiles(x, y) = New Tile(" "c, 0, 0, 0, 0, TileType.Ground)
    27. Case "S"c : Map.Tiles(x, y) = New Tile("X"c, 0, 0, 0, 0, TileType.StartPosition) : Map.RememberStartPosition(x, y)
    28. End Select
    29. Next
    30. Next
    31. End Sub
    32. Private Sub FindNextPipe()
    33. Dim CurrentPosition = Map.StartPosition
    34. Do
    35. CurrentPosition = Map.GetNextPosition(CurrentPosition)
    36. Loop Until CurrentPosition.Is(Map.StartPosition)
    37. End Sub
    38. Private Sub CountTilesInLoop()
    39. Map.CountTilesInLoop()
    40. End Sub
    41. Private Sub DrawMapIn(FilePath As String)
    42. Map.RemoveDirt()
    43. Map.DrawIn(FilePath)
    44. End Sub
    45. End Class
    46. Friend Class Map
    47. Property Tiles As Tile(,)
    48. Property StartPosition As Position
    49. Property TilesInLoop As Integer
    50. ReadOnly Property PositionsAlreadyVisited As New List(Of Position)
    51. Function GetNextPosition(Position As Position) As Position
    52. Return GetNewPositionFrom(Position, Tiles(Position.X, Position.Y))
    53. End Function
    54. Private Function GetNewPositionFrom(Position As Position, Tile As Tile) As Position
    55. Dim NewPosition As Position
    56. If Tile.TileType = TileType.StartPosition AndAlso PositionsAlreadyVisited.Count = 0 Then
    57. If Position.X - 1 >= 0 AndAlso Tiles(Position.X - 1, Position.Y).IsConnectedTo(Position, Position.X - 1, Position.Y) Then NewPosition = New Position With {.X = Position.X - 1, .Y = Position.Y}
    58. If Position.Y - 1 >= 0 AndAlso Tiles(Position.X, Position.Y - 1).IsConnectedTo(Position, Position.X, Position.Y - 1) Then NewPosition = New Position With {.X = Position.X, .Y = Position.Y - 1}
    59. If Position.X <= Tiles.GetUpperBound(0) AndAlso Tiles(Position.X + 1, Position.Y).IsConnectedTo(Position, Position.X + 1, Position.Y) Then NewPosition = New Position With {.X = Position.X + 1, .Y = Position.Y}
    60. If Position.Y <= Tiles.GetUpperBound(1) AndAlso Tiles(Position.X, Position.Y + 1).IsConnectedTo(Position, Position.X, Position.Y + 1) Then NewPosition = New Position With {.X = Position.X, .Y = Position.Y + 1}
    61. ElseIf Tile.TileType = TileType.Pipe Then
    62. NewPosition = New Position With {.X = Position.X + Tile.Offset1.X, .Y = Position.Y + Tile.Offset1.Y}
    63. If Tiles(NewPosition.X, NewPosition.Y).TileType = TileType.StartPosition AndAlso PositionsAlreadyVisited.Count > 1 Then
    64. ElseIf PositionsAlreadyVisited.Contains(NewPosition) Then
    65. NewPosition = New Position With {.X = Position.X + Tile.Offset2.X, .Y = Position.Y + Tile.Offset2.Y}
    66. End If
    67. End If
    68. PositionsAlreadyVisited.Add(Position)
    69. Return NewPosition
    70. End Function
    71. Sub RememberStartPosition(x As Integer, y As Integer)
    72. StartPosition = New Position With {.X = x, .Y = y}
    73. End Sub
    74. Sub CountTilesInLoop()
    75. Dim IsInsideOfLoop = False
    76. For y = 0 To Tiles.GetUpperBound(1)
    77. For x = 0 To Tiles.GetUpperBound(0)
    78. Dim Position = New Position With {.X = x, .Y = y}
    79. Dim CurrentPipeSymbol = Tiles(x, y).PipeSymbol
    80. If PositionsAlreadyVisited.Contains(Position) AndAlso "┌│┐".Contains(Tiles(x, y).PipeSymbol) Then IsInsideOfLoop = Not IsInsideOfLoop
    81. If Not PositionsAlreadyVisited.Contains(Position) AndAlso IsInsideOfLoop Then TilesInLoop += 1
    82. Next
    83. Next
    84. End Sub
    85. Sub RemoveDirt()
    86. For y = 0 To Tiles.GetUpperBound(1)
    87. For x = 0 To Tiles.GetUpperBound(0)
    88. If Not PositionsAlreadyVisited.Contains(New Position With {.X = x, .Y = y}) Then Tiles(x, y).PipeSymbol = "█"c
    89. Next
    90. Next
    91. End Sub
    92. Sub DrawIn(FilePath As String)
    93. Dim Text As New Text.StringBuilder
    94. For y = 0 To Tiles.GetUpperBound(1)
    95. For x = 0 To Tiles.GetUpperBound(0)
    96. Text.Append(Tiles(x, y).PipeSymbol)
    97. Next
    98. Text.AppendLine()
    99. Next
    100. IO.File.WriteAllText(FilePath, Text.ToString)
    101. End Sub
    102. End Class
    103. Friend Class Tile
    104. Property TileType As TileType
    105. Property Offset1 As Position
    106. Property Offset2 As Position
    107. Property PipeSymbol As Char
    108. Sub New(PipeSymbol As Char, x1 As Integer, y1 As Integer, x2 As Integer, y2 As Integer, TileType As TileType)
    109. Me.PipeSymbol = PipeSymbol
    110. Me.TileType = TileType
    111. Offset1 = New Position With {.X = x1, .Y = y1}
    112. Offset2 = New Position With {.X = x2, .Y = y2}
    113. End Sub
    114. Function IsConnectedTo(Position As Position, X As Integer, Y As Integer) As Boolean
    115. If X + Offset1.X = Position.X AndAlso Y + Offset1.Y = Position.Y Then Return True
    116. If X + Offset2.X = Position.X AndAlso Y + Offset2.Y = Position.Y Then Return True
    117. Return False
    118. End Function
    119. End Class
    120. Friend Structure Position
    121. Property X As Integer
    122. Property Y As Integer
    123. Function [Is](Position As Position) As Boolean
    124. Return X = Position.X AndAlso Y = Position.Y
    125. End Function
    126. End Structure
    127. Friend Enum TileType
    128. Pipe
    129. Ground
    130. StartPosition
    131. End Enum

    Das Kartezeichnen ist für die Lösungsberechnung überflüssig, nicht aber für die Lösungsfindung.
    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.
    Part 1 und 2

    C#-Quellcode

    1. private static void Part_01_02()
    2. {
    3. var result = Compute(Source(), 1L);
    4. Console.WriteLine($"{nameof(Part01)}: {result.Sum()}");
    5. result = Compute(Source(), 999_999L);
    6. Console.WriteLine($"{nameof(Part02)}: {result.Sum()}");
    7. }​

    Methodes

    C#-Quellcode

    1. private static List<long> Compute(string[] grid, long expansion)
    2. {
    3. var galaxies = AllGalaxies(grid, '#');
    4. var idxemptyrow = IndexOfEmptyRows(grid);
    5. var idxemptycol = IndexOfEmptyCols(grid);
    6. var result = new List<long>();
    7. for (var x = 0; x < galaxies.Length; x++)
    8. {
    9. var (x1, y1) = galaxies[x];
    10. for (var y = x + 1; y < galaxies.Length; y++)
    11. {
    12. var (x2, y2) = galaxies[y];
    13. long distance = Math.Abs(x1 - x2) + Math.Abs(y1 - y2);
    14. distance += idxemptyrow.Count(r => Between(r, y1, y2)) * expansion;
    15. distance += idxemptycol.Count(r => Between(r, x1, x2)) * expansion;
    16. result.Add(distance);
    17. }
    18. }
    19. return result;
    20. }
    21. private static bool Between( int value, int min, int max) =>
    22. Math.Min(min, max) <= value && value <= Math.Max(min, max);
    23. private static int[] IndexOfEmptyRows(string[] grid) =>
    24. Enumerable.Range(0,grid.Length).Where(r => grid[r].All(ch=>ch == '.')).ToArray();
    25. private static int[] IndexOfEmptyCols(string[] grid) =>
    26. Enumerable.Range(0, grid[0].Length).Where(c => grid.All(row => row[c] == '.')).ToArray();
    27. private static (int X, int Y)[] AllGalaxies(string[] grid, char galaxie)
    28. {
    29. var result = new List<(int x, int y)>();
    30. for (int r = 0; r < grid.Length; r++)
    31. for (int c = 0; c < grid[0].Length; c++)
    32. if (grid[r][c] == galaxie) result.Add((c, r));
    33. return result.ToArray();
    34. }

    Source

    C#-Quellcode

    1. private static string[] Source() =>
    2. [
    3. "...#......",
    4. ".......#..",
    5. "#.........",
    6. "..........",
    7. "......#...",
    8. ".#........",
    9. ".........#",
    10. "..........",
    11. ".......#..",
    12. "#...#.....",
    13. ];

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

    Eine Stunde Frust, bis ich bemerkt hatte, dass
    Spoiler anzeigen
    es hieß: Eine leere Reihe wird durch x leere Reihen ersetzt, also betroffene Positionen nicht um x verschieben, sondern um x - 1 :cursing: (typischer off-by-1-Fehler)


    Code

    VB.NET-Quellcode

    1. Friend Class ValueCalculatorForDay8
    2. Private ReadOnly Map As New Map
    3. Function GetValueFor(FilePath As String) As Long
    4. Map.Process(FilePath)
    5. Return Map.Distances.Sum
    6. End Function
    7. End Class
    8. Friend Class Map
    9. Private ReadOnly GalaxyPositions As New List(Of Position)
    10. Private ReadOnly RawMapLines As New List(Of String)
    11. Property Distances As New List(Of Long)
    12. Sub Process(FilePath As String)
    13. CreateRawFrom(IO.File.ReadAllLines(FilePath))
    14. CollectGalaxies()
    15. CorrectBy(10) 'Part 1 = 2, Part 2 = 1000000
    16. DetermineShortestPathsBetweenAllGalaxies()
    17. End Sub
    18. Private Sub CreateRawFrom(RawDataLines As IEnumerable(Of String))
    19. RawMapLines.AddRange(RawDataLines)
    20. End Sub
    21. Private Sub CollectGalaxies()
    22. Dim ID = 1
    23. For y = 0 To RawMapLines.Count - 1
    24. For x = 0 To RawMapLines(0).Count - 1
    25. If RawMapLines(y)(x) = "#" Then GalaxyPositions.Add(New Position(ID, x, y)) : ID += 1
    26. Next
    27. Next
    28. End Sub
    29. Private Sub CorrectBy(Offset As Integer)
    30. For y = RawMapLines.Count - 1 To 0 Step -1
    31. Dim IsEmptyRow = RawMapLines(y).Distinct.Count = 1
    32. If Not IsEmptyRow Then Continue For
    33. Dim TempY = y
    34. For Each GalaxyPosition In GalaxyPositions.Where(Function(x) x.Y > TempY).ToList
    35. GalaxyPosition.Y += Offset - 1
    36. Next
    37. Next
    38. For x = RawMapLines(0).Count - 1 To 0 Step -1
    39. Dim TempX = x
    40. Dim IsEmptyColumn = RawMapLines.Select(Function(a) a(TempX)).Distinct.Count = 1
    41. If Not IsEmptyColumn Then Continue For
    42. For Each GalaxyPosition In GalaxyPositions.Where(Function(a) a.X > TempX).ToList
    43. GalaxyPosition.X += Offset - 1
    44. Next
    45. Next
    46. End Sub
    47. Private Sub DetermineShortestPathsBetweenAllGalaxies()
    48. For i = 0 To GalaxyPositions.Count - 2
    49. For j = i + 1 To GalaxyPositions.Count - 1
    50. Distances.Add(RetrieveDistanceBetween(GalaxyPositions(i), GalaxyPositions(j)))
    51. Next
    52. Next
    53. End Sub
    54. Private Function RetrieveDistanceBetween(GalaxyPosition1 As Position, GalaxyPosition2 As Position) As Integer
    55. Dim DeltaY = Math.Abs(GalaxyPosition1.Y - GalaxyPosition2.Y)
    56. Dim DeltaX = Math.Abs(GalaxyPosition1.X - GalaxyPosition2.X)
    57. Return DeltaX + DeltaY
    58. End Function
    59. End Class
    60. Friend Class Position
    61. Property ID As Integer
    62. Property X As Integer
    63. Property Y As Integer
    64. Sub New(ID As Integer, X As Integer, Y As Integer)
    65. Me.ID = ID
    66. Me.X = X
    67. Me.Y = Y
    68. End Sub
    69. End Class
    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.
    Ausnahmsweise beides in einem, wer reinguckt weiß warum.
    D11 Achtung beide Parts

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllLines(FilePathOfData)
    3. Dim sky = input.Select(Function(l) l.ToCharArray).ToArray
    4. Dim skyExpanded = Transpose(Expand(Transpose(Expand(sky))))
    5. Dim resultPart1 = CLng(CalcSumDistances(skyExpanded))
    6. Dim resultPart2 = resultPart1 + 999998 * (resultPart1 - CalcSumDistances(sky))
    7. End Sub
    8. Private Function CalcSumDistances(input As Char()()) As Integer
    9. Dim Positions As New Dictionary(Of Integer, Integer())
    10. Dim k = 0
    11. For y = 0 To input.Length - 1
    12. For x = 0 To input(0).Length - 1
    13. If input(y)(x) = "#"c Then
    14. Positions.Add(k, {x, y})
    15. k += 1
    16. End If
    17. Next
    18. Next
    19. Dim result = 0
    20. For i = 0 To Positions.Count - 1
    21. For j = i + 1 To Positions.Count - 1
    22. Dim galaxy1 = Positions(i)
    23. Dim galaxy2 = Positions(j)
    24. result += Math.Abs(galaxy1(0) - galaxy2(0)) + Math.Abs(galaxy1(1) - galaxy2(1))
    25. Next
    26. Next
    27. Return result
    28. End Function
    29. Private Function Transpose(input As Char()()) As Char()()
    30. Dim output(input(0).Length - 1)() As Char
    31. For y = 0 To output.Length - 1
    32. Dim line(input.Length - 1) As Char
    33. output(y) = line
    34. Next
    35. For y = 0 To output.Length - 1
    36. For x = 0 To output(0).Length - 1
    37. output(y)(x) = input(x)(y)
    38. Next
    39. Next
    40. Return output
    41. End Function
    42. Private Function Expand(input As Char()()) As Char()()
    43. Dim output = New List(Of Char())
    44. For Each line In input
    45. output.Add(line)
    46. If line.Distinct.Count = 1 Then output.Add(line)
    47. Next
    48. Return output.ToArray
    49. End Function

    D12 Part1
    Hier wird alles stumpf durchprobiert

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim Comparer As New List(Of String)
    3. Dim Build As New List(Of Integer())
    4. Dim input = IO.File.ReadAllLines(PathOfFileData)
    5. For Each l In input
    6. Dim compandbuild = l.Split(" "c)
    7. Comparer.Add(compandbuild(0))
    8. Build.Add(compandbuild(1).Split(","c).Select(AddressOf Integer.Parse).ToArray)
    9. Next
    10. Dim result As Integer
    11. For n = 0 To Comparer.Count - 1
    12. result += Test(Comparer(n), Build(n))
    13. Next
    14. End Sub
    15. Private Function Test(comp As String, build As Integer()) As Integer
    16. Dim hold As Char()
    17. Dim result As Integer
    18. Dim idxs = comp.Select(Function(c, i) If(c = "?"c, i, -1)).Where(Function(i) i > -1).ToArray
    19. For k = 0 To CInt(2 ^ idxs.Length) - 1
    20. hold = comp.ToCharArray
    21. Dim a = Convert.ToString(k, 2).PadLeft(hold.Count(Function(c) c = "?"c), "0"c).ToCharArray
    22. For i = 0 To idxs.Length - 1
    23. hold(idxs(i)) = If(a(i) = "1"c, "."c, "#"c)
    24. Next
    25. Dim check = New String(hold).Split("."c, StringSplitOptions.RemoveEmptyEntries).Select(Function(x) x.Length).ToArray
    26. If check.SequenceEqual(build) Then result += 1
    27. Next
    28. Return result
    29. End Function

    Für Part 2 reicht es daher nicht, weil der Möglichkeitsraum gesprengt wird. Weder ein Trick für Part 1 (der Part 2 dann vermutlich durchführbar macht), noch eine Umrechnung der Part 1 Ergebnisse will mir einfallen. Bleibt weiter zu knobeln.

    Zu Part2: Eine direkte Umrechnung für die Lösung eines einfacheren, aber immer noch zeitaufwendigen Problems:
    Spoiler anzeigen
    Das Ergebnis der Verfünffachung einer Zeile (F) ergibt sich aus dem Ergebnis einer Zeile (E) und dem Ergebnis der Verdopplung einer Zeile (D) wie folgt:
    F = D^4/E^3

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

    Day 12/13 2023

    Day 12

    Part 1 / 2

    C#-Quellcode

    1. private static void Part_01_02()
    2. {
    3. var repeat = 1;
    4. string separator1 = "?", separator2 = ",";
    5. var result = Source().Select(src =>
    6. (RepeatPattern(src.Pattern, separator1, repeat), RepeatPattern(src.Numbers, separator2, repeat)))
    7. .Select(ssrc => Compute(
    8. ssrc.Item1, ssrc.Item2.Split(separator2).Select(int.Parse).ToArray(), (0, 0, 0), []));
    9. Console.WriteLine($"Part01: {result.Sum()}");
    10. repeat = 5;
    11. result = Source().Select(src =>
    12. (RepeatPattern(src.Pattern, separator1, repeat), RepeatPattern(src.Numbers, separator2, repeat)))
    13. .Select(ssrc => Compute(
    14. ssrc.Item1, ssrc.Item2.Split(separator2).Select(int.Parse).ToArray(), (0, 0, 0), []));
    15. Console.WriteLine($"Part02: {result.Sum()}");
    16. }

    Methodes

    C#-Quellcode

    1. ​private static string RepeatPattern(string pattern, string separator, int repeat) =>
    2. string.Join(separator, Enumerable.Repeat(pattern, repeat));
    3. private static long Compute(string pattern, int[] numbers,
    4. (int kpattern, int knumber, int kindex) key,
    5. Dictionary<(int kp, int kn, int ki), long> buffer)
    6. {
    7. (int pidx, int nidx, int cinx) = key;
    8. if (buffer.TryGetValue(key, out var value)) return value;
    9. if (pidx == pattern.Length)
    10. {
    11. if (nidx == numbers.Length && cinx == 0) return 1;
    12. if (nidx == numbers.Length - 1 && numbers[nidx] == cinx) return 1;
    13. return 0;
    14. }
    15. var result = 0L;
    16. if (pattern[pidx] is '.' or '?' && cinx == 0)
    17. result += Compute(pattern, numbers, (pidx + 1, nidx, 0), buffer);
    18. if (pattern[pidx] is '.' or '?' && cinx > 0 &&
    19. nidx < numbers.Length && numbers[nidx] == cinx)
    20. result += Compute(pattern, numbers, (pidx + 1, nidx + 1, 0), buffer);
    21. if (pattern[pidx] is '#' or '?')
    22. result += Compute(pattern, numbers, (pidx + 1, nidx, cinx + 1), buffer);
    23. buffer[key] = result;
    24. return result;
    25. }

    Source

    C#-Quellcode

    1. ​private static (string Pattern, string Numbers)[] Source()
    2. {
    3. return SourceText().Select(line => line
    4. .Split(" ", StringSplitOptions.RemoveEmptyEntries))
    5. .Select(x => (x.First(), x.Last())).ToArray();
    6. }
    7. private static string[] SourceText() =>
    8. [
    9. "???.### 1,1,3",
    10. ".??..??...?##. 1,1,3",
    11. "?#?#?#?#?#?#?#? 1,3,1,6",
    12. "????.#...#... 4,1,1",
    13. "????.######..#####. 1,6,5",
    14. "?###???????? 3,2,1",
    15. ];


    Day 13

    Part 1

    C#-Quellcode

    1. private static void Part01()
    2. {
    3. var src = Source().Split("").Select(x => x.ToArray()).ToArray();
    4. var v = EqualsPairVertical(src.First());
    5. var h = EqualsPairHorizontal(src.Last());
    6. var rv = ReflexionVertical(src.First(), v);
    7. var rh = ReflexionHorizontal(src.Last(), h);
    8. var result = rv.First().RPair.Item1 + 1 + 100 * (rh.First().RPair.Item1 + 1);
    9. Console.WriteLine($"{nameof(Part01)}: {result}");
    10. }

    Part 2
    Kenne den Text nicht, daher werde ich es nach den Ferien machen.

    Methodes

    C#-Quellcode

    1. private static (int, int)[] EqualsPairHorizontal(string[] lines)
    2. {
    3. var result = new List<(int, int)>();
    4. for (var i = 1; i < lines.Length; i++)
    5. if (lines[i] == lines[i - 1])
    6. result.Add((i - 1, i));
    7. return [.. result];
    8. }
    9. private static ((int, int) RPair, int Length)[]
    10. ReflexionHorizontal(string[] lines, (int, int)[] pairs)
    11. {
    12. var result = new List<((int, int) rpair, int length)>();
    13. foreach (var pair in pairs)
    14. {
    15. var flag = true;
    16. var row = pair.Item1;
    17. var max = Math.Min(row, lines.Length - row - 2);
    18. for (var j = 0; flag && j <= max; j++)
    19. if (lines[row - j] != lines[row + j + 1])
    20. flag = false;
    21. if (flag)
    22. result.Add((pair, max + 1));
    23. }
    24. return [.. result];
    25. }
    26. private static ((int, int) RPair, int Length)[]
    27. ReflexionVertical(string[] lines, (int, int)[] pairs) =>
    28. ReflexionHorizontal(lines.Select(x => x.ToCharArray())
    29. .Transpose().Select(x => string.Join("", x)).ToArray(), pairs);
    30. private static (int, int)[] EqualsPairVertical(string[] lines) =>
    31. EqualsPairHorizontal(lines.Select(x => x.ToCharArray())
    32. .Transpose().Select(x => string.Join("", x)).ToArray());

    Source

    C#-Quellcode

    1. private static string[] Source() =>
    2. [
    3. "#.##..##.",
    4. "..#.##.#.",
    5. "##......#",
    6. "##......#",
    7. "..#.##.#.",
    8. "..##..##.",
    9. "#.#.##.#.",
    10. "",
    11. "#...##..#",
    12. "#....#..#",
    13. "..##..###",
    14. "#####.##.",
    15. "#####.##.",
    16. "..##..###",
    17. "#....#..#",
    18. ];

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

    D13 Part 1

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllText(FilePathOfData).Split(vbCrLf & vbCrLf)
    3. Dim Patterns = input.Select(Function(t) t.Split(vbCrLf))
    4. Dim result = Patterns.Sum(Function(p) 100 * FindReflLine(p) + FindReflLine(Transpose(p)))
    5. End Sub
    6. Private Function FindReflLine(pattern As String()) As Long
    7. Dim middle = pattern.Length / 2
    8. For i = 1 To pattern.Length - 1
    9. Dim Cut = {pattern.Take(i), pattern.Skip(i)}
    10. If i > middle Then
    11. If Cut(1).SequenceEqual(Cut(0).Reverse.Take(pattern.Length - i)) Then Return i
    12. Else
    13. If Cut(0).SequenceEqual(Cut(1).Reverse.TakeLast(i)) Then Return i
    14. End If
    15. Next
    16. Return 0
    17. End Function
    18. Private Function Transpose(Strs As String()) As String()
    19. Dim input = Strs.Select(Function(s) s.ToCharArray).ToArray
    20. Dim output(input(0).Length - 1)() As Char
    21. For y = 0 To output.Length - 1
    22. Dim line(input.Length - 1) As Char
    23. output(y) = line
    24. Next
    25. For y = 0 To output.Length - 1
    26. For x = 0 To output(0).Length - 1
    27. output(y)(x) = input(x)(y)
    28. Next
    29. Next
    30. Return output.Select(Function(cs) New String(cs)).ToArray
    31. End Function

    D13 Part 2
    Bastelt man die SequenceEqual selbst geht beides in einem

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllText(FilePathOfData).Split(vbCrLf & vbCrLf)
    3. Dim Patterns = input.Select(Function(t) t.Split(vbCrLf)).ToList
    4. Dim resultPart1 As Integer
    5. Dim resultPart2 As Integer
    6. For i = 0 To Patterns.Count - 1
    7. Dim add2 = 0
    8. resultPart1 += 100 * FindReflLine(Patterns(i), add2) : resultPart2 += 100 * add2
    9. add2 = 0
    10. resultPart1 += FindReflLine(Transpose(Patterns(i)), add2) : resultPart2 += add2
    11. Next
    12. End Sub
    13. Private Function FindReflLine(pattern As String(), ByRef addPart2 As Integer) As Integer
    14. Dim middle = pattern.Length / 2
    15. Dim result1 = 0
    16. For i = 1 To pattern.Length - 1
    17. Dim Cut = {pattern.Take(i), pattern.Skip(i)}
    18. Dim check As Integer
    19. If i > middle Then
    20. check = SequenceEqual(Cut(0).Reverse.Take(pattern.Length - i).ToArray, Cut(1).ToArray)
    21. Else
    22. check = SequenceEqual(Cut(0).ToArray, Cut(1).Reverse.TakeLast(i).ToArray)
    23. End If
    24. If check < 2 Then
    25. result += i * (1 - check)
    26. addPart2 += i * check
    27. End If
    28. Next
    29. Return result1
    30. End Function
    31. Private Function SequenceEqual(arr1 As String(), arr2 As String()) As Integer
    32. Dim countErrors As Integer
    33. For y = 0 To arr1.Length - 1
    34. For x = 0 To arr1(0).Length - 1
    35. If arr1(y)(x) <> arr2(y)(x) Then countErrors += 1
    36. If countErrors > 1 Then Return countErrors
    37. Next
    38. Next
    39. Return countErrors
    40. End Function

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

    Den 12. erstmal überspringend (obwohl mir im Traum eine Idee kam …)
    Tag 13:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend Class ValueCalculatorForDay9
    2. Private ReadOnly Blocks As New List(Of Block)
    3. Private FinalValue As Integer = 0
    4. Function GetValueFor(FilePath As String) As Long
    5. RetrieveBlocksFrom(FilePath)
    6. Blocks.ForEach(Sub(x) Analyze(x, 1)) 'Analyze(x, y) - y bei Part 1 = 0, Part 2 = 1
    7. Return FinalValue
    8. End Function
    9. Private Sub RetrieveBlocksFrom(FilePath As String)
    10. Dim NewBlock As New Block
    11. Dim ID = 0
    12. For Each Line In IO.File.ReadLines(FilePath)
    13. If String.IsNullOrEmpty(Line) Then
    14. NewBlock.ID = ID
    15. Blocks.Add(NewBlock)
    16. ID += 1
    17. NewBlock = New Block
    18. Else
    19. NewBlock.Rows.Add(Line)
    20. End If
    21. Next
    22. NewBlock.ID = ID
    23. Blocks.Add(NewBlock)
    24. End Sub
    25. Private Sub Analyze(Block As Block, TargetDifference As Integer)
    26. For x = 0 To Block.Rows(0).Length - 2
    27. If IsMirrorYAxis(Block, x, TargetDifference) Then FinalValue += x + 1 : Return
    28. Next
    29. For y = 0 To Block.Rows.Count - 2
    30. If IsMirrorXAxis(Block, y, TargetDifference) Then FinalValue += 100 * (y + 1) : Return
    31. Next
    32. End Sub
    33. Private Function IsMirrorYAxis(Block As Block, x As Integer, TargetDifference As Integer) As Boolean
    34. Dim CountOfDifferentCharacters = 0
    35. Dim Offset = 0
    36. Do
    37. For y = 0 To Block.Rows.Count - 1
    38. If Block.Rows(y)(x - Offset) <> Block.Rows(y)(x + Offset + 1) Then CountOfDifferentCharacters += 1
    39. If CountOfDifferentCharacters > TargetDifference Then Return False
    40. Next
    41. Offset += 1
    42. Loop Until x - Offset = -1 OrElse x + Offset + 1 = Block.Rows(0).Count
    43. Return CountOfDifferentCharacters = TargetDifference
    44. End Function
    45. Private Function IsMirrorXAxis(Block As Block, y As Integer, TargetDifference As Integer) As Boolean
    46. Dim CountOfDifferentCharacters = 0
    47. Dim Offset = 0
    48. Do
    49. For x = 0 To Block.Rows(0).Count - 1
    50. If Block.Rows(y - Offset)(x) <> Block.Rows(y + Offset + 1)(x) Then CountOfDifferentCharacters += 1
    51. If CountOfDifferentCharacters > TargetDifference Then Return False
    52. Next
    53. Offset += 1
    54. Loop Until y - Offset = -1 OrElse y + Offset + 1 = Block.Rows.Count
    55. Return CountOfDifferentCharacters = TargetDifference
    56. End Function
    57. End Class
    58. Friend Class Block
    59. Property ID As Integer
    60. Property Rows As New List(Of String)
    61. End Class
    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.
    D14 Part 1

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllLines(FilePathOfData)
    3. Dim Tilted = Tilt(input, Direction.North)
    4. Dim result = Tilted.Select(Function(l, i) (i + 1) * l.Count(Function(c) c = "O"c)).Sum
    5. End Sub
    6. Private Function Tilt(input As String(), dir As Direction) As String()
    7. Dim rocklines = Array.Empty(Of String)
    8. Dim reverse = False
    9. Select Case dir
    10. Case Direction.North
    11. rocklines = Transpose(input)
    12. Case Direction.West
    13. rocklines = input
    14. Case Direction.South
    15. rocklines = Transpose(input)
    16. reverse = True
    17. Case Direction.East
    18. rocklines = input
    19. reverse = True
    20. Case Else
    21. Return input
    22. End Select
    23. For i = 0 To rocklines.Length - 1
    24. Dim borders = rocklines(i).Split("#"c)
    25. For j = 0 To borders.Length - 1
    26. Dim rockcount = borders(j).Count(Function(c) c = "O"c)
    27. borders(j) = borders(j).Replace("O"c, String.Empty)
    28. Dim pad = borders(j).Length + rockcount
    29. borders(j) = If(reverse, borders(j).PadRight(pad, "O"c), borders(j).PadLeft(pad, "O"c))
    30. Next
    31. rocklines(i) = String.Join("#"c, borders)
    32. Next
    33. Select Case dir
    34. Case Direction.North
    35. Return Transpose(rocklines)
    36. Case Direction.West
    37. Return rocklines
    38. Case Direction.South
    39. Return Transpose(rocklines)
    40. End Select
    41. Return rocklines
    42. End Function
    43. Private Function Transpose(Strs As IEnumerable(Of String)) As String()
    44. Dim input = Strs.Select(Function(s) s.ToCharArray).ToArray
    45. Dim output(input(0).Length - 1)() As Char
    46. For y = 0 To output.Length - 1
    47. Dim line(input.Length - 1) As Char
    48. output(y) = line
    49. Next
    50. For y = 0 To output.Length - 1
    51. For x = 0 To output(0).Length - 1
    52. output(y)(x) = input(x)(y)
    53. Next
    54. Next
    55. Return output.Select(Function(cs) New String(cs)).ToArray
    56. End Function
    57. Friend Enum Direction
    58. North
    59. West
    60. South
    61. East
    62. End Enum

    D14 Part 2
    Da lässt sich noch Einiges verbessern, aber naja

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllLines(FilePathOfData)
    3. Dim resultPart1 = Tilt(input, Direction.North).Select(Function(l, k) (l.Length - k) * l.Count(Function(c) c = "O"c)).Sum
    4. Dim lstRes As New List(Of Integer)
    5. Dim CycleEstablished = 200 '100 war zu klein, ggf. weiter erhöhen
    6. Dim resultPart2 As Integer
    7. For t = 1 To 100 'Grob analysiert ergab sich für ein nxn Grid eine Zyklusgröße < n, allerdings habe ich das noch nicht bewiesen. Ggf erhöhen.
    8. Console.WriteLine(t)
    9. For Each i In {CycleEstablished - t, CycleEstablished, CycleEstablished + t} 'Naiv, da Zahlen groß genug im Haupttest
    10. Dim Cycle1 = Spin(input, i)
    11. lstRes.Add(Cycle1.Select(Function(l, k) (l.Length - k) * l.Count(Function(c) c = "O"c)).Sum)
    12. Next
    13. If lstRes.Distinct.Count = 1 Then
    14. resultPart2 = Spin(input, CycleEstablished + ((1000000000 - CycleEstablished) Mod t)).Select(Function(l, k) (l.Length - k) * l.Count(Function(c) c = "O"c)).Sum
    15. Exit For
    16. End If
    17. lstRes.Clear()
    18. Next
    19. End Sub
    20. Private Function Spin(input As String(), n As Integer) As String()
    21. Dim k As Long
    22. Dim output = input
    23. While k < n
    24. For i As Direction = 0 To Direction.East
    25. output = Tilt(output, i)
    26. Next
    27. k += 1
    28. End While
    29. Return output
    30. End Function

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

    Beim Finalwert von Part 2 hab ich aufgrund von Müdigkeit getrickst und
    Spoiler anzeigen
    manell aufgrund des Zykluses den richtigen Wert rausgefischt

    VB.NET-Quellcode

    1. Friend Class ValueCalculatorForDay14
    2. Private ReadOnly Block As New Block
    3. Private FinalValue As Integer = 0
    4. Function GetValueFor(FilePath As String) As (Integer, Integer)
    5. RetrieveBlockDataFrom(FilePath)
    6. Dim Values As New List(Of Integer)
    7. For i = 1 To 200
    8. FinalValue = 0
    9. Block.TiltBy(0, -1)
    10. Block.TiltBy(-1, 0)
    11. Block.TiltBy(0, 1)
    12. Block.TiltBy(1, 0)
    13. Values.Add(Block.Calculate())
    14. Next
    15. FinalValue = Block.Calculate()
    16. Return (FinalValue, 0)
    17. End Function
    18. Private Sub RetrieveBlockDataFrom(FilePath As String)
    19. Dim RawDataLines = IO.File.ReadLines(FilePath)
    20. ReDim Block.Tiles(RawDataLines(0).Count, RawDataLines.Count)
    21. For y = 0 To RawDataLines.Count - 1
    22. For x = 0 To RawDataLines(0).Count - 1
    23. Block.Tiles(x, y) = GetTileTypeFrom(RawDataLines(y)(x))
    24. Next
    25. Next
    26. End Sub
    27. Private Function GetTileTypeFrom(Character As Char) As TileType
    28. Select Case Character
    29. Case "#"c : Return TileType.FixedRock
    30. Case "O"c : Return TileType.MoveableRock
    31. Case Else : Return TileType.Void
    32. End Select
    33. End Function
    34. End Class
    35. Friend Class Block
    36. Property Tiles As Integer(,)
    37. Sub TiltBy(XSign As Integer, YSign As Integer)
    38. Dim StartX = If(XSign = 1, Tiles.GetUpperBound(0) - 1, 0)
    39. Dim EndX = If(XSign = 1, 0, Tiles.GetUpperBound(0) - 1)
    40. Dim StartY = If(YSign = 1, Tiles.GetUpperBound(1) - 1, 0)
    41. Dim EndY = If(YSign = 1, 0, Tiles.GetUpperBound(1) - 1)
    42. For x = StartX To EndX Step If(XSign = 0, 1, -XSign)
    43. For y = StartY To EndY Step If(YSign = 0, 1, -YSign)
    44. If Tiles(x, y) <> TileType.MoveableRock Then Continue For
    45. Dim EndPositionX = If(XSign = -1, 0, If(XSign = 0, x, Tiles.GetUpperBound(0) - 1))
    46. Dim EndPositionY = If(YSign = -1, 0, If(YSign = 0, y, Tiles.GetUpperBound(1) - 1))
    47. If YSign <> 0 Then
    48. For YToCheck = y + YSign To If(YSign = -1, 0, Tiles.GetUpperBound(1) - 1) Step YSign
    49. If Tiles(x, YToCheck) <> TileType.Void Then EndPositionY = YToCheck - YSign : Exit For
    50. Next
    51. End If
    52. If XSign <> 0 Then
    53. For XToCheck = x + XSign To If(XSign = -1, 0, Tiles.GetUpperBound(0) - 1) Step XSign
    54. If Tiles(XToCheck, y) <> TileType.Void Then EndPositionX = XToCheck - XSign : Exit For
    55. Next
    56. End If
    57. Tiles(x, y) = TileType.Void
    58. Tiles(EndPositionX, EndPositionY) = TileType.MoveableRock
    59. Next
    60. Next
    61. End Sub
    62. Function Calculate() As Integer
    63. Dim FinalValue = 0
    64. For y = 0 To Tiles.GetUpperBound(1) - 1
    65. For x = 0 To Tiles.GetUpperBound(0) - 1
    66. If Tiles(x, y) <> TileType.MoveableRock Then Continue For
    67. Dim Value = Tiles.GetUpperBound(1) - y
    68. FinalValue += Value
    69. Next
    70. Next
    71. Return FinalValue
    72. End Function
    73. Private Function GetCharacterFrom(TileType As Integer) As String
    74. Select Case TileType
    75. Case 0 : Return "O"
    76. Case 1 : Return "#"
    77. Case Else : Return "."
    78. End Select
    79. End Function
    80. End Class
    81. Friend Enum TileType
    82. MoveableRock
    83. FixedRock
    84. Void
    85. End Enum
    :rolleyes:
    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.
    D15 Part 1

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllText(FilePathOfData).Split(","c)
    3. Dim result = input.Sum(AddressOf GetHash)
    4. End Sub
    5. Private Function GetHash(value As String) As Long
    6. Return value.Select(Function(c) CLng(Asc(c))).Aggregate(Function(n, m) (n * 17) + m) * 17 Mod 256
    7. End Function

    D15 Part 2

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim input = IO.File.ReadAllText(FilePathOfData).Split(","c)
    3. Dim resultPart1 = input.Sum(AddressOf GetHash)
    4. Dim Boxes = New Dictionary(Of Integer, List(Of Lens))
    5. For i = 0 To 255
    6. Boxes.Add(i, New List(Of Lens))
    7. Next
    8. Dim Lenses = input.Select(AddressOf ToLens)
    9. For Each lens In Lenses
    10. Dim _lens = Boxes(lens.Box).FirstOrDefault(Function(l) l.Name = lens.Name)
    11. If _lens Is Nothing AndAlso lens.FocalLength > 0 Then Boxes(lens.Box).Add(lens)
    12. If lens.FocalLength = 0 AndAlso _lens IsNot Nothing Then
    13. Boxes(lens.Box).Remove(_lens)
    14. ElseIf _lens IsNot Nothing Then
    15. _lens.FocalLength = lens.FocalLength
    16. End If
    17. Next
    18. Dim resultPart2 = Boxes.Sum(Function(p) (p.Key + 1) * p.Value.Select(Function(l, i) l.FocalLength * (i + 1)).Sum)
    19. End Sub
    20. Private Function GetHash(value As String) As Integer
    21. Return CInt(value.Select(Function(c) CLng(Asc(c))).Aggregate(Function(n, m) (n * 17) + m) * 17 Mod 256)
    22. End Function
    23. Private Function ToLens(value As String) As Lens
    24. Dim lensandlength = value.Split("="c, "-"c)
    25. Return New Lens() With {
    26. .Name = lensandlength(0),
    27. .Box = GetHash(lensandlength(0)),
    28. .FocalLength = If(lensandlength(1) = String.Empty, 0, CInt(lensandlength(1)))}
    29. End Function
    30. Friend Class Lens
    31. Property Name As String
    32. Property Box As Integer
    33. Property FocalLength As Integer
    34. End Class


    Edit nach Post 100 @VaporiZed Definitiv, hab mich 5 Minuten gefragt woran man die "richtige" Box erkennen soll, bis ich den Paragraph gefunden hab wo das steht, hab den mehrfach überlesen.

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

    Die Beschreibung von Tag 2 kam mir komplizierter als die eigentliche Problemlöösung vor :S
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend Class ValueCalculatorForDay15
    2. Private ReadOnly Boxes As New List(Of Box)
    3. Function GetValueFor(FilePath As String) As (Integer, Integer)
    4. Dim Text = IO.File.ReadAllText(FilePath).Split(","c)
    5. Return (GetValueForPart1(Text), GetValueForPart2(Text))
    6. End Function
    7. Private Function GetValueForPart1(Text As IEnumerable(Of String)) As Integer
    8. Dim FinalValue = 0
    9. For Each Part In Text
    10. Dim Value = 0
    11. For Each Character In Part
    12. Dim AsciiValue = Microsoft.VisualBasic.Asc(Character)
    13. Value = ((Value + AsciiValue) * 17) Mod 256
    14. Next
    15. FinalValue += Value
    16. Next
    17. Return FinalValue
    18. End Function
    19. Private Function GetValueForPart2(Text As IEnumerable(Of String)) As Integer
    20. CreateBoxesFrom(Text)
    21. ApplyLensSequence(Text)
    22. Return GetFocusPower()
    23. End Function
    24. Private Sub CreateBoxesFrom(Text As IEnumerable(Of String))
    25. For Each Part In Text
    26. Dim BoxLabel = String.Empty
    27. For Each Character In Part
    28. If "=-".Contains(Character) Then Exit For
    29. BoxLabel &= Character
    30. Next
    31. Dim BoxID = GetBoxIdFrom(BoxLabel)
    32. If Not Boxes.Any(Function(x) x.ID = BoxID) Then Boxes.Add(New Box With {.ID = BoxID, .Label = BoxLabel})
    33. Next
    34. End Sub
    35. Private Function GetBoxIdFrom(BoxLabel As String) As Integer
    36. Dim BoxID = 0
    37. For Each Character In BoxLabel
    38. Dim AsciiValue = Microsoft.VisualBasic.Asc(Character)
    39. BoxID = ((BoxID + AsciiValue) * 17) Mod 256
    40. Next
    41. Return BoxID
    42. End Function
    43. Private Sub ApplyLensSequence(Text As IEnumerable(Of String))
    44. For Each Part In Text
    45. Dim OperationPack = GetOperationPackFrom(Part)
    46. Apply(OperationPack)
    47. Next
    48. End Sub
    49. Private Function GetOperationPackFrom(Part As String) As OperationPack
    50. Dim OperationPack As New OperationPack
    51. Dim BoxLabel = String.Empty
    52. Dim CollectBoxID = True
    53. For i = 0 To Part.Count - 1
    54. If CollectBoxID Then
    55. If Not "=-".Contains(Part(i)) Then
    56. BoxLabel &= Part(i)
    57. Else
    58. OperationPack.BoxID = GetBoxIdFrom(BoxLabel)
    59. OperationPack.LensID = BoxLabel
    60. OperationPack.Operation = If(Part(i) = "-"c, OperationType.RemoveLens, OperationType.SetLens)
    61. CollectBoxID = False
    62. End If
    63. Else
    64. If OperationPack.Operation = OperationType.SetLens Then OperationPack.FocusLength = Integer.Parse(Part.Substring(i))
    65. End If
    66. Next
    67. Return OperationPack
    68. End Function
    69. Private Sub Apply(OperationPack As OperationPack)
    70. Dim Box = Boxes.Single(Function(x) x.ID = OperationPack.BoxID)
    71. If Box.Lenses.Any(Function(x) x.ID = OperationPack.LensID) Then
    72. For i = 0 To Box.Lenses.Count - 1
    73. If i = Box.Lenses.Count Then Exit For
    74. If Box.Lenses(i).ID <> OperationPack.LensID Then Continue For
    75. If OperationPack.Operation = OperationType.SetLens Then Box.Lenses(i).FocalLength = OperationPack.FocusLength
    76. If OperationPack.Operation = OperationType.RemoveLens Then Box.Lenses.RemoveAt(i) : i = -1
    77. Next
    78. Else
    79. If OperationPack.Operation = OperationType.SetLens Then Box.Lenses.Add(New Lens With {.ID = OperationPack.LensID, .FocalLength = OperationPack.FocusLength})
    80. End If
    81. End Sub
    82. Private Function GetFocusPower() As Integer
    83. Dim FinalValue = 0
    84. For Each Box In Boxes
    85. For i = 0 To Box.Lenses.Count - 1
    86. FinalValue += (Box.ID + 1) * (i + 1) * Box.Lenses(i).FocalLength
    87. Next
    88. Next
    89. Return FinalValue
    90. End Function
    91. End Class
    92. Friend Class Box
    93. Property ID As Integer
    94. Property Label As String
    95. Property Lenses As New List(Of Lens)
    96. End Class
    97. Friend Class Lens
    98. Property ID As String
    99. Property FocalLength As Integer
    100. End Class
    101. Friend Class OperationPack
    102. Property BoxID As Integer
    103. Property LensID As String
    104. Property Operation As OperationType
    105. Property FocusLength As Integer
    106. End Class
    107. Friend Enum OperationType
    108. RemoveLens
    109. SetLens
    110. End Enum
    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.