201903-3-损坏的RAID5
问题
思路
分类:
- 指定的块超出阵列总长度,则
print('-')
- 不超出阵列总长度
- 包含所请求数据的硬盘已知,则打印所请求的数据
- 现存的硬盘数足够(l >= n - 1),则通过异或计算获得缺失的数据
- 阵列不完整,现存的硬盘数不足够(l < n - 1),则
print('-')
核心算法在于计算所请求数据的硬盘地址和块偏移
实现
def func(txts): # 计算八位字符串异或值
out = 0
for txt in txts:
out = out ^ eval('0x' + txt)
return '%X' % (out,)
n, s, l = eval(input().replace(' ', ',')) # n硬盘的数目,s条带的大小,l现存的硬盘数目
disks = ['' for i in range(n)]
for i in range(l):
num, txt = input().split(' ')
disks[int(num)] = txt # disks列表存,i硬盘字符串数据[0,n)
max_num = len(disks[0]) // 8 * (n - 1) # 可访问块的最大序号
m = int(input()) # 查询的次数
for i in range(m):
num = int(input()) # 访问块的序号[0,max_num)
# 指定的块超出阵列总长度
if num >= max_num:
print('-')
# 对于每个查询,计算所请求数据的硬盘地址和块偏移
else:
addr_disk = num // (s * (n - 1)) * s + num % s # 盘内偏移块数
addr_c = num // (s * (n - 1)) # 层数
addr_n = (num // s) % (n - 1) # 层顺序
addr_p = n - 1 - addr_c % n # P区层偏移
addr_d = addr_p + 1 + addr_n if addr_p + 1 + \
addr_n < n else addr_n - (n - addr_p - 1) # 层偏移
# 如果包含所请求数据的硬盘已知,则打印所请求的数据
if disks[addr_d] != '':
print(disks[addr_d][addr_disk * 8:(addr_disk + 1) * 8])
# 如果现存的硬盘数足够(l >= n - 1),则通过异或计算获得缺失的数据
elif l >= n - 1:
txts = []
for i, txt in enumerate(disks):
if i != addr_d:
txts.append(txt[addr_disk * 8:(addr_disk + 1) * 8])
print(func(txts))
# 阵列不完整,现存的硬盘数不足够(l < n - 1)
else:
print('-')
1、计算字符串异或值
def func(txts): # 将输入的字符串中的每位之间进行异或运算 out = 0 for txt in txts: out = out ^ eval('0x' + txt) return '%X' % out
- 使用
^
运算符将输入的字符串中的每位之间进行异或运算eval()
函数被用于将每个输入列表中的字符串解释为十六进制整数值,以便执行异或运算。在每次循环迭代中,字符串'0x' + txt
被传递给eval()
函数,表示将十六进制字符串txt
转换为一个十六进制整数值。'%X'
:格式化符号将整数转换为十六进制2、
n, s, l = eval(input().replace(' ', ','))
# n硬盘的数目,s条带的大小,l现存的硬盘数目
eval()
函数用于将字符串当作 Python 代码执行,并返回执行结果。在这个例子中,replace()
函数返回的字符串被当作一个 Python 表达式执行,其中包含了三个整数值,这三个整数值用逗号,
分隔。eval()
函数将这个表达式求值,并将其结果赋给三个变量n
、s
和l
,这三个变量分别代表硬盘的数目、条带的大小和现存的硬盘数目。3、
addr_d = addr_p + 1 + addr_n if addr_p + 1 + \ addr_n < n else addr_n - (n - addr_p - 1) # 层偏移
例如,假设当前地址
addr_p
为 8,下一个地址addr_n
为 5,而总长度n
为 10。则按照上述计算方法,可以得到:addr_d = addr_p + 1 + addr_n if addr_p + 1 + addr_n < n else addr_n - (n - addr_p - 1) = 8 + 1 + 5 if 8 + 1 + 5 < 10 else 5 - (10 - 8 - 1) = 14 if 14 < 10 else 5 - 1 = 4
因此,下一个地址
addr_d
就是 4。4、
enumerate()
在 Python 中,
enumerate()
是一个内置函数,它用于在遍历可迭代对象时,同时返回该对象的元素以及该元素在可迭代对象中的索引。
Appendx
Python的位运算符
按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、同或
同或运算可以用按位异或(^)运算符和逻辑非(not)
运算符组合实现,具体的实现方式如下:
a = True
b = False
c = not (a ^ b) # c的值为True,因为a和b的值不同