Count numbers with atleast one common factor, excluding one (updated) Below is an updated version of  the question I asked prior:

Count numbers with atleast one common factor, excluding one 

I have been trying to teach myself some python 3 by working through problems at geeksforgeeks.org. A common issue I am having is that my code runs on my machine, and in their test environment, but my code ultimately exceeds their time limits upon submission. I was wondering if anyone had any general advice on making my code more efficient so I could continue to make use of the practice problems. 

As for my update, I have tried:

(1) Utilizing list comprehension in python. While cleaner, I don't think this made any dramatic improvements for me. 
(2) I only populate the list of possibilities once now as per the suggestion of Gareth Rees. I originally knew this was inefficient, but I thought this was bad form since it makes my code less flexible for the most general case. I realize now that the constraints should be used in a way to make the code faster for these types of time-limited problems.
(3) I have traded a while loop for a for loop since I read this was faster. 

That said, I am still no where near the time limits they are imposing in the problem. Some thoughts I had:

(1) My guess is the main culprit is the nested for loop inside a for loop which is likely very time consuming, but I don't know how to get around using nested for loops in this. 

(2) Also, I am wondering if Python is even suitable for severely time limited challenges of this sort? I have read that Python is generally slower than C++ and from what I can tell very few people use Python on time-limited sites like this. 

The problem I have been working on is:

http://practice.geeksforgeeks.org/problems/mathematical-manipulation/0


  Given a number \$N\$, find the total numbers, less than or equal to \$N\$ which have at-least one common factor with \$N\$ other than \$1\$.
  
  Input:
  The first line of input contains an integer \$T\$ denoting the no of test cases. Then \$T\$ test cases follow. Each test case consist of an integer \$N\$.
  
  Output:
  For each test case output an integer denoting the count of numbers, less than or equal to \$N\$ having at-least one common factor between the number and \$N\$ except \$1\$.
  
  Constraints:
  \$1 \le T \le 100000\$
  \$1 \le N \le 1000000\$
  
  Example:
  Input:

3
1
6
15

  
  Output:

0
4
7



And my (updated) code:

def myfun(num_in):

    int_list = []
    some_list = []
    final_list = []

    if num_in == 1:
        print(0)
    elif num_in &gt; 1:

        # check remainder from division
        test = [num_in % pos[j] for j in range(0, (num_in + 1) // 2)]  # only need .5 the number or smaller

        # record if remainder is 0, if it is, keep that because it will be common denominator
        for i in range(0, len(test)):
            if test[i] == 0:
                int_list.append(pos[i])

        # multiply factor by integers until it exceeds input
        # this seems like the best candidate to make more efficient
        for i in range(0, len(int_list)):
            temp = int_list[i]
            # for j in range(1, int(num_in / temp)):
            #     final_list.append(temp * j)

            ttempp = [j for j in range(1, int(num_in / temp))]
            some_list = list(map(lambda x: x * temp, ttempp))
            final_list = final_list + some_list


        #print(final_list)
        #print(set(final_list))
        # add 1 for the number itself since we don't check that (only checked up to .5 * num)
        print(len(set(final_list)) + 1)


# list all possibilities once
pos = [i for i in range(2, 1000000)]


# input code
# how many to run
tot_num = int(input())

# get full list of inputs
master_list = [int(input()) for i in range(tot_num)]

# run code on list of inputs
[myfun(master_list[q]) for q in range(tot_num)]
Your algorithm is very far from optimal. In the worst case (if all numbers are equal to N in the input), it does O(N * T) operations, which clearly way too much (not just for python, for any programming language). 

What they're asking to compute is n - phi(n), where phi is the Euler's totient function. Using the fact that the function is multiplicative one can derive a formula phi(n) = n * {product of (1 - 1 / p) over all prime p dividing n. Using this fact, we can compute it efficiently in O(N log log N) time for all 1 &lt;= i &lt;= N using something that looks like the sieve of Eratosthenes. After that, we can answer each query in O(1). 

A C++ implementation is ridiculously concise and easily fits in the time limit:

#include &lt;cstdio&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;

int main() {
    const int max_n = 1000 * 1000;
    std::vector&lt;int&gt; ans(max_n + 1);
    std::iota(ans.begin(), ans.end(), 0);
    for (int i = 2; i &lt;= max_n; i++)
        if (ans[i] == i)
            for (int j = i; j &lt;= max_n; j += i)
                ans[j] = ans[j] / i * (i - 1);
    int t;
    scanf("%d", &amp;t);
    while (t--) {
        int x;
        scanf("%d", &amp;x);
        printf("%d\n", x - ans[x]);
    }
}


Unfortunately, the same solution in python is too slow. 

def calc_phi(n):
    res = [i for i in range(n + 1)]
    is_prime = [True] * (n + 1)
    for i in range(2, n + 1):
        if is_prime[i]:
            for j in range(2 * i, n, i):
                is_prime[j] = False
                res[j] = res[j] // i * (i - 1)
    return res


def solve():
    max_n = 10 ** 6
    phi = calc_phi(max_n)
    cnt = int(input())
    res = []
    for _ in range(cnt):
        n = int(input())
        res.append(n - phi[n])
    print('\n'.join(map(str, res)))


if __name__ == '__main__':
    solve()


With some optimizations (like more efficient input reading and handling small prime divisors separately), which made the code less readable and nice, I managed to make it complete under 1 second in the worst case on my machine, which is pretty close. It's still too slow for the online judge. So I'm not sure if it's actually solvable in python. That's the main reason why python is rarely used to solve problems with a tight time limit: it's much slower than C++ or Java.