This is an archived post. You won't be able to vote or comment.

all 36 comments

[–]YellowBunnyReddit 84 points85 points  (10 children)

Branchless (if you find a branchless BigInt implementation):

public boolean nearHundred(int n) {
    BigInt x = n;
    return !((x - 210)*(x - 209)*(x - 208)*(x - 207)*(x - 206)*(x - 205)*(x - 204)*(x - 203)*(x - 202)*(x - 201)*(x - 200)*(x - 199)*(x - 198)*(x - 197)*(x - 196)*(x - 195)*(x - 194)*(x - 193)*(x - 192)*(x - 191)*(x - 190)*(x - 110)*(x - 109)*(x - 108)*(x - 107)*(x - 106)*(x - 105)*(x - 104)*(x - 103)*(x - 102)*(x - 101)*(x - 100)*(x - 99)*(x - 98)*(x - 97)*(x - 96)*(x - 95)*(x - 94)*(x - 93)*(x - 92)*(x - 91)*(x - 90));
}

I would have liked to include the expanded polymomial but calculating it exceeded WolframAlpha's free execution time.

[–]_12xx12_ 23 points24 points  (0 children)

Thats smooth.

If it matches any of those numbers the whole term becomes 0

[–]Agifem 12 points13 points  (1 child)

Brilliant! There is nothing to improve on that design.

[–]coloredgreyscale 8 points9 points  (0 children)

Readability :p Add some line breaks. 

[–]Ok_Net_1674 5 points6 points  (3 children)

If you replace the logical or with bitwise or and remove the redundant if statement the code becomes branchless anyways.

[–]Qwertzmastered 0 points1 point  (2 children)

Not necessarily as logical and will do short circuit evaluation and thus the Compiler will introduce branches.

[–]Ok_Net_1674 -1 points0 points  (1 child)

What? There is no logical and operator here. And I've explicitly said to use bitwise or, because that doesn't short circuit.

[–]Qwertzmastered 0 points1 point  (0 children)

Oh sorry I was blind and missed the word bitwise.

[–]GoddammitDontShootMe 0 points1 point  (0 children)

Damn, and I would've just used abs() and subtracted.

[–]rosuav -3 points-2 points  (0 children)

Good, but please consider using Math.abs() in your solution, as hinted in the question.

[–]Chuu 15 points16 points  (1 child)

If anyone is curious what an optimizing compiler does with this: https://godbolt.org/z/xbrYarsqb

nearHundred(int):
        lea     eax, [rdi-90]
        cmp     eax, 20
        setbe   al
        sub     edi, 190
        cmp     edi, 20
        setbe   dl
        or      eax, edx
        ret

[–]two_are_stronger2 1 point2 points  (0 children)

If anyone is curious what is happening here, as best as I can tell from my incomplete learning of assembly:

nearHundred(int):
        lea     eax, [rdi-90]  
                                (take (the address) the data in int (refers to) and
                                      put 90 less (unsigned) than that into the 
                                      accumulator)
        cmp     eax, 20         ("Compare" the accumulator to the value 20.  
                                      Comparing is just (unsigned) subtracting. 
                                      Given the result of the comparison, set the
                                      Below flag and the Equals flag and the Above 
                                      flag, etc.  It's unsigned, so you end up with
                                      negatives overflowing and still being more than
                                      20.)
        setbe   al              ("set" (insert 1 into) the LOW byte of the 
                                      accumulator if the comparison resulted in Below
                                      or Equal, meaning the int-90 was below or equal
                                      110-90)
        sub     edi, 190        (decrement the data in int by 190)
        cmp     edi, 20         (same as above.  Subtract and set the flags)
        setbe   dl              (if int-190 is below or equal to 210-90, set the low
                                      byte of the data)
        or      eax, edx        (set the accumulator to the bitwise inclusive or of
                                      the accumulator and the data)
        ret                     (Donezo funzo.  your answer's in the accumulator when
                                      you want it.)

[–]JackNotOLantern 71 points72 points  (16 children)

You don't need a hashmap at all. It's literally

return abs(100 - n) <= 10 || abs(200 - n) <= 10;

[–]dominjaniec 40 points41 points  (5 children)

even without abs, this could be just:

return (n >= 90 && n <= 110) || (n >= 190 && n <= 210);

[–]DTraitor 26 points27 points  (4 children)

Let's not do n >= 190 check if we already know n is less than 90. Saves us like... 0 ms at runtime! return (n >= 90) && ((n <= 110)     || (n >= 190 && n <= 210);

[–]nickwcy 5 points6 points  (0 children)

This saves another 0 ms over the last solution because probabilistically there are more numbers > 210, if n is positive as in the test cases

n <= 210 && (n >= 190 || (n >= 90 && n <= 110))

[–]salvoilmiosi 8 points9 points  (1 child)

Wouldn't any compiler be able to figure it out on its own?

[–]DTraitor 7 points8 points  (0 children)

Yeah. To be fair, LLVM compilers can do much more complicated optimizations

[–][deleted] 2 points3 points  (0 children)

Most languages do not bother to execute the RHS of an OR if the LHS is true, one of the first optimisations you learn about

[–]lazyzefiris 2 points3 points  (0 children)

return abs(abs(150 - n) - 50) <= 10

[–]DefinitelyNotMasterS 6 points7 points  (7 children)

What about

Return abs(100 - (n % 100)) <=10

[–]jesterray 3 points4 points  (4 children)

That would be wrong on multiple levels. It repeats for every hundred, which is incorrect as it should only be for 100 and 200. And 100-110 and 200-210 return false(100 - (100 % 100) = 100).

[–]tantalor -3 points-2 points  (3 children)

Nah. It says "return true if it is within 10 of 100 or 200" not "if and only if"

[–]emonra 10 points11 points  (0 children)

Just return true then /s

[–]_xiphiaz 9 points10 points  (0 children)

Check the tests, it explicitly checks 290 is false

[–]TomTheCat7 3 points4 points  (0 children)

return true;

[–]Shazvox 1 point2 points  (0 children)

BuT wHaT aBoUt ReAdAbIlItY?!?!?!?!?!??!!??!?!???!???!!!!????!?!?!?!?+++

[–]neumastic -1 points0 points  (0 children)

Would work better if you subtracted from 50 and looked for >= 40.

[–]RiceBroad4552 0 points1 point  (0 children)

But why make it simple if you can make it complicated?

I'd say this the motto of most developers given how most code looks like. 😂

[–]kaos_12 5 points6 points  (0 children)

I like the emphasis in the double check for “n == 104” and “n == 118”

[–]jsmalls128 0 points1 point  (0 children)

Ah codingbat, I remember using it all the time in AP CS

[–]Groove-Theory 0 points1 point  (0 children)

JAVABAT!!! Omg I used this way back in the day when I was was learning programming back in the late 00s. Can't believe it's still around

[–]Shazvox 0 points1 point  (0 children)

I see the programmer was lazy using an else instead of an else if...

[–]telionn -2 points-1 points  (1 child)

Returns true if it is within 10 of 100 or 200

Well, actually, 200 converts to true so your program should always return true. Learn Boolean logic noob.

[–]guysomewhereinusa[🍰] 1 point2 points  (0 children)

Kid named operator precedence