# Can you beat our solutions for the raindrops exercise?

**URL:** https://discourse.julialang.org/t/can-you-beat-our-solutions-for-the-raindrops-exercise/52006
**Category:** Performance
**Created:** [December 17, 2020, 7:07pm UTC](https://discourse.julialang.org/t/can-you-beat-our-solutions-for-the-raindrops-exercise/52006 "2020-12-17T19:07:46Z")
**Posts on this page:** 1
**Showing post:** 9

<div class="post-metadata">

### Author: ![Luapulu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/luapulu/32/17669_2.png) [@Luapulu](https://discourse.julialang.org/u/Luapulu)
#### Post date: [December 18, 2020, 7:30am UTC](https://discourse.julialang.org/t/can-you-beat-our-solutions-for-the-raindrops-exercise/52006/9 "2020-12-18T07:30:36Z")

</div>

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](https://discourse.julialang.org/t/if-elseif-else-performance/24622/18) 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**

```julia
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
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)

```

---

_[View the full topic](https://discourse.julialang.org/t/can-you-beat-our-solutions-for-the-raindrops-exercise/52006)._
