磁盘碎片
代码来临 2024 年第 9 天
第 1 部分
三相拳套。令人兴奋!?
我所看到的各个阶段的详细说明:
- 将内存表示为列表
- 将值从末尾移动到开头
- 走线计算校验和
没有一个感觉特别困难。
其中一些实际上看起来像是另一个有趣的算法挑战!
列清单
我想把这个:
12345
进入此:
0..111....22222
我需要考虑:
- 使用循环
- 检查偶数和奇数索引
- 从 0 开始将值加 1
这是我的磁盘生成算法:
let id = 0 let disk = [] for (let i = 0; i < input.length; i++) { if (i % 2 == 1) { // Odd for (let j = 0; j < +input[i]; j++) { disk.push('.') } } else { // Even for (let j = 0; j < +input[i]; j++) { disk.push(id) } id++ } }
就像魅力一样!
将值从结束移动到开始
让这一切变得更容易的是拥有磁盘上所有空位置的列表。
我需要在两个地方更新我的算法:
- 一个新变量:let empty = []
- 插入 . 后的新操作:empty.push(disk.length - 1)
在示例中测试它会显示每个 .!
的预期索引号这是当我将值从列表末尾移动到开头并向前移动时将迭代的列表。
但是等等。
这可能比我想象的更困难。
我如何知道何时停止尝试移动值?
- 我是否迭代空索引列表?我什么时候应该停止?
- 我是否向后迭代磁盘?我什么时候应该停止?
顿悟:神奇的数字 10
这是简短示例的最后状态:
022111222......
第一个例子:
0099811188827773336446555566..............
这意味着有一个点,所有 id 都在左边,所有空白都在右边。
我如何检查该状态?
输入:数字 10。
连续空白空间的数量永远不会高于 9。
所以,如果我遇到一个空白空间,向前查找 9 个空格(或到磁盘列表的末尾),并看到所有空白空间,我就知道我已经完成了碎片化。
我想我知道如何编写这个算法的其余部分!
编写我的碎片算法
这是工作算法:
let diskI = disk.length - 1 let emptyI = 0 while (true) { while (disk[diskI] == '.') { diskI-- } disk[empty[emptyI]] = disk[diskI] disk[diskI] = '.' emptyI++ diskI-- if (disk.slice(empty[emptyI],empty[emptyI] + 10).every(el => el == '.')) { break; } }
工作原理:
Two trackers: - one for my place in the disk - one for my place in the list of empty slots Do until manually escaped Do as long as the current place in the disk is an empty slot Adjust the tracker one to the left Swap the values at each tracker Decrement the disk tracker Increment the empty tracker If there are 9 empty slots contiguous with the current empty slot Escape the loop
幸运的是,我看到了与两个示例相同的输出!
计算校验和
这看起来相当简单明了:
let part1 = disk.slice(0, disk.indexOf('.')).reduce((checksum, id, position) => { checksum += (+id * position) return checksum }, 0)
伪代码:
Extract all values up to the first empty cell Iterate through each value, amassing a total Increment the accumulator by the product of the value and its index
成功!它为示例输入生成正确的答案!
它对我的拼图输入也会有同样的作用吗?
...
是的!!!
呜呼!!!
第二部分会有什么转折?轻微的规则调整还是规模上的挑战?
第2部分
一个有趣的转折
是零件。现在完整了。
这肯定需要对我的算法进行一些调整。
可能更强大地跟踪间隙和块的大小。
实施我的第一个策略
我正在跟踪每个空的位置。
我想我需要跟踪每个空的位置以及大小。
那会是什么样子?
刮掉那个。也许是新策略。
使用第一个示例:
12345
文件块大小为奇数:
0..111....22222
空单元格大小是偶数:
let id = 0 let disk = [] for (let i = 0; i < input.length; i++) { if (i % 2 == 1) { // Odd for (let j = 0; j < +input[i]; j++) { disk.push('.') } } else { // Even for (let j = 0; j < +input[i]; j++) { disk.push(id) } id++ } }
从奇数末尾和偶数开头开始,寻找大于等于奇数的偶数:
022111222......
我立即找到匹配的。
结果:
- 奇数移动
- 偶数减少
- 但是现在两个奇数没有间隙了
- 并且我丢失了第二个2s ID
0099811188827773336446555566..............
这个策略肯定行不通。
实施我的第二个策略
我不喜欢这个对性能的影响。
但我相信它会起作用......只要它完成运行。
对于磁盘输入中的每个数字,我将记录为列表项:
- 文件块或空单元格
- 长度
- ID
举个例子:
let diskI = disk.length - 1 let emptyI = 0 while (true) { while (disk[diskI] == '.') { diskI-- } disk[empty[emptyI]] = disk[diskI] disk[diskI] = '.' emptyI++ diskI-- if (disk.slice(empty[emptyI],empty[emptyI] + 10).every(el => el == '.')) { break; } }
将成为:
Two trackers: - one for my place in the disk - one for my place in the list of empty slots Do until manually escaped Do as long as the current place in the disk is an empty slot Adjust the tracker one to the left Swap the values at each tracker Decrement the disk tracker Increment the empty tracker If there are 9 empty slots contiguous with the current empty slot Escape the loop
呃,让我们清理一下:
let part1 = disk.slice(0, disk.indexOf('.')).reduce((checksum, id, position) => { checksum += (+id * position) return checksum }, 0)
我将通过数据类型区分间隙和文件块。
移动文件块在更改后的示例输入中将如下所示:
Extract all values up to the first empty cell Iterate through each value, amassing a total Increment the accumulator by the product of the value and its index
每 10 万次迭代都会涉及到:
- 在大数组中搜索项目
- 就地改变数组
两者都是非常昂贵的任务。
但这是我能想到解决这个难题的唯一方法。
所以,这就是我的方法。
编写我的策略
这是获取上述数据架构的 JavaScript:
2333133121414131402
我将如何开始和结束我的主循环?
从文件 ID 号最高的文件开始,按照文件 ID 号递减的顺序尝试将每个文件移动一次
似乎从后到前移动就可以满足我的需要。
这个 for 循环骨架应该可以工作:
[2,4,1,4,2,5,5,3,5,2]
查找、移动和替换
[3,3,3,1,1,1,1,1,0]
if 中的第二个子句是我最后一次调试。太早设置最低 ID 了。
编码磁盘打印机
我意识到我必须近乎实时地看到我的磁盘碎片。至少有一个日志,就像示例演练中一样。
值得庆幸的是,编码并不困难。只是我混合了两个索引并看到一些真正奇怪的输出的部分:
12345
- 我建立了一个字符串
- 基于磁盘中项目的类型
- 无论哪种方式,我都会创建一个数组并用 .s 或块的 ID 填充它
效果很好!我可以看到文件被移动到的位置,并更轻松地排除代码故障!
喜欢我所看到的
0..111....22222
看起来我的文件移动算法有效!
最后一步是计算新的校验和。
最后,更多数学
通过双重归约:
let id = 0 let disk = [] for (let i = 0; i < input.length; i++) { if (i % 2 == 1) { // Odd for (let j = 0; j < +input[i]; j++) { disk.push('.') } } else { // Even for (let j = 0; j < +input[i]; j++) { disk.push(id) } id++ } }
- 第一个reduce为我提供了一个由ids和.s组成的分散数组
- 当项目是 id 时,第二个reduce 执行适当的数学计算,而当项目是 .
有效吗?
关于示例拼图输入?是的!
关于我的拼图输入?
...
是啊SSSS!
哇。我很惊讶。我为第 2 部分提交的数字几乎与第 1 部分相同。我认为会更高。
我没有兴趣进一步调查。
我宁愿带着我的两颗来之不易的金星一起走到第十天。
再见第九天!
以上是磁盘碎片的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

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

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。 1)C 用于解析JavaScript源码并生成抽象语法树。 2)C 负责生成和执行字节码。 3)C 实现JIT编译器,在运行时优化和编译热点代码,显着提高JavaScript的执行效率。
