我所看到的各个阶段的详细说明:
没有一个感觉特别困难。
其中一些实际上看起来像是另一个有趣的算法挑战!
我想把这个:
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......
第一个例子:
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
成功!它为示例输入生成正确的答案!
它对我的拼图输入也会有同样的作用吗?
...
是的!!!
呜呼!!!
第二部分会有什么转折?轻微的规则调整还是规模上的挑战?
是零件。现在完整了。
这肯定需要对我的算法进行一些调整。
可能更强大地跟踪间隙和块的大小。
我正在跟踪每个空的位置。
我想我需要跟踪每个空的位置以及大小。
那会是什么样子?
刮掉那个。也许是新策略。
使用第一个示例:
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......
我立即找到匹配的。
结果:
0099811188827773336446555566..............
这个策略肯定行不通。
我不喜欢这个对性能的影响。
但我相信它会起作用......只要它完成运行。
对于磁盘输入中的每个数字,我将记录为列表项:
举个例子:
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
效果很好!我可以看到文件被移动到的位置,并更轻松地排除代码故障!
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++ } }
关于示例拼图输入?是的!
关于我的拼图输入?
...
是啊SSSS!
哇。我很惊讶。我为第 2 部分提交的数字几乎与第 1 部分相同。我认为会更高。
我没有兴趣进一步调查。
我宁愿带着我的两颗来之不易的金星一起走到第十天。
再见第九天!
以上是磁盘碎片的详细内容。更多信息请关注PHP中文网其他相关文章!