鱼C论坛

 找回密码
 立即注册
查看: 5111|回复: 40

[技术交流] Python:每日一题 49

[复制链接]
发表于 2017-5-19 11:08:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 ooxx7788 于 2017-5-20 11:32 编辑

转换电子表格的行列显示。

  1. Spreadsheet        Row Column
  2. A1                 R1C1
  3. D5                 R5C4
  4. AA48               R48C27
  5. BK12               R12C63
复制代码


A1单元格,表示的是第一行R1,第一列C1
D5单元格,表示的是第五行R5,第四列C1

好了,现在请你给出一个函数def spreadsheet(s):,可以实现两者之间的相互转换。

测试代码忘记给了!
  1. test.assert_equals(spreadsheet("A1"), "R1C1")
  2. test.assert_equals(spreadsheet("R1C1"), "A1")
  3. test.assert_equals(spreadsheet("R5C4"), "D5")
  4. test.assert_equals(spreadsheet("AA48"), "R48C27")
  5. test.assert_equals(spreadsheet("BK12"), "R12C63")
  6. test.assert_equals(spreadsheet("R12C63"), "BK12")
  7. test.assert_equals(spreadsheet("R85C26"), "Z85")
  8. test.assert_equals(spreadsheet("R31C78"), "BZ31")
  9. test.assert_equals(spreadsheet("BZ31"), "R31C78")
复制代码



游客,如果您要查看本帖隐藏内容请回复

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-5-19 12:39:51 | 显示全部楼层
  1. def spreadsheet(s):
  2.     import re, functools
  3.     c = re.search(r'\D+', s).group()
  4.     r = re.search(r'\d+', s).group()
  5.     c_lst =[ord(i) - 64 for i in c]
  6.     c = functools.reduce(lambda x, y: x * 26 + y, c_lst)
  7.     return 'R' + r + 'C' +  str(c)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2017-5-19 13:10:21 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2017-5-19 13:17 编辑
  1. import re

  2. def spreadsheet(s):
  3.     if re.match('^R(\d{1,5})C(\d{1,5})$, s):
  4.         row, col = re.findall('^R(\d{1,5})C(\d{1,5})$, s)[0]
  5.         col = int(col)
  6.         c = ''
  7.         while col > 0:
  8.             c = chr(col % 26 + 64) + c
  9.             col //= 26
  10.         return c + row

  11.     elif re.match('^([A-Z]{1,10})(\d{1,5})$, s):
  12.         col, row = re.findall('^([A-Z]{1,10})(\d{1,5})$, s)[0]
  13.         c = 0
  14.         while len(col) > 0:
  15.             c = c * 26 + (ord(col[0]) - 64)
  16.             col = col[1:]
  17.         return 'R' + row + 'C' + str(c)

  18.     else:
  19.         return None
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-19 14:07:06 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-19 14:29:02 | 显示全部楼层

两个问题哦!
第一个,4,5,13,14都少一个'。程序是有语法错误的。
第二个:
  1. Success!
  2. Success!
  3. Success!
  4. Success!
  5. Success!
  6. Success!
  7. Fail!A@85 not equals Z85
  8. Fail!C@31 not equals BZ31
  9. Success!
复制代码

结果也是有错误的。"R85C26"第26列,85行,显然应该是Z85
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-19 15:33:21 | 显示全部楼层
本帖最后由 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)[0]
        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('^([A-Z]{1,10})(\d{1,5})$', s):
        col, row = re.findall('^([A-Z]{1,10})(\d{1,5})$', s)[0]
        c = 0
        while len(col) > 1:
            c = c * 26 + (ord(col[0]) - 64)
            col = col[1:]
        c = c * 26 + (ord(col[0]) - 64)
        return 'R' + row + 'C' + str(c)

    else:
        return None

for i in range(1, 100):
    print(spreadsheet('R85C' + str(i)))

我看我原始的程序里是有引号的,不知道为啥粘贴上来就少了。
另外,在转换26倍数的时候由于%的问题好像是有错误,改正了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-19 15:37:07 | 显示全部楼层
ooxx7788 发表于 2017-5-19 14:29
两个问题哦!
第一个,4,5,13,14都少一个'。程序是有语法错误的。
第二个:


好像是code的格式问题,只要把我的程序放code /code之间就会出错。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-19 16:09:21 | 显示全部楼层

重新写了。
  1. def spreadsheet(s):
  2.     import re, functools
  3.     if re.search(r'\dC', s):
  4.         r, c = s.split('C')
  5.         c = int(c)
  6.         column = ''
  7.         while c:
  8.             column = chr(c % 26 + 64) + column
  9.             c //= 26
  10.         return column + r[1:]
  11.     else:
  12.         c = re.search(r'\D+', s).group()
  13.         r = re.search(r'\d+', s).group()
  14.         c_lst =[ord(i) - 64 for i in c]
  15.         c = functools.reduce(lambda x, y: x * 26 + y, c_lst)
  16.         return 'R' + r + 'C' +  str(c)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-19 16:16:06 | 显示全部楼层
另外,写了一种反推的
import re

def spreadsheet(s):
    def trans(ss):
        col, row = re.findall('^([A-Z]{1,10})(\d{1,5})$', ss)[0]
        c = 0
        while len(col) > 1:
            c = c * 26 + (ord(col[0]) - 64)
            col = col[1:]
        c = c * 26 + (ord(col[0]) - 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)[0]
        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('^([A-Z]{1,10})(\d{1,5})$', s):
        return trans(s)
    else:
        return None
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-19 16:21:01 | 显示全部楼层

你的程序和我之前的一样的问题,当column为26的倍数时会出错。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-19 16:38:41 | 显示全部楼层
本帖最后由 冬雪雪冬 于 2017-5-19 16:46 编辑
jerryxjr1220 发表于 2017-5-19 16:21
你的程序和我之前的一样的问题,当column为26的倍数时会出错。


是的,我再想想。新修改的。
  1. def spreadsheet(s):
  2.     import re, functools
  3.     if re.search(r'\dC', s):
  4.         r, c = s.split('C')
  5.         c = int(c)
  6.         column = ''
  7.         while c:
  8.             c -= 1
  9.             column = chr(c % 26 + 65) + column
  10.             c //= 26
  11.         return column + r[1:]
  12.     else:
  13.         c = re.search(r'\D+', s).group()
  14.         r = re.search(r'\d+', s).group()
  15.         c_lst =[ord(i) - 64 for i in c]
  16.         c = functools.reduce(lambda x, y: x * 26 + y, c_lst)
  17.         return 'R' + r + 'C' +  str(c)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-19 17:03:22 | 显示全部楼层
jerryxjr1220 发表于 2017-5-19 16:21
你的程序和我之前的一样的问题,当column为26的倍数时会出错。

你的第一个答案还是有点问题,当s = 'R61574C53328'
第一个答案的结果是CZWB61574
第二个答案的结果是BZWB61574
而实际上,第二个答案是正确答案。
第一个答案条件分支的位置好像还是有点问题,在答案里面有Z的时候,好像会出问题。但是我也没想出来怎么改。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-19 17:16:34 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2017-5-19 17:23 编辑
ooxx7788 发表于 2017-5-19 17:03
你的第一个答案还是有点问题,当s = 'R61574C53328'
第一个答案的结果是CZWB61574
第二个答案的结果是B ...


反推的方法肯定是对的,只不过效率会相对比较低一点。
第一个答案的话,主要是由于%26取模的范围是(0~25),而实际(A~Z)对应的应该是(1~26)。
需要有一个合理的转换程序来匹配。似乎版主修改的方法应该是正确的。
暂时就以第二个答案为准好了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-20 02:49:47 | 显示全部楼层
  1. def spreadsheet(s):
  2.     letter = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
  3.     letter = list(letter)
  4.     s = list(s)
  5.     x = []
  6.     y = []
  7.     if(s[0] == 'R' and s[1].isdigit() and 'C' in s[2:]):
  8.         while 'C' in s:
  9.             y.append(s.pop())
  10.         y.reverse()
  11.         temp = int(''.join(y[1:]))
  12.         while temp:
  13.             x_int  = temp % 26
  14.             temp = temp // 26
  15.             print(x_int)
  16.             if x_int == 0:
  17.                 temp -= 1
  18.             x.append(letter[x_int-1])
  19.             print(x)
  20.             x.reverse()
  21.             x_str = ''.join(x)
  22.         y_str = ''.join(s[1:])
  23.         return(x_str+y_str)
  24.     else:
  25.         num = 0
  26.         y_int = 0
  27.         temp = s.copy()
  28.         for i in range(len(''.join(temp))):
  29.             if not temp[i].isdigit():
  30.                 y.append(temp[i])
  31.                 s.remove(temp[i])
  32.         while y != []:
  33.             temp = y.pop()
  34.             for i in range(26):
  35.                 if letter[i] == temp:
  36.                     y_int += (i+1) * (26 ** num)
  37.                     num += 1
  38.         return('R'+''.join(s)+'C'+str(y_int))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-20 08:42:26 | 显示全部楼层

R14208C2856

Your result is: 'DVE14208' should equal 'DEV14208'
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-20 09:26:44 | 显示全部楼层
ooxx7788 发表于 2017-5-20 08:42
R14208C2856

Your result is: 'DVE14208' should equal 'DEV14208'

有两行缩进错了、、、
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-20 09:27:26 | 显示全部楼层
本帖最后由 当回首遇上转身 于 2017-5-20 09:29 编辑

这就对了
  1. def spreadsheet(s):
  2.     letter = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
  3.     letter = list(letter)
  4.     s = list(s)
  5.     x = []
  6.     y = []
  7.     if(s[0] == 'R' and s[1].isdigit() and 'C' in s[2:]):
  8.         while 'C' in s:
  9.             y.append(s.pop())
  10.         y.reverse()
  11.         temp = int(''.join(y[1:]))
  12.         while temp:
  13.             x_int  = temp % 26
  14.             temp = temp // 26
  15.             if x_int == 0:
  16.                 temp -= 1
  17.             x.append(letter[x_int-1])
  18.         x.reverse()
  19.         x_str = ''.join(x)
  20.         y_str = ''.join(s[1:])
  21.         return(x_str+y_str)
  22.     else:
  23.         num = 0
  24.         y_int = 0
  25.         temp = s.copy()
  26.         for i in range(len(''.join(temp))):
  27.             if not temp[i].isdigit():
  28.                 y.append(temp[i])
  29.                 s.remove(temp[i])
  30.         while y != []:
  31.             temp = y.pop()
  32.             for i in range(26):
  33.                 if letter[i] == temp:
  34.                     y_int += (i+1) * (26 ** num)
  35.                     num += 1
  36.         return('R'+''.join(s)+'C'+str(y_int))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-20 11:30:43 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-20 21:50:14 | 显示全部楼层
  1. A = [1]
  2. def f(x,y):
  3.         return 2*x+y*2
  4. print functools.reduce(f, A)
复制代码

这个返回值为啥是1呢, 是reduce()函数本身有什么机制吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-20 21:55:43 | 显示全部楼层
badaoqingchen 发表于 2017-5-20 21:50
这个返回值为啥是1呢, 是reduce()函数本身有什么机制吗

我的理解,函数f需要2个参数x和y,但A只有一个元素,无法满足要求,所以直接返回A[0]了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-25 04:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表