Search code examples
pythonstringpython-3.xlexicographic

Creating a program that prints true if three words are entered in dictionary order


I am trying to create a program that asks the user for three words and prints 'True' if the words are entered in dictionary order. E.G:

Enter first word: chicken

Enter second word: fish

Enter third word: zebra

True

Here is my code so far:

first = (input('Enter first word: '))
second = (input('Enter second word: '))
third = (input('Enter third word: '))
s = ['a','b','c','d','e','f','g','h',
     'i','j','k','l','m','n','o','p',
     'q','r','s','t','u','v','w','x',
     'y','z','A','B','C','D','E','F',
     'G','H','I','J','K','L','M','N',
     'O','P','Q','R','S','T','U','V',
     'W','Z','Y','Z']
if s.find(first[0]) > s.find(second[0]) and s.find(second[0]) >                                  s.find(third[0]):
    print(True)

Solution

  • If you work on a list of arbitrary length, I believe using sorted() as other answers indicate is good for small lists (with small strings) , when it comes to larger lists and larger strings and cases (and cases where the list can be randomly ordered), a faster way would be to use all() built-in function and a generator expression (This should be faster than the sorted() approach). Example -

    #Assuming list is called lst
    print(all(lst[i].lower() < lst[i+1].lower() for i in range(len(lst)-1)))
    

    Please note, above would end up calling str.lower() on every string (except for first and last) twice. Unless your strings are very large, this should be fine.

    If your strings are really very large compared to the length of the list, you can create another temporary list before doing the all() that stores all the strings in lowercase. And then run same logic on that list.

    You can create your list (by taking inputs from the user) using a list comprehension, Example -

    lst = [input("Enter word {}:".format(i)) for i in range(3)] #Change 3 to the number of elements you want to take input from user.
    

    Timing results of the above method vs sorted() (modified code of sorted() to work case-insensitively) -

    In [5]: lst = ['{:0>7}'.format(i) for i in range(1000000)]
    
    In [6]: lst == sorted(lst,key=str.lower)
    Out[6]: True
    
    In [7]: %timeit lst == sorted(lst,key=str.lower)
    1 loops, best of 3: 204 ms per loop
    
    In [8]: %timeit all(lst[i].lower() < lst[i+1].lower() for i in range(len(lst)-1))
    1 loops, best of 3: 439 ms per loop
    
    In [11]: lst = ['{:0>7}'.format(random.randint(1,10000)) for i in range(1000000)]
    
    In [12]: %timeit lst == sorted(lst,key=str.lower)
    1 loops, best of 3: 1.08 s per loop
    
    In [13]: %timeit all(lst[i].lower() < lst[i+1].lower() for i in range(len(lst)-1))
    The slowest run took 6.20 times longer than the fastest. This could mean that an intermediate result is being cached
    100000 loops, best of 3: 2.89 µs per loop
    

    Result -

    For cases that should return True (that is already sorted lists) the using sorted() is quite faster than all() , since sorted() works well for mostly-sorted lists.

    For cases that are random, all() works better than sorted() because of the short-circuiting nature of the all() (it would short-circuit when it sees the first False ).

    Also, there is the fact that sorted() would create a temporary (sorted list) in memory (for comparison), whereas all() would not require that (and this fact does attribute to the timings we see above).


    Earlier answer that directly (and only applies to this question) you can simply directly compare the strings as such, you do not need another string/list for alphabets. Example -

    first = (input('Enter first word: '))
    second = (input('Enter second word: '))
    third = (input('Enter third word: '))
    if first <= second <= third:
        print(True)
    

    Or if you want to compare only the first characters (though I highly doubt that) -

    if first[0] <= second[0] <= third[0]:
        print(True)
    

    To compare the strings case-insensitively, you can convert all the string to lowercase, before comparison. Example -

    if first.lower() <= second.lower() <= third.lower():
        print(True)
    

    Or the simpler -

    print(first.lower() <= second.lower() <= third.lower())