简体   繁体   中英

How do I use python recursion in this scenario?

"Write a recursive function called anagram(s) that returns a list of all the possible anagrams of the string, s." Can I get some guidance on how to tackle this question? I am new to recursion and do not understand how to make a simpler base case for this scenario. Or what my general algorithm would be.

I linked a duplicate question in comments above which contains an implementation of this, but since this is clearly a homework-like task I'd encourage you to use it as a last resort.

Your end goal is a list of all possible combinations of the letters in a given string.

When looking for a recursive approach, you want to be thinking about "how can I break this task down into doing the same thing over and over again, against increasingly simple versions of the input."

So instead of trying to anagram the full string ABCD, start out by just anagramming the first letter: you'll have one set of results that starts with "A" (and has all the combinations of "BCD" after it), one that starts with "B" (and is followed by all the combinations of "ACD"), and so on for C and D.

So that's the first layer of your recursion; pluck each letter out one by one as the first character and recurse with the remainder of the string.

The first instance of the next layer only has to deal with a three character string "BCD" -- you know all of these will start with "A", and you'll need to recurse for "B", "C", and "D" as the second letter, with the remaining letters left to be shuffled.

One layer deeper, you're starting with (for example) "AB", and need to recurse against both the possible orderings of "CD".

The bottom layer of the recursion will be when there's only a single letter left so there's nothing left to shuffle; at that point you can just append it to the preceding characters and return the result to be added to your list of anagrams.

Your recursive function would take two parameters: the first one is "the letters I've already shuffled" and the second one is "the letters I have yet to shuffle".

combinatorics

We can write permutations(t) using inductive reasoning -

  1. if the input t is empty, yield the empty result
  2. (inductive) t has at least one element. for all p of the subproblem t[1:] , for all r of the first element t[0] rotated through p , yield r
def permutations(t):
  if not t:
    yield ()                          #1
  else:
    for p in permutations(t[1:]):     #2
      for r in rotations(p, t[0]):
        yield r

By rotations((a,b,c), X) we mean X will "rotate" through each position in (a, b, c) -

(X, a, b, c)
(a, X, b, c)
(a, b, X, c)
(a, b, c, X)

Where rotations(t,e) is defined as -

  1. if the input t is empty, yield the empty rotation, (e)
  2. (inductive) t has at least one element. yield (e, *t) and for all r of the subproblem t[1:] , prepend the first element t[0] to r and yield
def rotations(t, e):
  if not t:
    yield (e)                       # 1
  else:
    yield (e, *t)                   # 2
    for r in rotations(t[1:], e):
      yield (t[0], *r)
for p in permutations("same"):
  print(p)
('s', 'a', 'm', 'e')
('a', 's', 'm', 'e')
('a', 'm', 's', 'e')
('a', 'm', 'e', 's')
('s', 'm', 'a', 'e')
('m', 's', 'a', 'e')
('m', 'a', 's', 'e')
('m', 'a', 'e', 's')
('s', 'm', 'e', 'a')
('m', 's', 'e', 'a')
('m', 'e', 's', 'a')
('m', 'e', 'a', 's')
('s', 'a', 'e', 'm')
('a', 's', 'e', 'm')
('a', 'e', 's', 'm')
('a', 'e', 'm', 's')
('s', 'e', 'a', 'm')
('e', 's', 'a', 'm')
('e', 'a', 's', 'm')
('e', 'a', 'm', 's')
('s', 'e', 'm', 'a')
('e', 's', 'm', 'a')
('e', 'm', 's', 'a')
('e', 'm', 'a', 's')

anagrams

Now anagrams can be a simple join on the resulting permutations -

def anagrams(s):
  for p in permutations(s):
    yield "".join(p)
for a in anagrams("same"):
  print(a)
same
asme
amse
ames
smae
msae
mase
maes
smea
msea
mesa
meas
saem
asem
aesm
aems
seam
esam
easm
eams
sema
esma
emsa
emas

valid words

If you wish to find only valid words, you will need a dictionary and add a condition before the yield statement -

def anagrams(s, dictionary):
  for p in permutations(s):
    word = "".join(p)
    if word in dictionary:
      yield word
mydict = {"valid", "words", "go", "here", ..., }

for a in anagrams("same"):
  print(a)
same
maes
mesa
seam

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM