# Activity Selection Problem  
def activity_selection(start, finish):
    n = len(start)
    
    activities = sorted(zip(start, finish, range(1, n + 1)), key=lambda x: x[1])

    print("\nSorted activities by finish time (Activity, Start, Finish):")
    for activity in activities:
        print(f"A{activity[2]}: Start: {activity[0]}, Finish: {activity[1]}")

    selected_activities = []
    last_finish_time = -1

    print("\nActivity Selection Process:")

    for activity in activities:
        if activity[0] >= last_finish_time:
            selected_activities.append(activity)
            last_finish_time = activity[1]
            print(f"Selected activity: A{activity[2]}: Start: {activity[0]}, Finish: {activity[1]}")

    print("\nFinal selected activities:")
    for activity in selected_activities:
        print(f"A{activity[2]}: Start: {activity[0]}, Finish: {activity[1]}")
    print(f"\nTotal number of activities that can be selected: {len(selected_activities)}")

def get_user_input():
    start_times = list(map(int, input("Enter space-separated start times: ").split()))
    finish_times = list(map(int, input("Enter space-separated finish times: ").split()))
    return start_times, finish_times

def main():
    start_times, finish_times = get_user_input()
    activity_selection(start_times, finish_times)

if __name__ == "__main__":
    main()





# Huffman Coding
import heapq
from collections import defaultdict

def build_frequency_dict(text):
    freq = defaultdict(int)
    for char in text:
        freq[char] += 1
    return freq

def build_huffman_tree(freq):
    heap = [[weight, [char, ""]] for char, weight in freq.items()]
    heapq.heapify(heap)

    while len(heap) > 1:
        lo = heapq.heappop(heap)
        hi = heapq.heappop(heap)

        for pair in lo[1:]:
            pair[1] = '0' + pair[1] 
        for pair in hi[1:]:
            pair[1] = '1' + pair[1] 

        heapq.heappush(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:])

    return heap[0]

def huffman_codes(tree):
    return {char: code for char, code in tree[1:]}


def encode(text, codes):
    return ''.join(codes[char] for char in text)


def decode(encoded_text, codes):
    reversed_codes = {v: k for k, v in codes.items()}
    current_code = ""
    decoded_text = ""

    for bit in encoded_text:
        current_code += bit
        if current_code in reversed_codes:
            decoded_text += reversed_codes[current_code]
            current_code = ""
    return decoded_text


def calculate_space_saved(text, encoded_text, freq_dict, codes):
    original_size = len(text) * 8

    encoded_size = sum(len(codes[char]) * freq_dict[char] for char in freq_dict)

    space_saved = original_size - encoded_size
    space_saved_percentage = (space_saved / original_size) * 100

    return original_size, encoded_size, space_saved, space_saved_percentage

def huffman_coding(text):
    freq_dict = build_frequency_dict(text)
    huffman_tree = build_huffman_tree(freq_dict)
    codes = huffman_codes(huffman_tree)
    
    encoded_text = encode(text, codes)
    decoded_text = decode(encoded_text, codes)
    original_size, encoded_size, space_saved, space_saved_percentage = calculate_space_saved(
        text, encoded_text, freq_dict, codes
    )

    print("\n--- Frequency Dictionary ---")
    for char, freq in freq_dict.items():
        print(f"Character: '{char}' | Frequency: {freq}")

    print("\n--- Huffman Codes ---")
    for char, code in codes.items():
        print(f"Character: '{char}' | Huffman Code: {code}")

    print("\n--- Encoded Text ---")
    print(encoded_text)
    print("\n--- Decoded Text ---")
    print(decoded_text)

    print("\n--- Space Comparison ---")
    print(f"Original size: {original_size} bits")
    print(f"Encoded size: {encoded_size} bits")
    print(f"Space saved: {space_saved} bits")
    print(f"Space saved percentage: {space_saved_percentage:.2f}%")


if __name__ == "__main__":
    input_text = input("Enter the string to encode: ")
    print()
    huffman_coding(input_text)
