最少的磁盘写入可对多个文件进行碎片整理


18

介绍

磁盘是一个线性容器,其块0通过索引size-1

文件是该文件使用的块索引的命名列表。

示例文件系统表示如下:

15 ALPHA=3,5 BETA=11,10,7

“磁盘有15个块,文件ALPHA的第一个块是索引3处的磁盘块。”

磁盘映射可以这样绘制:

Block Index  00  01  02  03  04  05  06  07  08  09  10  11  12  13  14
Contents    |   |   |   |A0 |   |A1 |   |B2 |   |   |B1 |B0 |   |   |   |

当磁盘中的所有文件连续存储时,该磁盘将被视为已碎片整理。

你的目标:

发出最短合法移动序列,以对给定的磁盘进行碎片整理。

法律行动

移动包含三部分信息:文件,要移动的文件中的块的索引以及要移动到的磁盘块的索引。

例如

ALPHA:1>4

“将文件ALPHA的块1移动到磁盘的块4。”

此举之后,示例文件系统现在是

15 ALPHA=3,4 BETA=11,10,7

Block Index  00  01  02  03  04  05  06  07  08  09  10  11  12  13  14
Contents    |   |   |   |A0 |A1 |   |   |B2 |   |   |B1 |B0 |   |   |   |

先前居住的磁盘块被隐式清除。同样,您可以将其视为交换磁盘上的两个块,但是交换中的一个块必须为空

数据可能不会被破坏。文件在任何阶段都不能共享块,并且移动必须在磁盘范围内。以下举动是非法的:(ALPHA:0>10由BETA拥有),ALPHA:3>0(在ALPHA中没有这样的块),ALPHA:0>-1(没有这样的磁盘索引),ALPHA:0>15(磁盘索引太大)

例子1

完整解决以上示例。

ALPHA:0>4
BETA:0>9
BETA:2>11

文件在解决方案中不必相邻,而在它们内部是连续的。

例子2

这是一个更受约束的情况

输入:

10 A=1,2,3 B=6,7,8 C=4,5,0

输出:

B:2>9
B:1>8
B:0>7
C:2>6

该文件系统的进程为:

Block Index  00  01  02  03  04  05  06  07  08  09
Contents    |C2 |A0 |A1 |A2 |C0 |C1 |BO |B1 |B2 |   |
            |C2 |A0 |A1 |A2 |C0 |C1 |BO |B1 |   |B2 |
            |C2 |A0 |A1 |A2 |C0 |C1 |BO |   |B1 |B2 |
            |C2 |A0 |A1 |A2 |C0 |C1 |   |B0 |B1 |B2 |
            |   |A0 |A1 |A2 |C0 |C1 |C2 |B0 |B1 |B2 |

另一种方式来进行碎片整理这将通过向C:2>9再带上A下一个步骤,然后将C下一个步骤,然后执行C:2>5,但因为它含有比其他更多的动作,这将不是一个合法的解决方案

表示

您可以对输入使用任何表示形式,只要它与基本字符串相当接近即可。根据您的语言,第一个示例的输入可能表示为

"15 ALPHA=3,5 BETA=11,10,7"
[15," ","ALPHA","=",3,",",5," ","BETA","=",11,",",10,",",7]
(15,(("ALPHA",(3,5)),("BETA",(11,10,7))))
etc

类似地,输出可以是您所用语言所方便的任何东西,因为它是打印出来的日志,易于阅读,并且代表合法动作的有序列表,每个动作都由1)file-name,2)file-block-index描述,3)new-disk-block-index

"ALPHA:1>6 BETA:2>9"
(0=>(0=>"ALPHA",1=>"1",2=>"6"), 1=>(0=>"BETA",1=>"2",2=>"9"))
["ALPHA",1,6,"BETA",2,9]
etc

要求

您的代码必须接受任何大小的磁盘以及任何数量和大小的文件。

没有描述合法的初始文件系统状态的输入可能导致未定义的行为。

对于任何定义明确的输入,您的代码必须产生最短的动作解决方案。

您产生的所有举动必须合法;在应用您产生的每个步骤之后,文件系统必须处于有效状态。

您的代码必须针对所有有效输入而终止,即,它绝不应陷入循环中,在应用每次移动后文件系统应处于明显新的状态。

如果存在多个最短的解决方案,则可以选择任何一个作为有效解决方案。

最短的代码胜出。请在您的代码中至少发布一个新的非平凡示例输入及其输出。


我们如何找到任意磁盘的“最短序列”有多长时间?(因为如果答案A说最短的是6个动作,而答案B说最短的是5个动作,那么答案A会被取消资格吗?)
ASCIIThenANSI

如果需要,广度优先搜索可以提供参考解决方案。
spraff

2
作为[atomic-code-golf]挑战,这可能会更好。这样您将获得更多答案。而不是最短的代码,赢家将是磁盘写入最少的答案。
mbomb007'2013/

Answers:


1

Python 3,295字节

S,F=eval(input());d=[0]*S;E=enumerate
for n,P in F:
 for j,p in E(P):d[int(p)]=n,j
Z=[(d,())]
while Z:d,p=Z.pop(0);any(e and(e[0],e[1]+1)in d and(S<j+2or(e[0],e[1]+1)!=d[j+1])for j,e in E(d))or print(p).q;{d[j]or exec("D=d[:];D[j]=e;D[k]=0;Z+=(D,p+(e,j)),")for j,_ in E(d)for k,e in E(d)if d[k]}

在线尝试!


另一个测试案例

输入:
   7 ALEF = 6,4,0 BET = 5,1 GIMEL = 3

初始磁盘状态:
   A2 B1 __ G0 A1 B0 A0

解:
   ALEF:2> 2
   ALEF:0> 0
   投注:1> 6
   ALEF:1> 1

可视化解决方案:
   A2 B1 __ G0 A1 B0 A0
   __ B1 A2 G0 A1 B0 A0
   A0 B1 A2 G0 A1 B0 __
   A0 __ A2 G0 A1 B0 B1
   A0 A1 A2 G0 __ B0 B1

非高尔夫版本

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.