# Consider all integer combinations of ab for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5:
#
# 2^2=4,  2^3=8,   2^4=16,  2^5=32
# 3^2=9,  3^3=27,  3^4=81,  3^5=243
# 4^2=16, 4^3=64,  4^4=256, 4^5=1024
# 5^2=25, 5^3=125, 5^4=625, 5^5=3125
#
# If they are then placed in numerical order, with any repeats removed, we get
# the following sequence of 15 distinct terms:
#
# 4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125
#
# How many distinct terms are in the sequence generated by ab for 2 ≤ a ≤ 100
# and 2 ≤ b ≤ 100?

using ProjectEulerSolutions

# Just try all combinations and store unique ones using a set.  BigInt must be
# used because 100^100 is larger than 2^64.  Can easily make it a bit faster
# using some additinoal logic to prevent trying multiples of powers.  Might be
# possible to do it without even performing powers, just looking at counts of
# prime factors, foregoing the need for BigInts, but that would probably be
# slower.
function p029solution_loop(amin::Integer=2, amax::Integer=5,
                      bmin::Integer=2, bmax::Integer=5)::Integer
    powers = Set{BigInt}()
    for a in amin:amax
        for b in bmin:bmax
            push!(powers, BigInt(a)^b)
        end
    end
    return length(powers)
end


function p029solution_listcomprehension(amin::Integer=2, amax::Integer=5,
                                        bmin::Integer=2, bmax::Integer=5)::Integer
    return length(Set{BigInt}([BigInt(a)^b for a in amin:amax, b in bmin:bmax]))
end

p029 = Problems.Problem(Dict("Explicit loop" => p029solution_loop,
                             "List comprehension" => p029solution_listcomprehension))

Problems.benchmark(p029, 2, 100, 2, 100)