38

I need to find whether a number is divisible by 3 without using %, / or *. The hint given was to use atoi() function. Any idea how to do it?

hichris123
  • 10,145
  • 15
  • 56
  • 70
josh
  • 13,793
  • 12
  • 49
  • 58
  • 48
    This is kind of a dumb interview question isn't it? Doesn't really test your programming knowledge, but rather whether or not you know obscure properties about numbers... – mpen Aug 06 '10 at 07:04
  • 5
    Another of those silly interview questions... this has nothing to do with programming skill in any way. It would just prove that you (maybe by chance) know that the sum of digits has to be divisible by 3 (which I didn't know/remember, honestly ;) ). – Olli Aug 06 '10 at 07:05
  • 9
    Well could also be an examn question from my universtity professor. That guy never worked on real projects but thought that such questions would actualy reflect the real world. ha. – Yves M. Aug 06 '10 at 07:14
  • 15
    I tried to imagine an episode of MacGuyver where he would need this snippet of knowledge, but it defies even that. – detly Aug 06 '10 at 07:29
  • 3
    I wouldn't want to work for someone who even *asked* such a question in an interview. It's insulting. They may as well say "OK, now select Comic Sans MS in Word, and type a sentence for me." – dreamlax Aug 06 '10 at 08:48
  • 2
    It's actually a nice icebreaker question, but of course not to be used when interviewing senior developers. It's not really hard, but still will show you how a junior developers approaches a coding task. Typical implementations require recursion, for instance - without recursion the "adds to 3,6,9" trick fails on 3333. – MSalters Aug 06 '10 at 09:26
  • This question looks like a duplicate of http://stackoverflow.com/questions/844867/check-if-a-number-is-divisible-by-3 – Tom Crockett Aug 06 '10 at 09:39
  • 26
    What people seem to be missing is that you don't need to know any obscure properties of numbers in order to solve this problem. What you *should* know, if you call yourself a computer scientist, is this: **given any language missing some set of mathematical operators, but which is nonetheless Turing complete, you can reimplement all the missing operators yourself.** – Tom Crockett Aug 07 '10 at 02:04
  • An interesting reference is http://www.hackersdelight.org/divcMore.pdf (Hacker's Delight, chapter on division-by-magicnumber-multiplication), pg. 15; the `remu3()` function there is very similar to MSalter's answer below, but the document gives a few additional possibilities how to (efficiently) solve this. – FrankH. Aug 20 '12 at 12:14
  • I think you meant `itoa()` not `atoi()`. But `itoa()` uses division, so it shouldn't be used also. – ST3 Oct 03 '13 at 10:18

16 Answers16

70

The current answers all focus on decimal digits, when applying the "add all digits and see if that divides by 3". That trick actually works in hex as well; e.g. 0x12 can be divided by 3 because 0x1 + 0x2 = 0x3. And "converting" to hex is a lot easier than converting to decimal.

Pseudo-code:

int reduce(int i) {
  if (i > 0x10)
    return reduce((i >> 4) + (i & 0x0F)); // Reduces 0x102 to 0x12 to 0x3.
  else
   return i; // Done.
}
bool isDiv3(int i) {
  i = reduce(i);
  return i==0 || i==3 || i==6 || i==9 || i==0xC || i == 0xF;
}

[edit] Inspired by R, a faster version (O log log N):

int reduce(unsigned i) {
  if (i >= 6)
    return reduce((i >> 2) + (i & 0x03));
  else
   return i; // Done.
}
bool isDiv3(unsigned  i) {
  // Do a few big shifts first before recursing.
  i = (i >> 16) + (i & 0xFFFF);
  i = (i >> 8) + (i & 0xFF);
  i = (i >> 4) + (i & 0xF);
  // Because of additive overflow, it's possible that i > 0x10 here. No big deal.
  i = reduce(i);
  return i==0 || i==3;
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 7
    BTW, in base-N the trick works for all factors of (N-1). E.g. in hex it also works for 5 ("dividable by 5" is another similar interview question) – MSalters Aug 06 '10 at 09:28
  • Doesn't work for negatives, but adding a condition to `isDiv3` would be easy. – Forrest Voight Aug 08 '10 at 05:38
  • +1 for pointing out that you can do this with hex. I hadn't realized that and it's really useful. Thanks to @MSalters too for mentioning how it extends to other values of `N`; it might be useful with other power-of-2 values of `N` with more factors. – R.. GitHub STOP HELPING ICE Aug 11 '10 at 08:03
  • 2
    Actually since 3=4-1, doing this in base 4 might be cleaner. At least you'd eliminate all the `||` mess at the end. – R.. GitHub STOP HELPING ICE Aug 11 '10 at 08:05
  • shouldn't that be: `return i` instead of `return in`? please explain if i'm wrong – Lily Chung Aug 11 '10 at 15:45
  • @R: Doing it in base 4 works as well. Of course, that means shifting by 2 bits at a time, which means the method will take twice as long. – MSalters Aug 16 '10 at 11:18
59

Subtract 3 until you either

a) hit 0 - number was divisible by 3

b) get a number less than 0 - number wasn't divisible

-- edited version to fix noted problems

while n > 0:
    n -= 3
while n < 0:
    n += 3
return n == 0
Forrest Voight
  • 2,249
  • 16
  • 21
  • If the number is signed, you have to add two more conditions for when x is negative and when x is 0 for the method to terminate. – blizpasta Aug 06 '10 at 07:19
  • 7
    This is not very efficient; it's Θ(n), whereas @tdammers' solution is Θ(log n) – Tom Crockett Aug 06 '10 at 07:26
  • not, however, the most efficient (since the atoi solution secretly uses division and mod) – cobbal Aug 06 '10 at 07:26
  • 2
    tdammers' solution requires the ability to do division which is explicity banned. (You can't split a number into its decimal digits without dividing by 10). – JeremyP Aug 06 '10 at 08:37
  • @JeremyP you're right, I hadn't thought of that. It's still possible to convert it to a string in Θ(n) time, replacing division with iterative subtraction, but the Θ(log n) solution can still be achieved by applying the modular arithmatic idea directly to the binary number--see @MSalters' answer, or mine. – Tom Crockett Aug 06 '10 at 09:45
  • Division wasn't banned explicitly, just the / and % operators. Use of atoi (or, as I assume, rather the reverse, itoa) is even explicitly hinted at. Also, using division behind the scenes doesn't make it less efficient in terms of big-O; the algorithmic complexity remains unchanged. – tdammers Aug 06 '10 at 09:55
  • 2
    @pelotom: MSalter's answer does division by 16. If you are going to allow bit shifts you might as well re-implement the modulus operation and test thus: `bool isDivisibleBy3 = modUsingShifts(x, 3); – JeremyP Aug 06 '10 at 09:58
  • 1
    @tdammers: Great, so if I am only banned from using the *symbols* % and /, the following line of Java qualifies `BigInteger(x).mod(BigInteger(3)).intValue() == 0` – JeremyP Aug 06 '10 at 10:03
  • 1
    @JeremyP I don't think what you're suggesting is illegal; the division operator was outlawed, not bit shifting. – Tom Crockett Aug 06 '10 at 10:05
  • 3
    @pelotom, describing this as Θ(n) is rather misleading, this is exponential in the bit length of the number (most algorithms you'll see with this property are also described as exponential, not linear). – Dimitris Andreou Aug 09 '10 at 00:38
  • 1
    @Dimitris: fair enough... so this solution of using iterative subtraction is exponential in the bit-length of the number, whereas a better solution (subtracting the even bits from the odd bits) is linear in the bit-length of the number. – Tom Crockett Aug 09 '10 at 01:41
  • 1
    I don't call `O(n)` solutions to problems that can be solved much more efficiently "elegant" unless the efficient solution would be several orders of magnitude larger or more complicated to implement. – R.. GitHub STOP HELPING ICE Aug 11 '10 at 08:06
  • 4
    Why worry about efficiency when what we're discussing is a silly interview question? I'd go with most straightforward solution possible. Bit shifts, multiple OR's and all that jazz increase complexity in my book. – YRH Aug 11 '10 at 08:38
  • 3
    @YRH: That's _precisely_ why worry - because it's an interview question. If an interviewee gave me the most-straightforward but also horrible-runtime variant of the answer, I'd definitely ask _more_ along the lines of "now think of ways to make it better ...". – FrankH. Aug 20 '12 at 12:20
  • 'the most elegant solution so far' -- It's not elegant at all because the conditionals are unnecessary: `while n > 0: n -= 3; while n < 0: n += 3; return n == 0` – Jim Balter Sep 08 '12 at 01:50
32

Split the number into digits. Add the digits together. Repeat until you have only one digit left. If that digit is 3, 6, or 9, the number is divisible by 3. (And don't forget to handle 0 as a special case).

tdammers
  • 20,353
  • 1
  • 39
  • 56
  • 7
    there could be a violation of requirements using this process that is not to use %,/,* to get digits from number we need to use them. better to convert entire number into string and get each character and covert it into again number and add them and find the reslut. – srinivas Aug 06 '10 at 07:06
  • 1
    "to get digits from number we need to use them" no, it is not true – Dennis C Aug 06 '10 at 07:15
  • That's what I was trying to get at. You convert the number into a string, split it into digits, and treat each digit as a number in the 0 to 9 range. – tdammers Aug 06 '10 at 07:15
  • 3
    So, how do you convert the number into a decimal number in a string without division? – janm Aug 06 '10 at 07:31
  • @Jakub: Yes, I should have added that. @janm: Virtually every programming language has a method for this in its standard library or even in the language itself. In C, one could use itoa() or even sprintf(). Of course, these probably use some kind of modulo internally too. – tdammers Aug 06 '10 at 08:41
  • It's not necessary to convert to a string to apply the basic idea here. See @MSalters' solution, or mine. – Tom Crockett Aug 06 '10 at 09:39
  • @srinivas in fact most number printing functions use `%` and `/` by 10 implicitly. But you can convert a binary number to BCD to get the digits using [double dabble algorithms](https://en.wikipedia.org/wiki/Double_dabble) using only add/subtract and bitshifts. Anyway, you don't need any conversion since you can check the sum of hexadecimal digits like in decimal – phuclv May 16 '14 at 13:18
17

While the technique of converting to a string and then adding the decimal digits together is elegant, it either requires division or is inefficient in the conversion-to-a-string step. Is there a way to apply the idea directly to a binary number, without first converting to a string of decimal digits?

It turns out, there is:

Given a binary number, the sum of its odd bits minus the sum of its even bits is divisible by 3 iff the original number was divisible by 3.

As an example: take the number 3726, which is divisible by 3. In binary, this is 111010001110. So we take the odd digits, starting from the right and moving left, which are [1, 1, 0, 1, 1, 1]; the sum of these is 5. The even bits are [0, 1, 0, 0, 0, 1]; the sum of these is 2. 5 - 2 = 3, from which we can conclude that the original number is divisible by 3.

Tom Crockett
  • 30,818
  • 8
  • 72
  • 90
  • 4
    This (summing of odd and even digits/bits) is again a special case of a general trick, checking in base N whether a number can be divided by (N+1). – MSalters Aug 16 '10 at 11:23
  • @MSalters: Can you give some reference to the proof of this statement ? – user1599964 Sep 13 '13 at 06:45
  • 1
    @user1599964: In base N, (N+1) is written as 11. So, the property holds for 11 * 1. If and only if the property holds for number x, it also holds for x+11. That's trivial if there's no overflow (e.g. 100 + 11 = 111, for any base). With an overflow, the overflow is from an odd digit to an even digit or from an even digit to an odd digit, which preserves the balance. Overflows deducts N from the overflowing digit and adds +1 to the higher digit. Since we take the difference of odd and even digit sums, overflow changes the difference by N+1 which doesn't affect divisibility by N+1. – MSalters Sep 13 '13 at 09:07
6

A number divisible by 3, iirc has a characteristic that the sum of its digit is divisible by 3. For example,

12 -> 1 + 2 = 3
144 -> 1 + 4 + 4 = 9
Anax
  • 9,122
  • 5
  • 34
  • 68
Eugene Yokota
  • 94,654
  • 45
  • 215
  • 319
6

The interview question essentially asks you to come up with (or have already known) the divisibility rule shorthand with 3 as the divisor.

One of the divisibility rule for 3 is as follows:

Take any number and add together each digit in the number. Then take that sum and determine if it is divisible by 3 (repeating the same procedure as necessary). If the final number is divisible by 3, then the original number is divisible by 3.

Example:

16,499,205,854,376
=> 1+6+4+9+9+2+0+5+8+5+4+3+7+6 sums to 69
=> 6 + 9 = 15 => 1 + 5 = 6, which is clearly divisible by 3.

See also

polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
5

Given a number x. Convert x to a string. Parse the string character by character. Convert each parsed character to a number (using atoi()) and add up all these numbers into a new number y. Repeat the process until your final resultant number is one digit long. If that one digit is either 3,6 or 9, the origional number x is divisible by 3.

Amichai
  • 1,144
  • 1
  • 12
  • 21
  • this is the procedure that wont user the operators /,% or *. Voted up.. Cheers.. :) – srinivas Aug 06 '10 at 07:03
  • 1
    To convert a single character to a number you don't need to use atoi - simply subtract '0' from the character (its ASCII code). – smichak Aug 06 '10 at 07:05
  • Give me an algorithm to convert a number into a decimal string without doing division. – JeremyP Aug 06 '10 at 08:39
  • 2
    @JeremyP: `divide x y = if x < y then 0 else 1 + divide (x - y) y` There, now I can use division, because I implemented it in terms of addition and subtraction. It's inefficient, but correct. Are you going to argue that addition and subtraction shouldn't be allowed now? – Tom Crockett Aug 06 '10 at 10:36
  • @pelotom: No, the point is that the question is flawed. Either it bans any "handed to you on a plate" form of division in which you have to reimplement it using repeated subtraction or it merely bans the use of the / and % symbols in which case it is quite easy to get round. Or perhaps it isn't flawed and it is designed to provoke these kinds of discussions. – JeremyP Aug 07 '10 at 11:22
5

My solution in Java only works for 32-bit unsigned ints.

static boolean isDivisibleBy3(int n) {
  int x = n;
  x = (x >>> 16) + (x & 0xffff); // max 0x0001fffe
  x = (x >>> 8) + (x & 0x00ff); // max 0x02fd
  x = (x >>> 4) + (x & 0x000f); // max 0x003d (for 0x02ef)
  x = (x >>> 4) + (x & 0x000f); // max 0x0011 (for 0x002f)
  return ((011111111111 >> x) & 1) != 0;
}

It first reduces the number down to a number less than 32. The last step checks for divisibility by shifting the mask the appropriate number of times to the right.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Roland Illig
  • 40,703
  • 10
  • 88
  • 121
  • you can remove the last `x = (x >>> 4) + (x & 0x000f);` line and replace the magic number with `01111111111111111111111L` because the max value fits in 64 bits. And to make it work for 64-bit values just add `x = (x >>> 32) + (x & 0xffffffff)`. Example: https://godbolt.org/z/Cc2ABA – phuclv Feb 26 '19 at 00:00
3

You didn't tag this C, but since you mentioned atoi, I'm going to give a C solution:

int isdiv3(int x)
{
    div_t d = div(x, 3);
    return !d.rem;
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
3
bool isDiv3(unsigned int n)
{
    unsigned int n_div_3 =
        n * (unsigned int) 0xaaaaaaab;
    return (n_div_3 < 0x55555556);//<=>n_div_3 <= 0x55555555

/*
because 3 * 0xaaaaaaab == 0x200000001 and
 (uint32_t) 0x200000001 == 1
*/
}

bool isDiv5(unsigned int n)
{
    unsigned int n_div_5 =
        i * (unsigned int) 0xcccccccd;
    return (n_div_5 < 0x33333334);//<=>n_div_5 <= 0x33333333

/*
because 5 * 0xcccccccd == 0x4 0000 0001 and
 (uint32_t) 0x400000001 == 1
*/
}

Following the same rule, to obtain the result of divisibility test by 'n', we can : multiply the number by 0x1 0000 0000 - (1/n)*0xFFFFFFFF compare to (1/n) * 0xFFFFFFFF

The counterpart is that for some values, the test won't be able to return a correct result for all the 32bit numbers you want to test, for example, with divisibility by 7 :

we got 0x100000000- (1/n)*0xFFFFFFFF = 0xDB6DB6DC and 7 * 0xDB6DB6DC = 0x6 0000 0004, We will only test one quarter of the values, but we can certainly avoid that with substractions.

Other examples :

11 * 0xE8BA2E8C = A0000 0004, one quarter of the values

17 * 0xF0F0F0F1 = 10 0000 0000 1 comparing to 0xF0F0F0F Every values !

Etc., we can even test every numbers by combining natural numbers between them.

phuclv
  • 37,963
  • 15
  • 156
  • 475
2
inline bool divisible3(uint32_t x)  //inline is not a must, because latest compilers always optimize it as inline.
{
    //1431655765 = (2^32 - 1) / 3
    //2863311531 = (2^32) - 1431655765
    return x * 2863311531u <= 1431655765u;
}

On some compilers this is even faster then regular way: x % 3. Read more here.

phuclv
  • 37,963
  • 15
  • 156
  • 475
ST3
  • 8,826
  • 3
  • 68
  • 92
  • In my opinion it is the best answer. –  Sep 15 '13 at 05:52
  • this method is also described in [Faster remainders when the divisor is a constant: beating compilers and libdivide](https://lemire.me/blog/2019/02/08/faster-remainders-when-the-divisor-is-a-constant-beating-compilers-and-libdivide/) – phuclv Feb 18 '19 at 16:20
  • @chepner God damn.. it was so long after posting it. I probably missed multiplication part... – ST3 Feb 21 '19 at 09:08
2

A number is divisible by 3 if all the digits in the number when added gives a result 3, 6 or 9. For example 3693 is divisible by 3 as 3+6+9+3 = 21 and 2+1=3 and 3 is divisible by 3.

Kangkan
  • 15,267
  • 10
  • 70
  • 113
1

well a number is divisible by 3 if all the sum of digits of the number are divisible by 3. so you could get each digit as a substring of the input number and then add them up. you then would repeat this process until there is only a single digit result.

if this is 3, 6 or 9 the number is divisable by 3.

GorillaPatch
  • 5,007
  • 1
  • 39
  • 56
0
  • Here is a pseudo-algol i came up with .

Let us follow binary progress of multiples of 3

000 011
000 110

001 001
001 100
001 111

010 010
010 101


011 000
011 011
011 110

100 001
100 100
100 111

101 010
101 101

just have a remark that, for a binary multiple of 3 x=abcdef in following couples abc=(000,011),(001,100),(010,101) cde doest change , hence, my proposed algorithm:

divisible(x):

    y = x&7

    z = x>>3

    if number_of_bits(z)<4

        if z=000 or 011 or 110 , return (y==000 or 011 or 110) end

        if z=001 or 100 or 111 , return (y==001 or 100 or 111) end

        if z=010 or 101 , return (y==010 or 101) end

    end

    if divisible(z) , return (y==000 or 011 or 110) end

    if divisible(z-1) , return (y==001 or 100 or 111) end

    if divisible(z-2) , return (y==010 or 101) end

end
Abr001am
  • 571
  • 6
  • 19
0

C# Solution for checking if a number is divisible by 3

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int num = 33;
            bool flag = false;

            while (true)
            {
                num = num - 7;
                if (num == 0)
                {
                    flag = true;
                    break;
                }
                else if (num < 0)
                {
                    break;
                }
                else
                {
                    flag = false;
                }
            }

            if (flag)
                Console.WriteLine("Divisible by 3");
            else
                Console.WriteLine("Not Divisible by 3");

            Console.ReadLine();

        }
    }
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
Vishwanath Dalvi
  • 35,388
  • 41
  • 123
  • 155
-1

Here is your optimized solution that every one should know.................

Source: http://www.geeksforgeeks.org/archives/511

#include<stdio.h>


int isMultiple(int n)
{
    int o_count = 0;
    int e_count = 0;


    if(n < 0)  
           n = -n;
    if(n == 0) 
           return 1;
    if(n == 1)
           return 0;

    while(n)
    {

        if(n & 1)
           o_count++;
        n = n>>1;


        if(n & 1)
            e_count++;
        n = n>>1;
    }

     return isMultiple(abs(o_count - e_count));
}


int main()
{
    int num = 23;
    if (isMultiple(num))
        printf("multiple of 3");
    else
        printf(" not multiple of 3");

    return 0;
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
Anil Arya
  • 3,100
  • 7
  • 43
  • 69
  • 1
    it's far from "optimized". I'm sure it'll be much slower than the simple `n % 3 == 0` that all modern compilers recognize and optimize into the efficient multiplication – phuclv Feb 18 '19 at 16:18