Solution for puzzle 3d x 1d = 2d x 2d in Python
Style

Python has a style guide called PEP8. It is definitly worth a read. Among the few things you could do to make your code more pythonic : spacing around operators. Also, you should try to avoid giving your variables the same name as builtins. Furthermore, you can assign all variables in one go if it corresponds to a single logical operation (as in "saving the best result found so far"). Finally, you can remove explicit conversion when printing :

import time
start = time.time()
maxi, gx, gy, gi, gj = 0, 0, 0, 0, 0

for i in range(999, 99, -1):
    for j in range(9, 0, -1):
        mul = i * j

        for x in range(99, 9, -1):
            for y in range(99, 9, -1):
                mul2 = x*y

                if mul == mul2:
                    if mul &gt; maxi:
                        maxi, gx, gy, gi, gj = mul, x, y, i, j

print("i: ", gi)
print("j: ", gj)
print("x: ", gx)
print("y: ", gy)
print("max: ", maxi)
end = time.time()
print(end - start


Algorithm

For each i, j, it only makes sense to check if it can be written under the form _ _ * _ _ if it is bigger than the current best value.

for i in range(999, 99, -1):
    for j in range(9, 0, -1):
        mul = i * j

        if mul &gt; maxi:
            for x in range(99, 9, -1):
                for y in range(99, 9, -1):
                    mul2 = x*y
                    if mul == mul2:
                            maxi, gx, gy, gi, gj = mul, x, y, i, j


This makes your code go roughly 500 times faster.

From this point, it is hard to make things actually faster but let's try.

Once you have mul, to find 2 divisors under of 2 digits, you don't need have two loops : one is enough and then you check if the number actually divides mul and if the result has 2 digits.

    if mul &gt; maxi:
        for x in range(99, 9, -1):
            y, r = divmod(mul, x)
            if r == 0 and 10 &lt;= y &lt; 100:
                axi, gx, gy, gi, gj = mul, x, y, i, j


Once you have it, you can break because it will only find the same solution.

    if mul &gt; maxi:
        for x in range(99, 9, -1):
            y, r = divmod(mul, x)
            if r == 0 and 10 &lt;= y &lt; 100:
                maxi, gx, gy, gi, gj = mul, x, y, i, j
                break


Similarly, you can break out of the j loop when mul &lt;= maxi because mul goes decreasing.

for i in range(999, 99, -1):
    for j in range(9, 0, -1):
        mul = i * j

        if mul &lt;= maxi:
            break
        else:
            for x in range(99, 9, -1):
                y, r = divmod(mul, x)
                if r == 0 and 10 &lt;= y &lt; 100:
                    maxi, gx, gy, gi, gj = mul, x, y, i, j
                    break


Also, in the x loop, it doesn't make sense anymore to do backward.

for i in range(999, 99, -1):
    for j in range(9, 0, -1):
        mul = i * j
        if mul &lt;= maxi:
            break
        else:
            for x in range(10, 100):
                y, r = divmod(mul, x)
                if r == 0 and 10 &lt;= y &lt; 100:
                    maxi, gx, gy, gi, gj = mul, x, y, i, j
                    print(maxi)
                    break


This seems to be roughly 10 000 times faster than it used to be.