## Vedic Divisibility

### July 8, 2011

We extract into separate functions the calculation of the last digit and the number remaining after stripping the last digit:

`(define (last x) (car (reverse (digits x))))`

```(define (but-last x)   (undigits (reverse (cdr (reverse (digits x))))))```

For the calculation of the osculator we need to figure out the smallest multiple of the divisor that ends with 9. That’s easy. Since the divisor must be odd and not divisible by 5, it must end in 1, 3, 7 or 9. If it ends in 1, multiply by 9. If it ends in 3, multiply by 3. If it ends in 7, multiply by 7. And if it ends in 9, do nothing. Then the calculation of the osculator is simple:

```(define (osculator n)   (define (f x) (+ (but-last (* n x)) 1))   (let ((ds (digits n)))     (case (car (reverse ds))      ((1) (f 9))      ((3) (f 3))      ((7) (f 7))      ((9) (f 1))     (else (error 'osculator "unsupported")))))```

The divisibility test is recursive, reducing the size of the dividend n at each step:

```(define (divisible? n d)   (let ((osc (osculator d)))     (let loop ((n n))       (let ((next (+ (but-last n) (* last n) osc))))         (if (< next n) (loop next) (zero? (modulo n d)))))))```

Here are some examples:

```> (divisible? 13174584 23) #t > (divisible? 175121 37) #t > (divisible? 134567 29) #f```

We used `digits` and `undigits` from the Standard Prelude. You can run the program at http://programmingpraxis.codepad.org/qZrg7y54.

Pages: 1 2

### 5 Responses to “Vedic Divisibility”

1. arturasl said

Solution in Python:

```def divides(dividend, divisor):
endings = {1 : 9, 3 : 3, 7 : 7, 9 : 1}

if divisor % 10 not in endings:
raise Exception('divisor should end in 1, 3, 7 or 9')

osculator = ((divisor * endings[divisor % 10]) // 10) + 1

while True:
prev_dividend = dividend
dividend = dividend // 10 + (dividend % 10) * osculator

if prev_dividend <= dividend:
dividend = prev_dividend
break

return (dividend % divisor) == 0

print(divides(13174584, 23))
```
2. WillJ said
```#include <iostream>

using namespace std;

int findOsculator( int num )
{
int temp, i = 1;
do
{
temp = num * i;
i++;
}
while( temp % 10 != 9 );
temp = temp / 10;
return temp + 1;
}

bool divisible(int dividend, int divisor)
{
int remainder,prev_dividend, osc;
osc = findOsculator( divisor );
do
{
prev_dividend = dividend;
remainder = dividend % 10;
dividend = (dividend / 10) + (osc * remainder);
}
while( dividend < prev_dividend );
return !( dividend % divisor );
}

int main()
{
cout << divisible(13174584,23);
}
```
3. Graham said

Python:

```def is_divisible(n, d):
osc = 1 + (d * {1: 9, 3: 3, 7: 7, 9: 1}[d % 10]) // 10
old, new = float('inf'), n
while new < old:
a, b = divmod(new, 10)
old, new = new, a + b * osc
return new % d == 0

if __name__ == "__main__":
for (n, d) in [(13174584, 23), (175121, 37), (134567, 29)]:
print "Is %d divisible by %d?%7s" % (n, d, "Yes." if is_divisible(n, d)
else "No.")
```

And since Remco hasn’t jumped on it yet, here’s my attempt in Haskell:

```import Data.Map

osculator :: (Integral a) => a -> a
osculator d = f e where
f x = 1 + d * x `div` 10
e = fromList [(1,9), (3,3), (7,7), (9,1)] ! (d `mod` 10)

isDivisible :: (Integral a) => a -> a -> Bool
isDivisible n d = aux old new where
old = n + 1
new = n
osc = osculator d
aux x y | x <= y            = y `mod` d == 0
| otherwise         = aux y (a + b * osc) where (a,b) = divMod y 10

main :: IO ()
main = mapM_ (\(n,d) -> print \$ "Is " ++ show n ++ " divisible by " ++ show d ++
"? " ++ show (isDivisible n d)) [(13174584, 23), (175121, 37), (134567, 29)]
```
4. Mike said

Just to be different, how about an F# version.

```

let osculator n =
match (n / 10, n % 10) with
| d,1 -> d*9 + 1
| d,3 -> d*3 + 1
| d,7 -> d*7 + 1
| d,9 -> d   + 1
| _,_ -> raise <| BadValue("divisor cannot be divisible by 2 or 5")

let isdivisible dividend divisor =
let osc = osculator divisor
let rec loop old_dividend =
let new_dividend = old_dividend / 10 + old_dividend % 10 * osc
if new_dividend >= old_dividend then
old_dividend % divisor = 0
else
loop new_dividend
loop dividend
```
5. Mike said

Line 07 above should be:

```    | d,7 -> d*7 + 5   // 7*7 = 49, so carry the 4
```