1

How can I find all the strings in "python" which are lexicographically greater than X and smaller than Y? X and Y are of same length.

Example:

X = "ab" and Y = "ad"

So the answer will be:

"ab", "ac" and "ad"

How can I do this?

sqluser
  • 5,502
  • 7
  • 36
  • 50
bazinga
  • 2,120
  • 4
  • 21
  • 35

4 Answers4

0

Some pseudocode you can start from:

lower=...
upper=...
str = next(lower)
while before(str, upper) :
    print(str)
    str = next(str)

The next function:

def next (str) :
    if str[-1] != 'z' :
        return str[:-1] + chr(ord(str[-1]) + 1) # increment last char
    else:
        return next( str[0:-1] ) + 'a' # reset last char and increment previous

The before function:

def before (a, b) :
   for i in 0.. (len(a)-1) :
       if a[i] < b[i] :
           return True
   return False
lodo
  • 2,314
  • 19
  • 31
  • I guess your `next` function is wrong. I would do `return str[:-1] + chr(ord(str[-1]) + 1)` in the first case and `return next(str[:-1]) + 'a'` in the second case. – Tigran Saluev Mar 29 '15 at 10:30
0

I think the answer you are looking for is:

X = 'ab'
Y = 'ad'

x = [chr(x) + chr(y) for x in range(ord(X[0]),ord(Y[0])+1) for y in range(ord(X[1]),ord(Y[1])+1)]

print(x)
lazarus
  • 677
  • 1
  • 13
  • 27
0

You can view this as converting from base 26 to get a range of integers, then convert those integers back into base 26. You can either roll your own for that, or pip install python-baseconv, eg:

from string import ascii_lowercase
from baseconv import BaseConverter

def lex_range(start, end):
    if len(start) != len(end):
        raise ValueError('inputs must be same length')
    B26 = BaseConverter(ascii_lowercase)
    # use `xrange` in Py 2.x
    for n in range(int(B26.decode(start)), int(B26.decode(end)) + 1):
        yield B26.encode(n).rjust(len(start), 'a')

for result in lex_range('ab', 'ad'):
    print(result)

Note - the above will work as long as they're lexicographically start <= end - they don't need to be the same length, so lex_range('a', 'zz') would still produce the desired output - hence the explicit len check.

Output:

# ab
# ac
# ad
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
0

First, let's write a function to find the lexicographically next string after the current (with the same length, and only using the characters a-z), I.e., to increment it. In most cases, that's easy – just increment the last character. However, if the last character is the highest possible character in our set (z), we start over with a, and increment the remaining string.

def next(s):
    front = s[:-1]
    last = s[-1]
    if last < 'z':
        return front + chr(ord(last) + 1)
    else:
        return next(front) + 'a'

Now we can use that to print all strings in the given range:

def print_between(start, end):
    s = start
    while s <= end:
        print (s)
        s = next(s)

Example:

print_between('ab', 'ad')
oefe
  • 19,298
  • 7
  • 47
  • 66