Here's my attempt. It's a very "off the cuff" approach; I'm not familiar with any advanced mathematical concepts related to prime numbers... but I've been exposed to them now, thanks to this challenge!

I've outlined my thought process in my comments, to the best of my ability on a late night, at least!

Admittedly, my code is a bit bloated for the challenge. And there are probably some blocks that would be better-served as functions. Nonetheless, it has worked with a good quantity of random test numbers.

I structured it as a loop, so that a user can repeatedly enter numbers, until '0' is entered, without having to rerun the script.

I had to learn basic Python for this; it was a fun experience. I'm happy to have any positive or constructive feedback.

Thanks for looking!

Use it on repl.it

(I'm new to this system, and I couldn't figure out how to embed the repl.it like the user above. Adding the embed script did nothing. A pro-tip on that would be great!)

```
# ***THOUGHTS***
# The approach used in this solution admittedly causes iterations with factors that are not prime.
# I should go back sometime and see if there is a performance gain or loss by checking whether a factor is prime before attempting the modulus operation.
# My "sniff test" result is that it would (slightly) decrease performance in checking if the factor is a prime number, because multiple operations would be performed for each candidate factor before performing the modulus check.
# As written, all potential odd factors are checked. But they are only processed once if they are not a prime factor of the input number.
#
# There are some chunks of code that would be better served as functions... perhaps for v2!
#
# I'm sure there are some inconsistencies or deviations from Python conventions. Please forgive them; this is my first attempt at Python.
#
# TODO: Add a try block to check for an integer input
# Will need square root & floor functions
import math
HEADER_PRIME = "PRIME FACTORS"
HEADER_UNIQUE_PRIME = "UNIQUE PRIME FACTORS"
HEADER_BOTH = "PRIME & UNIQUE PRIME FACTORS"
def displayFactors(header, factors_array, sum_of_factors):
print("\n{}\n{}\nSum = {}\n".format(header, factors_array, sum_of_factors))
# Place all logic in an outer loop,
# in order to continue entering numbers
# without having to run the script each time.
# This loop will continue until 0 is entered.
while True:
# Allow the user to enter a number to be factored
number = int(input("Enter a number (0 = Exit)\n>"))
# Exit the script if 0 was entered
if number == 0:
print("Exiting...")
break
# Display a special message if 1-3 was entered,
# because these numbers are prime numbers,
# and it is mathematically impossible for them to have another prime factor > 1
elif number <= 3:
print("{} is a prime number\n".format(number))
displayFactors(HEADER_BOTH, [number], number)
continue
# The largest possible factor for any number is the square root of that number.
# Since we're only considering prime integers, the factor should be floored.
max_factor = math.floor(math.sqrt(number))
print("Square root of {} is {}".format(number, math.sqrt(number)))
# By definition, an even number larger than 2 cannot be a prime factor.
# If the resulting max_factor value is even, subtract 1 from max_factor.
# The exception to this is a max_factor of 2, so it must also be checked as a condition
#
# max_factor will then represents the largest potential prime factor.
if (max_factor % 2) == 0 and max_factor != 2:
print("By definition, an even number higher than 2 cannot be a prime factor.")
max_factor -= 1
print("Therefore, the largest integer factor required for iteration is {}".format(max_factor))
# Stop the console to view summary information before iterating over factors
stop = input("[Press ENTER to continue...]")
# Initialize or reset a list in which identified prime factors can be placed,
# for summary output after iterations are complete
prime_factors = []
# Helper function to iterate through each factor
def checkFactor(dividend, divisor):
while (dividend % divisor) == 0:
prime_factors.append(divisor)
print("{} / {} = {}".format(
dividend, divisor, dividend / divisor))
dividend = dividend / divisor
return dividend
print("\nSHOWING WORK...")
# Set the initial factor to the smallest possible prime factor,
# (excluding 1, because it has already been accounted for)
factor = 2
print("\nFactor is", factor)
# 2 is a special case -- the only even prime number,
# so it must be checked before entering the main loop.
number = checkFactor(number, factor)
# Update factor to the next prime factor (3),
# unless max_factor <= 2
# After this, it will increment within the while loop
if max_factor > 2:
factor = 3
print("\nFactor updated to {}".format(factor))
# The loop must continue until the value of 'number' has been reduced to 1
# or the factor is > max_factor
while number > 1:
# If the number is evenly divisible by the current factor,
# then it is a prime factor and should be added to the prime_factors list.
# This check should repeated until the number is no longer divisible by the current factor.
while (number % factor) == 0:
number = checkFactor(number, factor)
# If the current factor is greater than the max_factor,
# then either all prime factors have been identified in the loop
# or the final prime factor is the indivisible number value
#
# Check to see if the factor still needs to be updated
if factor < max_factor:
# This is checked by the while loop,
# but placing a check here allows for informational messages.
#
# Not needed for core functionality
if number == 1:
print("ALL FACTORS FOUND. Exiting loop...\n")
break
# Since 2 has already been checked,
# and the factor value is at least 3 at this point,
# every potential prime factor will be an odd number.
#
# Add 2 to increment to next odd factor.
factor += 2
print("\nFactor updated to {}".format(int(factor)))
else:
print("MAX FACTOR REACHED. Exiting loop...\n")
break
#end while (number % factor) == 0
# If the number is > 1 after exiting the loop,
# then the remaining value of the number must be the final prime factor.
# It should be appended to the prime_factors list
if number > 1:
prime_factors.append(int(number))
print("{} is a prime number".format(prime_factors[-1]))
# TASK 1: Sum all prime factors
# Initialize or reset a variable to hold the sum of the prime factors
sum_of_prime_factors = 0;
# Iterate over the prime_factors list to obtain the sum
for i in range(0, len(prime_factors)):
sum_of_prime_factors += prime_factors[i]
# Display the list of prime factors & their sum
if len(prime_factors) > 1:
displayFactors(HEADER_PRIME, prime_factors, sum_of_prime_factors)
else:
displayFactors(HEADER_BOTH, prime_factors, sum_of_prime_factors)
continue
# TASK 2: Sum all unique prime factors
# Initialize or reset a list to hold the sum of the unique prime factors
unique_prime_factors = []
# It's safe to seed the first value of the unique factors list
# because there will always be at least one prime factor
unique_prime_factors.append(prime_factors[0])
# Initialize or reset a variable to hold the sum of the unique prime factors
sum_of_unique_prime_factors = 0
for i in range(0, len(prime_factors)):
if prime_factors[i] != unique_prime_factors[-1]:
unique_prime_factors.append(prime_factors[i])
for i in range(0, len(unique_prime_factors)):
sum_of_unique_prime_factors += unique_prime_factors[i]
# Display the unique prime factors & their sum
displayFactors(HEADER_UNIQUE_PRIME, unique_prime_factors, sum_of_unique_prime_factors)
```