【问题标题】:Recursive Elimination of Character Groups in a String in PythonPython中字符串中字符组的递归消除
【发布时间】:2021-02-14 02:42:59
【问题描述】:

给定一个包含一系列 Rs 和 Gs 的字符串,寻找一种按组消除它们的方法。如果字符被分组(至少 2 个),您只能消除。

Example 1: RGRRRGGGRR 
  v           v        v
RGRRRGGGRR = RGGGGRR = RRR = {empty}, thus there is a possible solution.

Example 2: GGGRGRGRG
v
GGGRGRGRG = RGRGRG, can no longer find groups, thus there is NO possible solution.

我创建了一个初始递归函数,但即使有可能的解决方案,它也没有解决方案。

def fn(string, start):
    l = len(string)
    if l-start > 0:
        counter, isPop = 0, False               
        if string[start] == 'R':
            while counter + start < l and string[counter + start] == 'R': counter+=1
            if counter > 1:          # If there is the same letter adjacent to the current letter being checked, it will pop this group.
                for i in range(counter):                 
                    string.pop(start)
                    isPop = True                         
            if not isPop and start+counter == l: return False         # Returns false if previous action did not pop and
            else: return fn(string, 0 if isPop else start+counter)    # Letter being checked is the last element (it means
                                                                      # that there are still elements in the string that can
        else:                                                         # no longer be grouped and eliminated.
            while counter + start < l and string[counter + start] == 'G': counter+=1
            if counter > 1:
                for i in range(counter):
                    string.pop(start)
                    isPop = True
            if not isPop and start+counter == len(string): return False
            else: return fn(string, 0 if isPop else start+counter)
        if string: return False
    else: return True
    

ways = []
string = input()
for j in range(len(string)):   # Iterates through every position in the list and calls the fn just to see if it is possible.
    if True in ways:           # If there is a possible solution, it breaks the loop and prints "possible"            
        break
    ways.append(fn(list(string), j))
if True in ways: print("Possible") 
else: print("Impossible")

我的算法不起作用的情况(返回 false 但实际上有办法):

1. GGRRGRRRRGGGGRGRGG
         v                v               v         v         v       v
GGRRGRRRRGGGGRGRGG = GGRRGRRRRRGRGG = GGRRGGRGG = GGRRRGG = GGRRRGG = GGGG = {empty}

2. GRRRGRRRGRRRGRRRGR
         v                     v               v       v          v        v
GRRRGRRRGRRRGRRRGR = GRRRGRRRGGRRRGR = GRRRGRRRGGGR = GRRRGRRRR = GGRRRR = RRRR = {empty}

【问题讨论】:

  • 您更喜欢没有任何导入的解决方案吗?
  • Imports 很好,只是在寻找一个快速的方法。 cdlane 的方法是目前最快的。我认为 ajax 会继续检查所有可能减慢其进程的解决方案,但到目前为止,这两个条目都运行良好。

标签: python string algorithm recursion search


【解决方案1】:

您可以在生成器中使用递归。此外,应用itertools.groupby 预先生成分组会导致更短的解决方案:

from itertools import groupby as gb
def get_groups(s, chain=[]):
   if not s:
      yield chain+[s]
   else:
      r = [list(b) for _, b in gb(s)]
      for i, a in enumerate(r):
        if len(a) > 1:
           t = ''.join(map(''.join, [*r[:i], *([] if i >= len(r) else r[i+1:])]))
           yield from get_groups(t, chain+[s])

cases = ['RGRRRGGGRR', 'GGGRGRGRG', 'GGRRGRRRRGGGGRGRGG', 'GRRRGRRRGRRRGRRRGR']
for case in cases:
   print(f'{case}: {any(get_groups(case))}')

输出:

RGRRRGGGRR: True
GGGRGRGRG: False
GGRRGRRRRGGGGRGRGG: True
GRRRGRRRGRRRGRRRGR: True

get_groups 生成一个空列表[],如果没有可能的路径,通过删除分组将输入完成减少为一个空字符串,并列出所有可能的路径到一个空字符串。

【讨论】:

  • 找到一个解决方案就可以退出吗?
  • @muw 是的,请参阅我最近的编辑。 any 可以用来代替调用bool 和list
  • 工作速度非常快。
【解决方案2】:

我相信您在调试此代码方面的主要问题是您的编码风格。

除了凌乱之外,你还有模棱两可的return情况;您的“R”和“G”平行块不相同;弹出数组后未能更新数组长度变量;您似乎在错误的索引处开始递归。

清理你的代码我能想到的最好的方法是通过以下一个案例,但仍然失败一个:

def fn(characters, start):
    length = len(characters)

    if length - start > 0:
        for character in ['R', 'G']:

            counter = 0
            isPop = False

            if characters[start] == character:
                while start+counter < length and characters[start+counter] == character:
                    counter += 1

                if counter > 1:
                    # If there is the same letter adjacent to the current
                    # letter being checked, it will pop this group.
                    for _ in range(counter):
                        characters.pop(start)
                        isPop = True
                        length -= 1  # we've shortened the array

                if not isPop and start+counter == length:
                    # Returns false if previous action did not pop and
                    # letter being checked is the last element (it means
                    # that there are still elements in characters that can
                    # no longer be grouped and eliminated.
                    return False
            
                return fn(characters, start if isPop else start+counter)

        if characters:
            return False

    return True

就groupby 而言,我自己的解决方案类似于@Ajax1234:

from itertools import groupby

def eliminate_groups(string):
    if not string:  # base case of recursion
        return True

    # "RGRRRGGGRR" -> ['R', 'G', 'RRR', 'GGG', 'RR']
    groups = [''.join(g) for _, g in groupby(string)]

    for index, group in enumerate(groups):
        if len(group) < 2:
            continue

        reduced = groups[:index] + groups[index+1:]  # a deficient copy

        status = eliminate_groups(''.join(reduced))

        if status:  # one of the variants succeeded!
            return status

    return False  # all of the variants failed!

if __name__ == '__main__':

    strings = ["RGRRRGGGRR", "GGGRGRGRG", "GGRRGRRRRGGGGRGRGG", "GRRRGRRRGRRRGRRRGR"]

    for string in strings:
        print(string, eliminate_groups(string))

输出

> python3 test.py
RGRRRGGGRR True
GGGRGRGRG False
GGRRGRRRRGGGGRGRGG True
GRRRGRRRGRRRGRRRGR True
> 

【讨论】:

  • 为我的凌乱工作道歉,我认为我的算法的错误是它只消除了从字符串的左边开始到右边,这错过了一些可能的解决方案,但我并不完全确定。我还不熟悉 groupby。
猜你喜欢
  • 2020-08-12
  • 2013-02-05
  • 2023-04-02
  • 2015-06-25
  • 1970-01-01
  • 1970-01-01
  • 2017-12-20
  • 2012-06-25
  • 1970-01-01
相关资源
最近更新 更多