Python:每日一题 49
本帖最后由 ooxx7788 于 2017-5-20 11:32 编辑转换电子表格的行列显示。
Spreadsheet Row Column
A1 R1C1
D5 R5C4
AA48 R48C27
BK12 R12C63
A1单元格,表示的是第一行R1,第一列C1
D5单元格,表示的是第五行R5,第四列C1
好了,现在请你给出一个函数def spreadsheet(s):,可以实现两者之间的相互转换。
测试代码忘记给了!
test.assert_equals(spreadsheet("A1"), "R1C1")
test.assert_equals(spreadsheet("R1C1"), "A1")
test.assert_equals(spreadsheet("R5C4"), "D5")
test.assert_equals(spreadsheet("AA48"), "R48C27")
test.assert_equals(spreadsheet("BK12"), "R12C63")
test.assert_equals(spreadsheet("R12C63"), "BK12")
test.assert_equals(spreadsheet("R85C26"), "Z85")
test.assert_equals(spreadsheet("R31C78"), "BZ31")
test.assert_equals(spreadsheet("BZ31"), "R31C78")
**** Hidden Message ***** def spreadsheet(s):
import re, functools
c = re.search(r'\D+', s).group()
r = re.search(r'\d+', s).group()
c_lst =
c = functools.reduce(lambda x, y: x * 26 + y, c_lst)
return 'R' + r + 'C' +str(c) 本帖最后由 jerryxjr1220 于 2017-5-19 13:17 编辑
import re
def spreadsheet(s):
if re.match('^R(\d{1,5})C(\d{1,5})$, s):
row, col = re.findall('^R(\d{1,5})C(\d{1,5})$, s)
col = int(col)
c = ''
while col > 0:
c = chr(col % 26 + 64) + c
col //= 26
return c + row
elif re.match('^({1,10})(\d{1,5})$, s):
col, row = re.findall('^({1,10})(\d{1,5})$, s)
c = 0
while len(col) > 0:
c = c * 26 + (ord(col) - 64)
col = col
return 'R' + row + 'C' + str(c)
else:
return None 冬雪雪冬 发表于 2017-5-19 12:39
相互转换! jerryxjr1220 发表于 2017-5-19 13:10
两个问题哦!
第一个,4,5,13,14都少一个'。程序是有语法错误的。
第二个:
Success!
Success!
Success!
Success!
Success!
Success!
Fail!A@85 not equals Z85
Fail!C@31 not equals BZ31
Success!
结果也是有错误的。"R85C26"第26列,85行,显然应该是Z85 本帖最后由 jerryxjr1220 于 2017-5-19 15:36 编辑
ooxx7788 发表于 2017-5-19 14:29
两个问题哦!
第一个,4,5,13,14都少一个'。程序是有语法错误的。
第二个:
import re
def spreadsheet(s):
if re.match('^R(\d{1,5})C(\d{1,5})$', s):
row, col = re.findall('^R(\d{1,5})C(\d{1,5})$', s)
col = int(col)
if col % 26 == 0:
col -= 1
c = ''
while col > 26:
c = chr((col - 1) % 26 + 65) + c
col //= 26
c = chr(col + 64) + c
return c[:-1] + 'Z' + row
else:
c = ''
while col > 26:
c = chr((col - 1) % 26 + 65) + c
col //= 26
c = chr(col + 64) + c
return c + row
elif re.match('^({1,10})(\d{1,5})$', s):
col, row = re.findall('^({1,10})(\d{1,5})$', s)
c = 0
while len(col) > 1:
c = c * 26 + (ord(col) - 64)
col = col
c = c * 26 + (ord(col) - 64)
return 'R' + row + 'C' + str(c)
else:
return None
for i in range(1, 100):
print(spreadsheet('R85C' + str(i)))
我看我原始的程序里是有引号的,不知道为啥粘贴上来就少了。
另外,在转换26倍数的时候由于%的问题好像是有错误,改正了。 ooxx7788 发表于 2017-5-19 14:29
两个问题哦!
第一个,4,5,13,14都少一个'。程序是有语法错误的。
第二个:
好像是code的格式问题,只要把我的程序放code /code之间就会出错。 ooxx7788 发表于 2017-5-19 14:07
相互转换!
重新写了。
def spreadsheet(s):
import re, functools
if re.search(r'\dC', s):
r, c = s.split('C')
c = int(c)
column = ''
while c:
column = chr(c % 26 + 64) + column
c //= 26
return column + r
else:
c = re.search(r'\D+', s).group()
r = re.search(r'\d+', s).group()
c_lst =
c = functools.reduce(lambda x, y: x * 26 + y, c_lst)
return 'R' + r + 'C' +str(c) 另外,写了一种反推的
import re
def spreadsheet(s):
def trans(ss):
col, row = re.findall('^({1,10})(\d{1,5})$', ss)
c = 0
while len(col) > 1:
c = c * 26 + (ord(col) - 64)
col = col
c = c * 26 + (ord(col) - 64)
return 'R' + row + 'C' + str(c)
if re.match('^R(\d{1,5})C(\d{1,5})$', s):
row, col = re.findall('^R(\d{1,5})C(\d{1,5})$', s)
for aa in range(64, 91):
A = chr(aa) if aa > 64 else ''
for bb in range(64, 91):
B = chr(bb) if bb > 64 else ''
for cc in range(64, 91):
C = chr(cc) if cc > 64 else ''
for dd in range(65, 91):
D = chr(dd) if dd > 64 else ''
col = A + B + C + D
if trans(col + row) == s:
return col + row
elif re.match('^({1,10})(\d{1,5})$', s):
return trans(s)
else:
return None 冬雪雪冬 发表于 2017-5-19 16:09
重新写了。
你的程序和我之前的一样的问题,当column为26的倍数时会出错。 本帖最后由 冬雪雪冬 于 2017-5-19 16:46 编辑
jerryxjr1220 发表于 2017-5-19 16:21
你的程序和我之前的一样的问题,当column为26的倍数时会出错。
是的,我再想想。新修改的。
def spreadsheet(s):
import re, functools
if re.search(r'\dC', s):
r, c = s.split('C')
c = int(c)
column = ''
while c:
c -= 1
column = chr(c % 26 + 65) + column
c //= 26
return column + r
else:
c = re.search(r'\D+', s).group()
r = re.search(r'\d+', s).group()
c_lst =
c = functools.reduce(lambda x, y: x * 26 + y, c_lst)
return 'R' + r + 'C' +str(c) jerryxjr1220 发表于 2017-5-19 16:21
你的程序和我之前的一样的问题,当column为26的倍数时会出错。
你的第一个答案还是有点问题,当s = 'R61574C53328'
第一个答案的结果是CZWB61574
第二个答案的结果是BZWB61574
而实际上,第二个答案是正确答案。
第一个答案条件分支的位置好像还是有点问题,在答案里面有Z的时候,好像会出问题。但是我也没想出来怎么改。
本帖最后由 jerryxjr1220 于 2017-5-19 17:23 编辑
ooxx7788 发表于 2017-5-19 17:03
你的第一个答案还是有点问题,当s = 'R61574C53328'
第一个答案的结果是CZWB61574
第二个答案的结果是B ...
反推的方法肯定是对的,只不过效率会相对比较低一点。
第一个答案的话,主要是由于%26取模的范围是(0~25),而实际(A~Z)对应的应该是(1~26)。
需要有一个合理的转换程序来匹配。似乎版主修改的方法应该是正确的。
暂时就以第二个答案为准好了。 def spreadsheet(s):
letter = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
letter = list(letter)
s = list(s)
x = []
y = []
if(s == 'R' and s.isdigit() and 'C' in s):
while 'C' in s:
y.append(s.pop())
y.reverse()
temp = int(''.join(y))
while temp:
x_int= temp % 26
temp = temp // 26
print(x_int)
if x_int == 0:
temp -= 1
x.append(letter)
print(x)
x.reverse()
x_str = ''.join(x)
y_str = ''.join(s)
return(x_str+y_str)
else:
num = 0
y_int = 0
temp = s.copy()
for i in range(len(''.join(temp))):
if not temp.isdigit():
y.append(temp)
s.remove(temp)
while y != []:
temp = y.pop()
for i in range(26):
if letter == temp:
y_int += (i+1) * (26 ** num)
num += 1
return('R'+''.join(s)+'C'+str(y_int))
当回首遇上转身 发表于 2017-5-20 02:49
R14208C2856
Your result is: 'DVE14208' should equal 'DEV14208' ooxx7788 发表于 2017-5-20 08:42
R14208C2856
Your result is: 'DVE14208' should equal 'DEV14208'
有两行缩进错了、、、 本帖最后由 当回首遇上转身 于 2017-5-20 09:29 编辑
这就对了
def spreadsheet(s):
letter = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
letter = list(letter)
s = list(s)
x = []
y = []
if(s == 'R' and s.isdigit() and 'C' in s):
while 'C' in s:
y.append(s.pop())
y.reverse()
temp = int(''.join(y))
while temp:
x_int= temp % 26
temp = temp // 26
if x_int == 0:
temp -= 1
x.append(letter)
x.reverse()
x_str = ''.join(x)
y_str = ''.join(s)
return(x_str+y_str)
else:
num = 0
y_int = 0
temp = s.copy()
for i in range(len(''.join(temp))):
if not temp.isdigit():
y.append(temp)
s.remove(temp)
while y != []:
temp = y.pop()
for i in range(26):
if letter == temp:
y_int += (i+1) * (26 ** num)
num += 1
return('R'+''.join(s)+'C'+str(y_int))
当回首遇上转身 发表于 2017-5-20 09:27
这就对了
确实OK了 冬雪雪冬 发表于 2017-5-19 12:39
A =
def f(x,y):
return 2*x+y*2
print functools.reduce(f, A)
这个返回值为啥是1呢, 是reduce()函数本身有什么机制吗 badaoqingchen 发表于 2017-5-20 21:50
这个返回值为啥是1呢, 是reduce()函数本身有什么机制吗
我的理解,函数f需要2个参数x和y,但A只有一个元素,无法满足要求,所以直接返回A了