solution_330.py

#!/usr/bin/python3
# ==============================================================
# compare 2 lists of random integers
# ==============================================================

import random
import sys

VERBOSE = False

# --------------------------------------------------------------
# ---- compare list A and B using loops, logic, and indexes
# --------------------------------------------------------------
# ----
# ---- Algorithm: compare lists A and B (one element at a time)
# ----
# ---- sort list A and B
# ----
# ---- loop:
# ----
# ----   if end of list A and B:
# ----      break
# ----
# ----   if end of list A:
# ----      mark the remaining elements on list B as not-in-a
# ----      break
# ----
# ----   if end of list B:
# ----      mark the remaining elements on list A as not-in-b
# ----      break
# ----
# ----   if the current elements in list A and B match
# ----      mark the current elements as in-both-a-and-b
# ----      get the next elements from each list
# ----      continue
# ----
# ----   if element in list A less that element in list B
# ----      mark the current A element as not-in-b
# ----      get next element from list A
# ----      continue
# ----
# ----   if element in list B less that element in list A
# ----      mark the current B element as not-in-a
# ----      get next element from list B
# ----      continue
# ----
# ---- Note: Instead of marking elements, copy then to
# ----       unique lists?
# ----
# --------------------------------------------------------------

def compare_lists(a,b):

    in_both    = []             # in both A and B lists
    in_a_not_b = []             # in A but not B list
    in_b_not_a = []             # in B but not A list
    a_idx      = 0              # list A index
    b_idx      = 0              # list B index
    a_len      = len(a)         # list A length
    b_len      = len(b)         # list B length

    while True:

        # ---- end of both lists (A and B)

        if a_idx >= a_len and b_idx >= b_len:
            break

        # ---- end of A list
        # ---- append remaining B list elements to
        # ----    "in_b_not_a" list

        if a_idx >= a_len:
            if VERBOSE:
                print('end of list A')
            while b_idx < b_len:
                in_b_not_a.append(b[b_idx])
                b_idx += 1
            break

        # ---- end of B list
        # ---- append remaining A list elements to
        # ----    "in_a_not_b" list

        if b_idx >= b_len:
            if VERBOSE:
                print('end of list B')
            while a_idx < a_len:
                in_a_not_b.append(a[a_idx])
                a_idx += 1
            break

        # ---- compare an element from each list (A and B)

        if VERBOSE:
            print('compare an element from each list')

        if a[a_idx] == b[b_idx]:
            in_both.append(a[a_idx])
            a_idx += 1
            b_idx += 1
            continue
        elif a[a_idx] < b[b_idx]:
            in_a_not_b.append(a[a_idx])
            a_idx += 1
            continue
        elif a[a_idx] > b[b_idx]:
            in_b_not_a.append(b[b_idx])
            b_idx += 1
            continue

        # ---- oops! how did we get here?

        print()
        print('OOPS! How did we get here?')
        print()
        print(f'a_len = {a_len:3}  b_len = {b_len:3}')
        print(f'a_idx = {a_idx:3}  b_idx = {b_idx:3}')
        print()
        print(f'in_a_not_b = {in_a_not_b}')
        print()
        print(f'in_b_not_a = {in_b_not_a}')
        print()
        print(f'in_both    = {in_both}')
        print()
        print('exit program')
        print()
        sys.exit()

    return(in_both, in_a_not_b, in_b_not_a)

# --------------------------------------------------------------
# ---- compare list A and B using Python sets
# --------------------------------------------------------------

def compare_lists_using_sets(set_a,set_b):

    in_both    = []             # in both A and B lists
    in_a_not_b = []             # in A but not B list
    in_b_not_a = []             # in B but not A list
    
    in_both    = sorted(list(set_a & set_b))
    in_a_not_b = sorted(list(set_a - set_b))
    in_b_not_a = sorted(list(set_b - set_a))

    return(in_both, in_a_not_b, in_b_not_a)

# --------------------------------------------------------------
# ---- display comparison results
# --------------------------------------------------------------

def display_comparison_results(ab_both, a_only, b_only,
                               title=None):

    # ---- display title?

    if title is not None:
        print()
        print('='*25)
        print(title)
        print('='*25)

    # ---- display in A only list

    print()
    print('in A list only')
    print('--------------')
    l = len(a_only)
    if l > 0:
        for i in range(l):
            print(f'{a_only[i]}')
    else:
        print('none')

    # ---- display in B only list

    print()
    print('in B list only')
    print('--------------')
    l = len(b_only)
    if l > 0:
        for i in range(l):
            print(f'{b_only[i]}')
    else:
        print('none')

    # ---- display in both lists

    print()
    print('in both lists')
    print('--------------')
    l = len(ab_both)
    if l > 0:
        for i in range(l):
            print(f'{ab_both[i]}')
    else:
        print('none')

# --------------------------------------------------------------
# ---- display lists A and B (side-by-side)
# --------------------------------------------------------------

def display_lists(a, b, title=None):

    print()
    if title is not None: print(title)
    print('Idx  A List  B List')
    print('---  ------  ------')

    a_len   = len(a)
    b_len   = len(b)
    idx_max = max(a_len,b_len)

    for idx in range(idx_max):

        if idx < a_len:
            a_str = f'{a[idx]:<6}'
        else:
            a_str = ' '*6

        if idx < b_len:
            b_str = f'{b[idx]:<6}'
        else:
            b_str = ' '*6

        print(f'{idx:<3}  {a_str}  {b_str}')

    return

# --------------------------------------------------------------
# ---- create random list of positive integers
# --------------------------------------------------------------

def create_random_integer_list(lst_len,
                               seed_value=None,
                               min_int=1,
                               max_int=10):

    lst = []

    if seed_value is not None: random.seed(seed_value)

    for _ in range(lst_len):
        lst.append(random.randint(min_int,max_int))

    lst.sort()

    return lst

# --------------------------------------------------------------
# ---- main
# --------------------------------------------------------------

if __name__ == '__main__':

    # ---- create lists random positive integers (sorted)

    list1 = create_random_integer_list(11, 123456)
    list2 = create_random_integer_list(16, 654321)

    display_lists(list1, list2, '----Test Lists-----')

    # ---- compare lists using loops, logic, and indexes

    ab_both, a_only, b_only = compare_lists(list1,list2)

    display_comparison_results(ab_both, a_only, b_only)

    # ---- compare lists using Python sets

    ab_both, a_only, b_only = compare_lists_using_sets(
        set(list1),set(list2))

    display_comparison_results(ab_both, a_only, b_only,
                               'Using Python Sets')