>백엔드 개발 >Golang >코드의 출현 ay n Golang: 주문 페이지

코드의 출현 ay n Golang: 주문 페이지

Mary-Kate Olsen
Mary-Kate Olsen원래의
2024-12-28 07:33:31313검색

소개

코드 출현 5일째입니다. 오늘은 페이지 순서 지정에 관한 흥미로운 문제가 발생했습니다. 문제와 제가 어떻게 접근했는지 살펴보겠습니다. 좋게 생각하면 꽤 간단한 문제였는데, 그렇지 않으면 맵, 리스트, 인덱스가 엉망이 될 뻔했습니다.

여기 GitHub에서 제 솔루션을 확인하실 수 있습니다.

Advent of Code ay n Golang: Ordering Pages 미스터 파괴자 / 출현_코드

코드의 출현

입력

5일차 입력에는 두 개의 섹션이 있습니다. 첫 번째 섹션은 페이지 순서 규칙, 특히 어떤 페이지가 어느 페이지 앞에 와야 하는지를 정의하고 두 번째 섹션은 페이지의 실제 순서를 포함합니다.

47|53
97|13
97|61
97|47
75|29
61|13
75|53
29|13
97|29
53|29
61|53
97|53
61|29
47|13
75|47
97|75
47|61
75|61
47|29
75|13
53|13

75,47,61,53,29
97,61,53,29,13
75,29,13
75,97,47,61,53
61,13,29
97,13,75,29,47

첫 번째 섹션에는 매핑된 규칙이 있고, 다른 섹션에는 페이지 순서가 있으며, 각 줄은 처리할 실제 데이터인 쿼리 또는 페이지 목록입니다. 파트 1과 2의 처리에 사용해야 합니다.

섹션 읽기

따라서 이러한 섹션을 구문 분석하고 더 쉽게 액세스할 수 있는 데이터 구조로 읽어야 합니다.

그렇게 하는 한 가지 방법은

  • 두 개의 섹션으로 구성된 목록

  • 첫 번째 섹션은 목록입니다

    • 목록은 규칙을 위해 두 개의 정수를 보유하는 정수 목록입니다.
  • 두 번째 섹션은 목록입니다

    • 목록은 페이지 목록을 담을 정수 목록입니다

따라서 데이터 구조는 정수 목록의 목록처럼 보입니다.

func ReadFileSections(path string) [][][]int {

    fileBytes := ReadFileBytes(path)
    lines := []string{}
    separator := []byte("\n\n")
    for _, line := range bytes.Split(fileBytes, separator) {
        if string(line) != "" {
            lines = append(lines, string(line))
        }
    }

    sections := [][][]int{}
    for i, section := range lines {
        nums := [][]int{}
        lineStrs := strings.Split(section, "\n")
        separator := ","
        if i == 0 {
            separator = "|"
        }
        for _, lineStr := range lineStrs {
            if lineStr == "" {
                continue
            }
            numL := []int{}
            for _, numStr := range strings.Split(lineStr, separator) {
                num, _ := strconv.Atoi(numStr)
                numL = append(numL, num)
            }
            nums = append(nums, numL)
        }
        sections = append(sections, nums)
    }
    return sections
}

ReadFileSections라는 위의 함수는 논의된 대로 입력 파일의 경로를 취하고 정수 목록의 슬라이스/배열을 반환합니다. 먼저 파일을 읽고 바이트를 섹션 구분 기호가 될 두 개의 개행 문자로 분할합니다. 행을 문자열 목록으로 저장합니다. 첫 번째에는 규칙 행이 포함되고 두 번째에는 페이지 목록 행이 포함됩니다.

그런 다음 섹션을 반복하고 각 구분 기호(예: | 첫 번째 섹션의 경우, 두 번째 섹션의 경우 (공백)입니다. 각 행을 구문 분석하여 정수 목록을 가져와 해당 섹션에 추가합니다.

이제 문제 처리에 도움이 되는 규칙과 페이지를 구성하는 데 사용할 수 있는 데이터가 생겼습니다.

규칙 구성

이제 편리한 액세스를 위해 규칙 목록을 처리해야 하며, 특정 페이지 뒤에 표시되어야 하는 페이지 번호를 가져와야 하므로 정수 목록이 포함된 정수 맵을 사용합니다. 여기서 키는 다음과 같습니다. 첫 번째 숫자와 값 중 하나가 두 번째 숫자(페이지 순서대로 뒤에 표시되어야 하는 숫자)가 됩니다.

func ConstructRules(rulesList [][]int) map[int][]int {
    rules := make(map[int][]int)
    for _, rule := range rulesList {
        rules[rule[0]] = append(rules[rule[0]], rule[1])
    }
    return rules
}

정수 목록을 반복하고 첫 번째 요소를 키로 매핑하고 값을 목록의 두 번째 요소로 매핑하므로 시각화할 수 있습니다.

FROM

[][]int

[
    [47,53]
    [97,13]
    [97,61]
]

TO

map[int][]int
{
    47: [53]
    97: [13,61]
}

이제 정수와 정수의 맵으로 규칙을 갖습니다.

인덱스 구성

이제 첫 번째와 두 번째 부분을 더 쉽게 만들기 위해 페이지 목록에 나타나는 색인을 사용하여 규칙 섹션의 각 숫자에 대한 지도를 만들어야 합니다.

그래서 우리는 정수와 정수의 맵인 규칙을 반복하고 규칙에서 고유한 정수 목록을 만드는 데 도움이 되는 정수 맵을 생성할 것입니다.

이제 규칙에서 정수 목록을 얻었으면 모든 숫자를 반복하고 각 페이지 줄에서 어떤 인덱스가 나타나는지 확인하여 정수(인덱스) 목록을 만듭니다.

따라서 페이지 줄의 모든 숫자를 반복합니다. 페이지 목록에서 해당 숫자를 찾으면 색인을 추가하지만, 그렇지 않으면 -1을 추가하므로 각 줄에 대해 다음과 같이 해당 숫자에 색인을 추가해야 합니다.

47|53
97|13
97|61
97|47
75|29
61|13
75|53
29|13
97|29
53|29
61|53
97|53
61|29
47|13
75|47
97|75
47|61
75|61
47|29
75|13
53|13

75,47,61,53,29
97,61,53,29,13
75,29,13
75,97,47,61,53
61,13,29
97,13,75,29,47

그래서 위의 예에서는 75를 참고로 하여 각 페이지 번호 목록에 대한 색인을 얻고, 75가 나타나는 색인 목록을 얻습니다.

이제 다음 기능을 사용하여 이 작업을 수행할 수 있습니다.

func ReadFileSections(path string) [][][]int {

    fileBytes := ReadFileBytes(path)
    lines := []string{}
    separator := []byte("\n\n")
    for _, line := range bytes.Split(fileBytes, separator) {
        if string(line) != "" {
            lines = append(lines, string(line))
        }
    }

    sections := [][][]int{}
    for i, section := range lines {
        nums := [][]int{}
        lineStrs := strings.Split(section, "\n")
        separator := ","
        if i == 0 {
            separator = "|"
        }
        for _, lineStr := range lineStrs {
            if lineStr == "" {
                continue
            }
            numL := []int{}
            for _, numStr := range strings.Split(lineStr, separator) {
                num, _ := strconv.Atoi(numStr)
                numL = append(numL, num)
            }
            nums = append(nums, numL)
        }
        sections = append(sections, nums)
    }
    return sections
}

이제 규칙의 각 페이지 번호 목록에 색인이 매핑되었습니다.

1부

이제 1부에서는 각 페이지 업데이트(줄)를 반복한 다음 페이지 번호가 규칙을 따르고 있는지 확인해야 하며, 각 번호는 규칙을 따라야 합니다. 즉, 숫자가 특정 숫자 뒤에 있지만 규칙에 따라 그 이전이어야 한다고 명시되어 있는 경우 해당 업데이트의 페이지 번호 매기기 규칙을 위반한 것이므로 올바른 순서의 페이지로 간주할 수 없으므로 중간 페이지를 추가해야 합니다. 1부의 답변으로 올바르게 정렬된 각 업데이트의 번호입니다.

이를 위해 각 페이지 업데이트를 반복한 다음 해당 페이지 업데이트의 각 숫자를 반복해야 합니다. 정수 목록이 있는 정수 맵입니다. 이제 현재 우리가 속한 숫자가 규칙에 있는 숫자보다 앞에 있는지 확인해야 합니다. 그래서 우리는 정수 목록을 인덱스로 포함하는 숫자 맵인 우리가 만든 숫자 인덱스를 사용하여 현재 숫자의 인덱스를 확인합니다. 따라서 현재 번호를 맵의 키로 사용하고 목록의 인덱스를 현재 행/페이지 업데이트 수로 사용하여 맵의 인덱스 목록을 얻습니다.

그런 다음 현재 숫자에 대한 색인을 얻은 후에는 해당 규칙의 모든 숫자인 두 번째 숫자에 대해 동일한 색인을 얻습니다. 규칙의 해당 숫자가 해당 페이지 줄/업데이트에 존재하는 경우 즉, -1이 아니고 그렇다면 유사하게 인덱스를 가져와서 규칙에 따라 현재 숫자 뒤에 나타나는지 확인합니다. 따라서 숫자가 규칙을 위반하면 페이지 업데이트가 올바르지 않은 것으로 표시해야 합니다. 주문하세요.

해당 페이지 업데이트에 대한 색인 규칙을 위반한 것으로 확인되어 해당 순서를 false로 표시합니다. 순서가 지정된 플래그가 여전히 true인 경우 해당 페이지 업데이트의 중간 요소로 점수를 업데이트합니다.

func ConstructRules(rulesList [][]int) map[int][]int {
    rules := make(map[int][]int)
    for _, rule := range rulesList {
        rules[rule[0]] = append(rules[rule[0]], rule[1])
    }
    return rules
}

다시 말해서, 정수 목록이 있는 정수 맵과 페이지 업데이트에 따라 정수 목록인 페이지로 규칙과 숫자 인덱스가 있는 GetOrderedPage라는 함수를 만듭니다. 이 함수의 출력으로 점수를 반환합니다.

각 페이지 업데이트를 반복한 다음 업데이트의 각 페이지 번호를 통해 해당 번호의 규칙을 확인하고 해당 번호의 인덱스가 현재 번호보다 낮으면 주문되지 않은 것으로 표시합니다. 각 페이지 업데이트가 끝날 때 순서가 올바른 경우 페이지 업데이트의 중간 요소로 점수를 업데이트합니다.

이제 1부를 요약하겠습니다. 올바르게 주문된 페이지 업데이트의 점수를 얻으면 됩니다.

2부

그러나 2부에서는 페이지 업데이트가 순서대로 되었는지 확인하고, 그렇지 않다면 순서대로 만들어야 합니다.

파트 2에서도 비슷한 작업을 수행합니다. 각 페이지 업데이트를 반복해야 하며 해당 페이지 업데이트의 각 번호에 대해 규칙을 위반했는지 여부를 확인해야 합니다. 숫자에 관계없이 규칙을 위반하면 주문한 플래그를 false로 표시하고 이를 사용하여 페이지 업데이트 순서를 수정합니다. 해당 페이지 라인/업데이트에서 페이지를 업데이트한 후 페이지 업데이트 순서를 수정한 중간 요소로 점수를 추가해야 합니다.

47|53
97|13
97|61
97|47
75|29
61|13
75|53
29|13
97|29
53|29
61|53
97|53
61|29
47|13
75|47
97|75
47|61
75|61
47|29
75|13
53|13

75,47,61,53,29
97,61,53,29,13
75,29,13
75,97,47,61,53
61,13,29
97,13,75,29,47

페이지 행이나 페이지 업데이트 및 규칙을 받아들이는 CorrectPageOrder 함수를 구현해야 하며, 모든 규칙을 따르는 페이지를 채우는 새 페이지 업데이트를 생성해야 합니다.

따라서 먼저 초기화된 요소 인덱스를 추적하고 그 이전 요소를 이동해야 하는 경우 인덱스를 업데이트합니다.

따라서 페이지 업데이트의 모든 숫자를 반복하고 규칙의 숫자 앞에 인덱스를 설정합니다. 규칙 맵에서 그러한 숫자를 발견하면 해당 숫자의 인덱스로 인덱스를 업데이트해야 합니다.

그리고 요소를 교체하려는 인덱스를 얻은 후에는 해당 인덱스 앞에 슬라이스를 만들고 그 숫자를 추가한 다음 해당 인덱스 뒤에 모든 것을 추가합니다.

func ReadFileSections(path string) [][][]int {

    fileBytes := ReadFileBytes(path)
    lines := []string{}
    separator := []byte("\n\n")
    for _, line := range bytes.Split(fileBytes, separator) {
        if string(line) != "" {
            lines = append(lines, string(line))
        }
    }

    sections := [][][]int{}
    for i, section := range lines {
        nums := [][]int{}
        lineStrs := strings.Split(section, "\n")
        separator := ","
        if i == 0 {
            separator = "|"
        }
        for _, lineStr := range lineStrs {
            if lineStr == "" {
                continue
            }
            numL := []int{}
            for _, numStr := range strings.Split(lineStr, separator) {
                num, _ := strconv.Atoi(numStr)
                numL = append(numL, num)
            }
            nums = append(nums, numL)
        }
        sections = append(sections, nums)
    }
    return sections
}

따라서 이 함수는 숫자의 인덱스를 찾아 가장 왼쪽(목록의 시작 부분)에 배치하여 해당 숫자에 대한 규칙을 위반하지 않도록 한 다음 슬라이스를 생성하여 해당 숫자를 앞에 추가합니다. 색인을 생성하고 해당 색인 뒤의 모든 항목을 추가합니다.

여기까지 2부에서 페이지 순서에 차이가 있을 경우 페이지 순서를 업데이트했습니다.

여기 GitHub에서 제 솔루션을 확인하실 수 있습니다.

Advent of Code ay n Golang: Ordering Pages 미스터 파괴자 / 출현_코드

코드의 출현

결론

그럼 Golang의 Advent of Code 5일차는 여기까지입니다. 제안 사항과 이에 접근한 방법이 있으면 알려주시기 바랍니다. 더 나은 솔루션이 있나요?

행복한 코딩하세요 :)

위 내용은 코드의 출현 ay n Golang: 주문 페이지의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.