Average of two strings in alphabetical/lexicographical order

前端 未结 8 1776
南方客
南方客 2021-02-15 17:38

Suppose you take the strings \'a\' and \'z\' and list all the strings that come between them in alphabetical order: [\'a\',\'b\',\'c\' ... \'x\',\'y\',\'z\']. Take the midpoint

相关标签:
8条回答
  • 2021-02-15 18:36

    I haven't programmed in python in a while and this seemed interesting enough to try. Bear with my recursive programming. Too many functional languages look like python.

    def stravg_half(a, ln):
         # If you have a problem it will probably be in here.
         # The floor of the character's value is 0, but you may want something different
         f = 0
         #f = ord('a')
         L = ln - 1
         if 0 == L:
              return ''
         A = ord(a[0])
         return chr(A/2) + stravg_half( a[1:], L)
    
    def stravg_helper(a, b, ln, x):
        L = ln - 1
        A = ord(a[0])
        B = ord(b[0])
        D = (A + B)/2
        if 0 == L:
            if 0 == x:
                 return chr(D)
            # NOTE: The caller of helper makes sure that len(a)>=len(b)
            return chr(D) + stravg_half(a[1:], x)
        return chr(D) + stravg_helper(a[1:], b[1:], L, x)
    
    def stravg(a, b):
        la = len(a)
        lb = len(b)
        if 0 == la:
            if 0 == lb:
                return a # which is empty
            return stravg_half(b, lb)
        if 0 == lb:
            return stravg_half(a, la)
        x = la - lb
        if x > 0:
            return stravg_helper(a, b, lb, x)
        return stravg_helper(b, a, la, -x) # Note the order of the args
    
    0 讨论(0)
  • 2021-02-15 18:39

    This version thinks 'abc' is a fraction like 0.abc. In this approach space is zero and a valid input/output.

    MAX_ITER = 10
    letters = " abcdefghijklmnopqrstuvwxyz"
    def to_double(name):
        d = 0
        for i, ch in enumerate(name):
            idx = letters.index(ch)
            d += idx * len(letters) ** (-i - 1)
        return d
    
    def from_double(d):
        name = ""
        for i in range(MAX_ITER):
            d *= len(letters)
            name += letters[int(d)]
            d -= int(d)
        return name
    
    def avg(w1, w2):
        w1 = to_double(w1)
        w2 = to_double(w2)
        return from_double((w1 + w2) * 0.5)
    
    print avg('a', 'a') # 'a'
    print avg('a', 'aa') # 'a mmmmmmmm'
    print avg('aa', 'aa') # 'a zzzzzzzz'
    print avg('car', 'duck') # 'cxxemmmmmm'
    

    Unfortunately, the naïve algorithm is not able to detect the periodic 'z's, this would be something like 0.99999 in decimal; therefore 'a zzzzzzzz' is actually 'aa' (the space before the 'z' periodicity must be increased by one.

    In order to normalise this, you can use the following function

    def remove_z_period(name):
        if len(name) != MAX_ITER:
            return name
        if name[-1] != 'z':
            return name
        n = ""
        overflow = True
        for ch in reversed(name):
            if overflow:
                if ch == 'z':
                    ch = ' '
                else:
                    ch=letters[(letters.index(ch)+1)]
                    overflow = False
            n = ch + n
        return n
    
    print remove_z_period('a zzzzzzzz') # 'aa'
    
    0 讨论(0)
提交回复
热议问题