views:

1920

answers:

11

Not sure if it's a duplicate. But 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?

+19  A: 

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
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
"to get digits from number we need to use them" no, it is not true
Dennis Cheung
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
So, how do you convert the number into a decimal number in a string without division?
janm
Don't forget about 0.
Jakub Šturc
@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
It's not necessary to convert to a string to apply the basic idea here. See @MSalters' solution, or mine.
pelotom
A: 

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
sorry, couldn't help myself when i read divisible by zero
kirbuchi
Sorry, updated the same.
Kangkan
+5  A: 

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
eed3si9n
A: 

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
@tdammers was quicker than me with typing...
GorillaPatch
Getting decimal digits is implicitly using division. See the answer using hex for a similar approach that's not cheating.
R..
No I am not cheating. You just convert the int into a string and then you access each character(digit) individually.
GorillaPatch
+4  A: 

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.

Ami
this is the procedure that wont user the operators /,% or *. Voted up.. Cheers.. :)
srinivas
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
Give me an algorithm to convert a number into a decimal string without doing division.
JeremyP
@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?
pelotom
@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
+36  A: 

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

if n > 0:
    while n > 0:
        n -= 3
elif n < 0:
    while n < 0:
        n += 3
return n == 0
Forrest
Probably the most elegant solution so far
smichak
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
This is not very efficient; it's Θ(n), whereas @tdammers' solution is Θ(log n)
pelotom
not, however, the most efficient (since the atoi solution secretly uses division and mod)
cobbal
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
@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.
pelotom
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
@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
@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
@JeremyP I don't think what you're suggesting is illegal; the division operator was outlawed, not bit shifting.
pelotom
@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
@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.
pelotom
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..
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
+35  A: 

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;
}
MSalters
+1 for the Hex Method.
st0le
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
Doesn't work for negatives, but adding a condition to `isDiv3` would be easy.
Forrest
+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..
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..
shouldn't that be: `return i` instead of `return in`? please explain if i'm wrong
Professor_Calculus
@Professor_Calculus: Of course, typo fixed.
MSalters
@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
+5  A: 

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
+12  A: 

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.

pelotom
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
+1  A: 

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;
}
R..
+1  A: 

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.

Roland Illig