Heim > Backend-Entwicklung > Python-Tutorial > AoC &#Day Red-Nosed Reports (C# und Python)

AoC &#Day Red-Nosed Reports (C# und Python)

Mary-Kate Olsen
Freigeben: 2024-12-07 21:02:15
Original
985 Leute haben es durchsucht

AoC

Heute war die Lösung etwas komplexer als am Vortag und rechtfertigte etwas mehr Code, war aber dennoch ziemlich einfach.

Grundlegende Lösungskonzepte:

Um gültig zu sein, müssen die folgenden Bedingungen für Teil 1 erfüllt sein:

  • Wir müssen entscheiden, ob die Zahlen alle von einer zur nächsten steigen oder sinken.

  • Der Abstand zwischen den Zahlen darf nicht mehr als 3 betragen

Teil 1

var reports = File.ReadAllLines("./input1.txt")
    .Select(x => x.Split(" "))
    .ToList();

Part1(reports);

void Part1(List<string[]> input)
{
    var validReports = input
        .Select(report => report.Select(int.Parse).ToList())
        .Count(IsValidReport);

    Console.WriteLine(validReports);
}

bool IsValidReport(List<int> levels)
{
    // We don't care about the numbers, just wether going up or down, not both
    var isIncreasing = IsIncreasing(levels);
    var isDecreasing = IsDecreasing(levels);

    if (!isIncreasing && !isDecreasing) return false;

    // Check that all adjacent levels differ by at least 1 and at most 3
    for (var i = 0; i < levels.Count - 1; i++)
    {
        var diff = Math.Abs(levels[i + 1] - levels[i]);
        if (diff is < 1 or > 3)
        {
            return false;
        }
    }

    return true;
}

bool IsIncreasing(List<int> numbers)
{
    for (var i = 1; i < numbers.Count; i++)
    {
        if (numbers[i] < numbers[i - 1]) return false;
    }

    return true;
}

bool IsDecreasing(List<int> numbers)
{
    for (var i = 1; i < numbers.Count; i++)
    {
        if (numbers[i] > numbers[i - 1]) return false;
    }

    return true;
}

Nach dem Login kopieren
Nach dem Login kopieren

Eine einfache Erklärung ist, dass wir die Zeichenfolgennummern mithilfe von LINQ in Ganzzahlen analysieren, bevor wir den Bericht an unsere Hilfsmethode IsValidReport() übergeben.

Diese Methode prüft, ob alle Zahlen entweder steigen oder fallen. Dies geschieht durch den Vergleich der IDs mit einer geordneten Liste, die beweist, dass alle Zahlen in eine Richtung gehen.

Sobald wir wissen, dass sie alle in einer Richtung liegen (nicht in der Band), können wir überprüfen, ob jede Zahl innerhalb von 3 Zahlen voneinander liegt. Verwendung der Math.Abs()-Methode, die die absolute Zahl zurückgibt und uns dabei hilft, Minuszahlen zu berücksichtigen.

Hinweis: Eine absolute Zahl ist die Zahl zwischen der Zahl und Null, d. h. -5 und 5 würden beide 5 zurückgeben;

Teil 2

Für Teil 2 hatten wir eine etwas komplexere Anleitung, aber es hört sich schwieriger an, als es ist.

Der zweite Teil stellt den Vorbehalt menschlicher Fehler vor, mit dem Grundkonzept, dass Sie wissen müssen, ob Sie ein Element aus dem Bericht entfernen können und es weiterhin als gültiger Bericht gilt.

void Part2(List<string[]> input)
{
    var validReports = 0;

    foreach (var ints in input.Select(report => report.Select(int.Parse).ToList()))
    {
        // If valid as-is, count it
        if (IsValidReport(ints))
        {
            validReports++;
            continue;
        }

        // Check if removing any single level makes it valid
        if (ints.Select((t, i) => ints.Where((_, index) => index != i).ToList())
            .Any(IsValidReport))
        {
            validReports++;
        }
    }

    Console.WriteLine(validReports);
}
Nach dem Login kopieren

Hier maximieren wir die Leistung von LINQ, analysieren die String-Berichte und verwenden es zum Ändern des Ints-Arrays. Wir ändern, indem wir das Array durchlaufen und das aktuelle Element am Index entfernen, wodurch das Array von Ints geändert wird.

Nach der Änderung führen wir den geänderten Bericht durch den Validator. Dies kann auf einmal mit der LINQ-Methode Select() in Kombination mit Any() erfolgen, die kurzschließt, sobald die Bedingung erfüllt ist (d. h. sobald ein geänderter Bericht gültig ist).

Warum nur nach einem einzigen gültigen geänderten Bericht suchen?

Dies liegt daran, dass der Bericht als gültig angesehen werden kann, wenn ein Element entfernt werden kann. Es wird kein bestimmter Artikel angegeben. Sobald wir also einen passenden Artikel finden, der bei Entfernung bedeutet, dass der Bericht gültig ist, können wir die Suche nach allen anderen beenden.

Wir erhöhen dann den validReports-Zähler, um den Überblick über unsere gültigen Berichte zu behalten.

Hier ist mein Versuch, dies in Python zu konvertieren:

def main():
    # Read the input file and split each line into a list of strings
    with open("./input1.txt") as file:
        reports = [line.split() for line in file]

    part1(reports)
    part2(reports)


def part1(reports):
    # Count valid reports using a list comprehension and the IsValidReport function

    valid_reports = 0
    for report in reports:
        levels = list(map(int, report))

        if is_valid_report(levels):
            valid_reports += 1

    print(valid_reports)


def part2(reports):
    valid_reports = 0

    for report in reports:
        ints = list(map(int, report))

        # If valid as-is, count it
        if is_valid_report(ints):
            valid_reports += 1
            continue

        # Check if removing any single level makes it valid
        valid_with_dampener = False

        # Iterate over each element in ints
        for i in range(len(ints)):
            # Create a new list without the element at index i
            modified_report = [x for j, x in enumerate(ints) if j != i]

            # Check if the modified report is valid
            if is_valid_report(modified_report):
                valid_with_dampener = True
                break

        if valid_with_dampener:
            valid_reports += 1

    print(valid_reports)


def is_valid_report(levels):
    # Check if the sequence is either all increasing or all decreasing
    is_increasing = is_increasing_sequence(levels)
    is_decreasing = is_decreasing_sequence(levels)

    if not is_increasing and not is_decreasing:
        return False

    # Check that all adjacent levels differ by at least 1 and at most 3
    for i in range(len(levels) - 1):
        diff = abs(levels[i + 1] - levels[i])
        if diff < 1 or diff > 3:
            return False

    return True


def is_increasing_sequence(numbers):
    for i in range(1, len(numbers)):
        if numbers[i] < numbers[i - 1]:
            return False
    return True


def is_decreasing_sequence(numbers):
    for i in range(1, len(numbers)):
        if numbers[i] > numbers[i - 1]:
            return False
    return True


if __name__ == "__main__":
    main()

Nach dem Login kopieren

Für eine weniger ausführliche Lösung könnten wir die innere for-Schleife von Teil 2 durch die Änderung und Prüfung ersetzen, wie wir es mit LINQ in der C#-Lösung getan haben, etwa so:

var reports = File.ReadAllLines("./input1.txt")
    .Select(x => x.Split(" "))
    .ToList();

Part1(reports);

void Part1(List<string[]> input)
{
    var validReports = input
        .Select(report => report.Select(int.Parse).ToList())
        .Count(IsValidReport);

    Console.WriteLine(validReports);
}

bool IsValidReport(List<int> levels)
{
    // We don't care about the numbers, just wether going up or down, not both
    var isIncreasing = IsIncreasing(levels);
    var isDecreasing = IsDecreasing(levels);

    if (!isIncreasing && !isDecreasing) return false;

    // Check that all adjacent levels differ by at least 1 and at most 3
    for (var i = 0; i < levels.Count - 1; i++)
    {
        var diff = Math.Abs(levels[i + 1] - levels[i]);
        if (diff is < 1 or > 3)
        {
            return false;
        }
    }

    return true;
}

bool IsIncreasing(List<int> numbers)
{
    for (var i = 1; i < numbers.Count; i++)
    {
        if (numbers[i] < numbers[i - 1]) return false;
    }

    return true;
}

bool IsDecreasing(List<int> numbers)
{
    for (var i = 1; i < numbers.Count; i++)
    {
        if (numbers[i] > numbers[i - 1]) return false;
    }

    return true;
}

Nach dem Login kopieren
Nach dem Login kopieren

Aber ich denke, Sie können zustimmen, dass die ausführliche Methode mit besser benannten Variablen viel besser lesbar ist.

Danke fürs Lesen, kommen Sie morgen wieder vorbei und folgen Sie mir wie immer auf Twitter

Das obige ist der detaillierte Inhalt vonAoC &#Day Red-Nosed Reports (C# und Python). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage