搜索
首页后端开发GolangGolang 代码的出现:排序页面

介绍

这是代码出现的第五天,今天我们遇到了一个有趣的页面排序问题。让我们深入探讨这个问题以及我是如何解决它的。如果平静地思考,这是一个非常简单的问题,否则,它会陷入地图、列表和索引的混乱中。

您可以在 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,如果是这种情况,我们类似地获取它的索引,并检查它是否出现在符合规则的当前数字之后,因此,如果任何数字违反规则,我们需要将页面更新标记为不正确订购。

当我们发现该页面更新的索引规则被违反时,我们将订单标记为 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 的函数,其中包含规则和数字索引作为带有整数列表的整数映射,以及页面更新时的整数列表。我们返回分数作为该函数的输出。

我们迭代每个页面更新,然后通过更新中的每个页码,检查该数字的规则,如果该数字的索引低于当前数字,我们将其标记为未排序,因此在每个页面更新的末尾,如果顺序正确,我们会使用页面更新的中间元素更新分数。

所以,这就是第一部分的总结,我们只需要获得正确排序的页面更新的分数即可。

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

因此,这个函数将找到一个数字的索引,将其放置在最左边(列表的开头),这样我们就不会违反该数字的任何规则,然后我们创建一个切片来将该数字附加到之前该索引并附加该索引后的所有内容。

第二部分就是这样,如果页面顺序有任何差异,我们已经更新了页面顺序。

您可以在 GitHub 上查看我的解决方案。

Advent of Code ay n Golang: Ordering Pages 破坏先生 / 代码出现

代码的出现

结论

所以,这就是 Golang 代码降临的第五天,如果您有任何建议,以及您是如何实现的,请告诉我。有更好的解决方案吗?

快乐编码:)

以上是Golang 代码的出现:排序页面的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
实施静音和锁以寻求线程安全性实施静音和锁以寻求线程安全性May 05, 2025 am 12:18 AM

在Go中,使用互斥锁和锁是确保线程安全的关键。1)使用sync.Mutex进行互斥访问,2)使用sync.RWMutex处理读写操作,3)使用原子操作进行性能优化。掌握这些工具及其使用技巧对于编写高效、可靠的并发程序至关重要。

基准测试和分析并发GO代码基准测试和分析并发GO代码May 05, 2025 am 12:18 AM

如何优化并发Go代码的性能?使用Go的内置工具如gotest、gobench和pprof进行基准测试和性能分析。1)使用testing包编写基准测试,评估并发函数的执行速度。2)通过pprof工具进行性能分析,识别程序中的瓶颈。3)调整垃圾收集设置以减少其对性能的影响。4)优化通道操作和限制goroutine数量以提高效率。通过持续的基准测试和性能分析,可以有效提升并发Go代码的性能。

并发程序中的错误处理:避免常见的陷阱并发程序中的错误处理:避免常见的陷阱May 05, 2025 am 12:17 AM

避免并发Go程序中错误处理的常见陷阱的方法包括:1.确保错误传播,2.处理超时,3.聚合错误,4.使用上下文管理,5.错误包装,6.日志记录,7.测试。这些策略有助于有效处理并发环境中的错误。

隐式接口实现:鸭打字的力量隐式接口实现:鸭打字的力量May 05, 2025 am 12:14 AM

IndimitInterfaceImplementationingingoembodiesducktybybyallowingTypestoSatoSatiSatiSatiSatiSatiSatsatSatiSatplicesWithouTexpliclIctDeclaration.1)itpromotesflemotesflexibility andmodularitybybyfocusingion.2)挑战挑战InclocteSincludeUpdatingMethodSignateSignatiSantTrackingImplections.3)工具li

进行错误处理:最佳实践和模式进行错误处理:最佳实践和模式May 04, 2025 am 12:19 AM

在Go编程中,有效管理错误的方法包括:1)使用错误值而非异常,2)采用错误包装技术,3)定义自定义错误类型,4)复用错误值以提高性能,5)谨慎使用panic和recover,6)确保错误消息清晰且一致,7)记录错误处理策略,8)将错误视为一等公民,9)使用错误通道处理异步错误。这些做法和模式有助于编写更健壮、可维护和高效的代码。

您如何在GO中实施并发?您如何在GO中实施并发?May 04, 2025 am 12:13 AM

在Go中实现并发可以通过使用goroutines和channels来实现。1)使用goroutines来并行执行任务,如示例中同时享受音乐和观察朋友。2)通过channels在goroutines之间安全传递数据,如生产者和消费者模式。3)避免过度使用goroutines和死锁,合理设计系统以优化并发程序。

在GO中构建并发数据结构在GO中构建并发数据结构May 04, 2025 am 12:09 AM

Gooffersmultipleapproachesforbuildingconcurrentdatastructures,includingmutexes,channels,andatomicoperations.1)Mutexesprovidesimplethreadsafetybutcancauseperformancebottlenecks.2)Channelsofferscalabilitybutmayblockiffullorempty.3)Atomicoperationsareef

将GO的错误处理与其他编程语言进行比较将GO的错误处理与其他编程语言进行比较May 04, 2025 am 12:09 AM

go'serrorhandlingisexplicit,治疗eRROSASRETRATERTHANEXCEPTIONS,与pythonandjava.1)go'sapphifeensuresererrawaresserrorawarenessbutcanleadtoverbosecode.2)pythonandjavauseexeexceptionseforforforforforcleanerCodebutmaymobisserrors.3)

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具