ooxx7788 发表于 2017-5-19 11:08:02

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 *****

冬雪雪冬 发表于 2017-5-19 12:39:51

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:10:21

本帖最后由 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

ooxx7788 发表于 2017-5-19 14:07:06

冬雪雪冬 发表于 2017-5-19 12:39


相互转换!

ooxx7788 发表于 2017-5-19 14:29:02

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: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)
      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倍数的时候由于%的问题好像是有错误,改正了。

jerryxjr1220 发表于 2017-5-19 15:37:07

ooxx7788 发表于 2017-5-19 14:29
两个问题哦!
第一个,4,5,13,14都少一个'。程序是有语法错误的。
第二个:


好像是code的格式问题,只要把我的程序放code /code之间就会出错。

冬雪雪冬 发表于 2017-5-19 16:09:21

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)

jerryxjr1220 发表于 2017-5-19 16:16:06

另外,写了一种反推的
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

jerryxjr1220 发表于 2017-5-19 16:21:01

冬雪雪冬 发表于 2017-5-19 16:09
重新写了。

你的程序和我之前的一样的问题,当column为26的倍数时会出错。

冬雪雪冬 发表于 2017-5-19 16:38:41

本帖最后由 冬雪雪冬 于 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)

ooxx7788 发表于 2017-5-19 17:03:22

jerryxjr1220 发表于 2017-5-19 16:21
你的程序和我之前的一样的问题,当column为26的倍数时会出错。

你的第一个答案还是有点问题,当s = 'R61574C53328'
第一个答案的结果是CZWB61574
第二个答案的结果是BZWB61574
而实际上,第二个答案是正确答案。
第一个答案条件分支的位置好像还是有点问题,在答案里面有Z的时候,好像会出问题。但是我也没想出来怎么改。

jerryxjr1220 发表于 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)。
需要有一个合理的转换程序来匹配。似乎版主修改的方法应该是正确的。
暂时就以第二个答案为准好了。

当回首遇上转身 发表于 2017-5-20 02:49:47

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))

ooxx7788 发表于 2017-5-20 08:42:26

当回首遇上转身 发表于 2017-5-20 02:49


R14208C2856

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

当回首遇上转身 发表于 2017-5-20 09:26:44

ooxx7788 发表于 2017-5-20 08:42
R14208C2856

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

有两行缩进错了、、、

当回首遇上转身 发表于 2017-5-20 09:27:26

本帖最后由 当回首遇上转身 于 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))

ooxx7788 发表于 2017-5-20 11:30:43

当回首遇上转身 发表于 2017-5-20 09:27
这就对了

确实OK了

badaoqingchen 发表于 2017-5-20 21:50:14

冬雪雪冬 发表于 2017-5-19 12:39


A =
def f(x,y):
        return 2*x+y*2
print functools.reduce(f, A)
这个返回值为啥是1呢, 是reduce()函数本身有什么机制吗

冬雪雪冬 发表于 2017-5-20 21:55:43

badaoqingchen 发表于 2017-5-20 21:50
这个返回值为啥是1呢, 是reduce()函数本身有什么机制吗

我的理解,函数f需要2个参数x和y,但A只有一个元素,无法满足要求,所以直接返回A了
页: [1] 2 3
查看完整版本: Python:每日一题 49