0

0

Golang 代码的出现:排序页面

心靈之曲

心靈之曲

发布时间:2024-12-12 13:45:10

|

320人浏览过

|

来源于dev.to

转载

介绍

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

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

Golang 代码的出现:排序页面 破坏先生 / 代码出现

代码的出现

输入

在第 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 部分的处理中使用它。

阅读部分

因此,我们需要解析这些部分并以更易于访问的数据结构读取它们。

一种方法是

立即学习go语言免费学习笔记(深入)”;

  • 包含两个部分的列表

  • 第一部分将是一个列表

    • 该列表将是一个整数列表,用于保存两个整数,即用于规则
  • 第二部分将是一个列表

    • 列表将是一个整数列表,用于保存页面列表

因此,数据结构看起来像一个整数列表的列表。

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,因此对于每一行,我们需要为该数字附加一个索引,如下所示:

# 75

75,47,61,53,29  ->  0
97,61,53,29,13  -> -1
75,29,13        ->  0
75,97,47,61,53  ->  0
61,13,29        -> -1
97,13,75,29,47  ->  2

75[0,-1,0,0,-1,2]

# map[int][]int
# 75 -> int
# [0,-1,0,0,-1,2] -> []int

所以,在上面的例子中,我们以75为参考,我们将得到每个页码列表的索引,并得到75出现的索引列表。

页面出现滚动条后才出现的返回顶部代码
页面出现滚动条后才出现的返回顶部代码

页面出现滚动条后才出现的返回顶部代码

下载

现在,这可以通过以下函数来完成:

func getpageindices(rules map[int][]int, pages [][]int) map[int][]int {
    nums := make(map[int]bool)
    for num, list := range rules {
        nums[num] = true
        for _, elem := range list {
            if !nums[elem] {
                nums[elem] = true
            }
        }
    }

    numindices := make(map[int][]int)
    for num, _ := range nums {
        for _, numline := range pages {
            index := -1
            for i, n := range numline {
                if n == num {
                    index = i
                }
            }
            numindices[num] = append(numindices[num], index)
        }
    }
    return numindices
}

因此,我们现在已经根据规则将索引映射到每个页码列表。

第 1 部分

现在,对于第一部分,我们需要迭代每个页面更新(行),然后我们需要检查页码是否遵循规则,每个数字都应该遵循规则。这意味着,如果一个数字在某个数字之后,但规则规定它应该在之前,那么它就违反了该更新中的页码规则,因此我们不能将其视为正确的有序页面,我们需要添加中间页面每个更新的编号已正确排序为第一部分的答案。

为此,我们迭代每个页面更新,然后我们需要迭代该页面更新中的每个数字,我们获得与该数字关联的所有规则(让我们称之为当前数字),因为我们有一个带有整数列表的整数映射。现在,我们必须检查当前所在的数字是否在其规则中的数字之前。因此,我们使用我们创建的数字索引来检查当前数字的索引,该索引是一个以整数列表作为索引的数字映射。因此,我们获取地图的索引列表,其中当前编号作为地图的键,列表中的索引作为我们当前所在的行/页面更新的数量。

然后,一旦我们获得了当前数字的索引,我们就获得了第二个数字的相同索引,即其规则中的所有数字,并且如果其规则中的该数字存在于该页行/更新中,即它是不是-1,如果是这种情况,我们类似地获取它的索引,并检查它是否出现在符合规则的当前数字之后,因此,如果任何数字违反规则,我们需要将页面更新标记为不正确订购。

当我们发现该页面更新的索引规则被违反时,我们将订单标记为 false。如果我们看到有序标志仍然为 true,我们会使用该页面更新的中间元素来更新分数。

func getorderedpages(rules, numindices map[int][]int, pages [][]int) int {
    score := 0

    for index, pageline := range pages {
        ordered := true
        for _, num1 := range pageline {
            rule := rules[num1]
            index1 := numindices[num1][index]
            for _, num2 := range rule {
                index2 := numindices[num2][index]
                if index1 == -1 || index2 == -1 {
                    continue
                }
                if index1 > index2 {
                    ordered = false
                }
            }
        }
        if ordered {
            score += pageline[int(len(pageline)/2)]
        }
    }
    return score
}

因此,重申一下,我们创建一个名为 getorderedpage 的函数,其中包含规则和数字索引作为带有整数列表的整数映射,以及页面更新时的整数列表。我们返回分数作为该函数的输出。

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

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

第2部分

但是在第 2 部分中,我们需要检查页面更新是否按顺序进行,如果不按顺序进行更新。

我们对第二部分做了类似的事情,我们需要迭代每个页面更新,并且对于该页面更新中的每个数字,我们需要检查是否违反规则,如果遇到以下情况对于任何数字都违反了规则,我们将有序标志标记为 false,我们将使用它来纠正页面更新的顺序。更新该页面行/更新中的页面后,我们需要添加页面更新正确顺序的中间元素的分数。


func getcorrectorderedpages(rules, numindices map[int][]int, pages [][]int) int {

    score := 0
    for index, pageline := range pages {
        ordered := true
        for _, num1 := range pageline {
            rule := rules[num1]
            index1 := numindices[num1][index]
            for _, num2 := range rule {
                index2 := numindices[num2][index]
                if index1 == -1 || index2 == -1 {
                    continue
                }
                if index1 > index2 {
                    ordered = false
                }
            }
        }
        if !ordered {
            newline := correctpageorder(pageline, rules)
            score += newline[len(newline)/2]
        }
    }
    return score
}

我们需要实现 correctpageorder 函数,该函数接受页面行或页面更新和规则,我们需要创建一个新的页面更新,它将填充遵循所有规则的页面。

因此,我们首先跟踪初始化的元素索引,如果需要移动它之前的元素,则更新索引。

因此,我们迭代页面更新中的所有数字,并在规则中的任何数字之前设置索引,如果我们在规则映射中遇到任何此类数字,我们需要使用该数字的索引来更新索引。

一旦我们获得了要交换元素的索引,我们就在该索引之前创建一个切片并将该数字附加到其中,并在该索引之后附加所有内容。

func CorrectPageOrder(line []int, rules map[int][]int) []int {
    newLine := []int{}
    for _, num := range line {
        index := make(map[int]int)
        for i, n := range newLine {
            index[n] = i
        }
        newInsertIndex := len(newLine)
        for _, rule := range rules[num] {
            if idx, ok := index[rule]; ok {
                if newInsertIndex > idx {
                    newInsertIndex = idx
                }
            }
        }
        afterNum := slices.Clone(newLine[newInsertIndex:])
        newLine = append(newLine[:newInsertIndex], num)
        newLine = append(newLine, afterNum...)
    }
    return newLine
}

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

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

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

Golang 代码的出现:排序页面 破坏先生 / 代码出现

代码的出现

结论

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

快乐编码:)

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

178

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

226

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

337

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

208

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

389

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

195

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

190

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

192

2025.06.17

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

36

2026.01.14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 2.7万人学习

Git版本控制工具
Git版本控制工具

共8课时 | 1.5万人学习

Git中文开发手册
Git中文开发手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号