Can you beat our solutions for the raindrops exercise?

You can do a little better by using @inbounds. Note that I added return 0 < i <= 1000 ? nums[i] : string(i) so that the function could actually handle any positive integer, even if we’re only benchmarking up to 1000.

I don’t quite understand why an array is faster than a tuple here. I thought this discussion concluded that tuples rule for these kind of small lookups.

I also think it’s interesting that the lookup is faster when you statically create the number strings, but the if tree is faster when you don’t. I’m not sure why that is.

Results

const str = [
    "Pling",            # 001
    "Plang",            # 010
    "PlingPlang",       # 011
    "Plong",            # 100
    "PlingPlong",       # 101
    "PlangPlong",       # 110
    "PlingPlangPlong",  # 111
]

const nums = string.(1:1000)

# MatFi
function raindrops7(i::Int)
    j=(i%3 == 0 && 1)|(i%5 == 0 && 2)|(i%7 == 0 && 4)
    j == 0  && return i <= 1000 ? nums[i] : string(i)
    return str[Int(j)]
end

# malacroi
function raindrops8(i)
    j=(i % 3 == 0) + (i % 5 == 0) << 1 + (i % 7 == 0) << 2
    j == 0 && return i <= 1000 ? nums[i] : string(i)
    return str[j]
end

# lookup 2
function raindrops9(number)
    i = (number % 3 == 0) + (number % 5 == 0) << 1 + (number % 7 == 0) << 2
    i == 0 && return 0 < number <= 1000 ? @inbounds(nums[number]) : string(number)
    return @inbounds str[i]
end

# tuple lookup
function raindrops10(number)
    i =  (number % 3 == 0) + (number % 5 == 0) << 1 + (number % 7 == 0) << 2
    i == 0 && return 0 < number <= 1000 ? @inbounds(nums[number]) : string(number)
    return @inbounds (
        "Pling",            # 001
        "Plang",            # 010
        "PlingPlang",       # 011
        "Plong",            # 100
        "PlingPlong",       # 101
        "PlangPlong",       # 110
        "PlingPlangPlong",  # 111
    )[i]
end

With these results:

julia> titles = (
    "tree", "IOBuffer", "compact", "switch", "lookup", "ScottPJones", "MatFi", "malacroi",
    "lookup 2", "tuple"
)

julia> for (i, name) in zip(7:10, titles[7:10])
           print(name, ": ")
           @btime mapreduce($(Symbol(:raindrops, i)), (a, b) -> b, 1:1000) samples=10_000_000
       end
MatFi:   5.686 μs (0 allocations: 0 bytes)
malacroi:   3.981 μs (0 allocations: 0 bytes)
lookup 2:   3.611 μs (0 allocations: 0 bytes)
tuple:   4.706 μs (0 allocations: 0 bytes)
1 Like