code: def oridam_generate_patterns(word_in,cm,ed=1,level=0,pos=0,candidates=None):
      
      alternates = cm.get(word_in[pos],[])
      if not candidates:
          candidates = []
      assert ed <= len(word_in), 'edit distance has to be comparable to word size [ins/del not explored]'
      if (pos >len(word_in)) or ed == 0:
          return candidates
      pfx = ''
      sfx = ''
      curr_candidates = []
      for p in range(0,pos):
          pfx = pfx + word_in[p]
      for p in range(pos+1,len(word_in)):
          sfx = sfx + word_in[p]
      for alt in alternates:
          word_alt = pfx + alt + sfx
          if not (word_alt in candidates):
              candidates.append( word_alt )
              curr_candidates.append( word_alt )
      for n_pos in range(pos,len(word_in)):
          # already what we have ' candidates ' of this round are edit-distance 1
          for word in curr_candidates:
              oridam_generate_patterns(word,cm,ed-1,level+1,n_pos,candidates)
      if level == 0:
          #candidates.append(word_in)
          for n_pos in range(pos,len(word_in)):
              oridam_generate_patterns(word_in,cm,ed, level+1,n_pos,candidates)
      return candidates
docs: ed = 1 by default, pos - internal variable for algorithm