> 백엔드 개발 > 파이썬 튜토리얼 > AoC &#Day Red-Nosed 보고서(C# 및 Python)

AoC &#Day Red-Nosed 보고서(C# 및 Python)

Mary-Kate Olsen
풀어 주다: 2024-12-07 21:02:15
원래의
964명이 탐색했습니다.

AoC

오늘의 솔루션은 이전보다 약간 더 복잡하여 코드가 더 필요했지만 그럼에도 불구하고 꽤 간단했습니다.

솔루션 기본 개념:

유효하려면 파트 1의 다음 조건을 충족해야 합니다.

  • 숫자가 모두 증가하는지, 아니면 감소하는지 결정해야 합니다.

  • 숫자 사이의 간격은 3을 넘을 수 없습니다

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;
}

로그인 후 복사
로그인 후 복사

간단히 설명하면 보고서를 도우미 IsValidReport() 메서드에 전달하기 전에 LINQ를 사용하여 문자열 숫자를 정수로 구문 분석한다는 것입니다.

이 방법은 모든 숫자가 증가하는지 감소하는지 확인합니다. 이는 ID를 순서가 지정된 목록과 비교하여 수행되며, 이는 모든 숫자가 모두 한 방향으로 가고 있음을 증명합니다.

모두 한 방향(밴드가 아님)에 있다는 것을 알고 나면 각 숫자가 서로 3자리 이내에 있는지 확인할 수 있습니다. 절대 숫자를 반환하는 Math.Abs() 메서드를 사용하면 마이너스 숫자를 설명하는 데 도움이 됩니다.

참고: 절대 숫자는 숫자와 0 사이의 숫자입니다. 즉, -5와 5는 모두 5를 반환합니다.

2부

파트 2에는 약간 더 복잡한 지침이 있었지만 실제보다 더 어려워 보입니다.

두 번째 부분에서는 보고서에서 항목 1개를 제거해도 여전히 유효한 보고서로 간주된다는 기본 개념을 바탕으로 인적 오류에 대한 주의 사항을 소개합니다.

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);
}
로그인 후 복사

여기에서는 LINQ의 성능을 극대화하여 문자열 보고서를 구문 분석하고 이를 사용하여 ints 배열을 수정합니다. 배열을 반복하고 인덱스에서 현재 항목을 제거하여 int 배열을 수정하여 수정합니다.

수정된 후에는 검증기를 통해 수정된 보고서를 실행합니다. 이 작업은 조건이 충족되는 즉시(즉, 수정된 보고서가 유효한 즉시) 단락되는 Any()와 결합된 LINQ Select() 메서드를 사용하여 한 번에 수행할 수 있습니다.

하나의 유효한 수정 보고서만 확인하는 이유는 무엇입니까?

하나의 항목이라도 제거할 수 있으면 신고가 유효한 것으로 간주되기 때문입니다. 특정 항목을 언급하지 않으므로 제거 시 보고서가 유효하다는 것을 의미하는 일치하는 항목을 찾는 즉시 다른 모든 항목 조회를 중단할 수 있습니다.

그런 다음 유효한 보고서를 추적하기 위해 validReports 카운터를 증가시킵니다.

이것을 Python으로 변환하려는 시도는 다음과 같습니다.

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()

로그인 후 복사

덜 장황한 솔루션의 경우 C# 솔루션에서 LINQ에서 했던 것처럼 Part 2 내부 for 루프를 수정 및 검사로 대체할 수 있습니다.

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;
}

로그인 후 복사
로그인 후 복사

하지만 당신도 동의할 것입니다. 더 좋은 이름의 변수를 사용하는 장황한 방법이 훨씬 더 읽기 쉽습니다.

읽어주셔서 감사합니다. 내일 다시 참여하고 언제나처럼 트위터에 팔로우를 남겨주세요

위 내용은 AoC &#Day Red-Nosed 보고서(C# 및 Python)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿