我有一个程序,递归地将自动换行计算到指定的行长度。
def wrap(input, lineSpaces):
if len(input) <= lineSpaces: # Base case
return input
temp = input.rfind(" ", 0, lineSpaces - 1) # Parsing
if temp == -1:
return input
else:
prev = input[:temp+1]
next = wrap(input[temp+1:], lineSpaces)
wrap.penalty = (lineSpaces-len(prev)+1)**3 +(lineSpaces-len(next)+1)**3 # Penalty calculation
return prev+'\n'+next
# I/O
list = []
penalties = []
M = int(raw_input())
for i in xrange(0, M):
lineSpaces = int(raw_input())
input = raw_input()
list.append(wrap(input, lineSpaces))
penalties.append(wrap.penalty)
for i in xrange(0, len(list)):
print "penalty: ", penalties[i]
print list[i]+"\n"
使用以下输入:
3
20
This is the first paragraph that you need to print
30
This is another paragraph that you need to print and it ends in a very long word onetwothreefourfivesixseven
36
This paragraph all fits on one line
我期待输出:
penalty: 35
This is the first
paragraph that you
need to print
penalty: 216
This is another paragraph
that you need to print and
it ends in a very long word
onetwothreefourfivesixseven
penalty: 0
This paragraph all fits on one line
然而,我实际上得到了输出:
penalty: -1701
This is the first
paragraph that you
need to print
penalty: -148752
This is another paragraph
that you need to print and
it ends in a very long word
onetwothreefourfivesixseven
penalty: -148752
This paragraph all fits on one line
你可以看到,我的惩罚输出是错误的。我想将我的罚分计算为每个段落中所有行的(lineSpaces-len(line)+1)**3
之和,除了每个段落的最后一行,罚分为0.似乎每次调用(lineSpaces-len(prev)+1)**3
段落(除了最后一个,应该是0)返回正确的值。我的逻辑有什么问题?
答案 0 :(得分:1)
您在某些方面对罚款的计算是错误的。首先,将next
设置为等于递归调用的返回值。这仍然与原始版本一样长,或者更长,因为您所做的就是为它添加换行符。但是你计算了这个惩罚。在每次调用时,您正在计算该调用适合一行的惩罚,以及传递给下一个递归调用的其他所有内容的惩罚。
此外,因为您将此值存储在wrap.penalty
上,所以在每次调用后都会覆盖它。由于您从未对wrap.penalty
的旧值执行任何操作,因此忽略除最后一个之外的所有计算。
使用函数属性来存储这样的数据是一个危险的游戏。只有一个 wrap
,因此只有一个wrap.penalty
,所以它不像每个递归调用都有自己的版本penalty
;他们都在踩着同一个人。而不是将值存储在wrap.penalty
中,最好将它与包装文本一起返回,如下所示:
def wrap(instr, lineSpaces):
if len(instr) <= lineSpaces: # Base case
return instr, 0
temp = instr.rfind(" ", 0, lineSpaces - 1) # Parsing
if temp == -1:
return instr, 0
else:
prev = instr[:temp+1]
next, penalty = wrap(instr[temp+1:], lineSpaces)
penalty += (lineSpaces-len(prev)+1)**3 # Penalty calculation
return prev+'\n'+next, penalty
然后:
>>> wrap("This is the first paragraph that you need to print", 20)
('This is the first \nparagraph that you \nneed to print', 35)
在每次调用时,我将从递归调用返回的惩罚添加到为刚刚解析的行计算的惩罚。 Pham Trung在评论中建议,你也可以在包装后的单独步骤中计算惩罚。
我还将您的变量名称从input
更改为instr
。您应该避免使用名称input
,因为该名称有内置函数。 (出于同样的原因,list
也不是变量的好名称。)