Determine if an integer is divisible by 3

20

4

Your goal is to determine if a number is divisible by 3 without using conditionals. The input will be an unsigned 8 bit number from 0 to 255. Creativity encouraged!

You are ONLY allowed to use

  • Equality/Inequality (==, !=, >, <, >=, <=)

  • Arithmetic (+, -, x)

  • Logical Operators (! not, && and, || or)

  • Bitwise Operators (~ not, & and, | or, ^ xor, <<, >>, >>> arithmetic and logical left and right shifts)

  • Constants (it would be better if you kept these small)

  • Variable assignment

Output 0 if false, 1 if true.

Standard atomic code-golf rules apply. If you have any questions please leave them in the comments. Example methods here. A token is any of the above excluding constants and variables.

qwr

Posted 2014-06-23T03:20:09.733

Reputation: 8 929

@GregHewgill My typo, it should be 8 bit number. – qwr – 2014-06-23T03:33:58.827

2Are we only allowed to use the above operators? Otherwise, modulo would make this way too easy. – Jwosty – 2014-06-23T03:40:41.697

Also, how about table lookup? – Greg Hewgill – 2014-06-23T03:42:13.067

@Jwosty you are only allowed to use those, but I will take suggestions. – qwr – 2014-06-23T03:44:45.753

@GregHewgill If you use a table lookup, you have to count all tokens. – qwr – 2014-06-23T03:46:19.403

Is 0 considered to be divisible by 3? – Greg Hewgill – 2014-06-23T03:49:45.637

3Can you clarify what you mean by no conditionals? Is it limited to IF statements, or does it apply to things like loops as well? – Ruslan – 2014-06-23T03:50:09.927

1@Ruslan You are only allowed to use the above. – qwr – 2014-06-23T03:54:02.297

Can I return true/false instead of 1/0? – Tyilo – 2014-06-23T17:20:12.533

what about Ruby's to_s or to_i? That is, toString or toInteger – Not that Charles – 2014-06-23T21:52:34.043

Answers

31

C - 2 tokens

int div3(int x) {
    return x * 0xAAAAAAAB <= x;
}

Seems to work up to 231-1.

Credits to zalgo("nhahtdh") for the multiplicative inverse idea.

aditsu quit because SE is EVIL

Posted 2014-06-23T03:20:09.733

Reputation: 22 326

1+1. Was baffled a bit at how the <= works, and remembered that 0xAAAAAAAB is taken to be unsigned int type, thus the result of multiplication is unsigned. – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ – 2014-06-23T07:56:31.300

@DigitalTrauma inequality operators are allowed, not banned – aditsu quit because SE is EVIL – 2014-06-23T17:59:41.563

@aditsu Oops! I need to read more carefully sometimes! +1 great answer! – Digital Trauma – 2014-06-23T18:01:43.230

@aditsu, sorry I'm noob, how exactly does this work? – Kartik_Koro – 2014-06-24T05:22:41.700

2

@Kartik_Koro 0xAAAAAAAB * 3 == 1 due to overflow, so for any int x, x * 0xAAAAAAAB * 3 == x. Also y * 3 has different values for different y, therefore y = x * 0xAAAAAAAB must be the only y such that y * 3 == x. If x is a multiple of 3, then y must be x/3, otherwise it must be working through overflow. A simple way to check is to compare y with x. Also see http://en.wikipedia.org/wiki/Modular_multiplicative_inverse

– aditsu quit because SE is EVIL – 2014-06-24T05:56:56.073

@aditsu I see, +1'd thats great :D – Kartik_Koro – 2014-06-24T06:40:43.993

The challenge states that the input should be unsigned. Maybe uint8_t x instead of int? – 200_success – 2014-06-24T15:04:04.847

@200_success The code is compatible with the specified type and range, I see no reason to restrict it. – aditsu quit because SE is EVIL – 2014-06-24T17:12:56.150

17

Python, 3 2 tokens

Brute force solution, but it works.

0x9249249249249249249249249249249249249249249249249249249249249249>>x&1

Thanks to Howard for the 1 token reduction.

Greg Hewgill

Posted 2014-06-23T03:20:09.733

Reputation: 2 641

Wow! Your solution is probably the shortest (3 tokens), but I want to encourage other answers too. – qwr – 2014-06-23T04:05:41.473

11There is even a 2 token solution: 0x9......>>x&1. – Howard – 2014-06-23T05:00:09.200

6

C - 5 4 (?) tokens

int div3_m2(uint32_t n) {
    return n == 3 * (n * 0xAAAAAAABull >> 33);
}

Works for any unsigned 32-bit number.

This code makes use of multiplicative inverse modulo 232 of a divisor to convert division operation into multiplication operation.

Edit

My solution (posted 2 minutes after) has the same spirit as aditsu's solution. Credit to him for the use of == that improves my solution by 1 token.

Reference

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Posted 2014-06-23T03:20:09.733

Reputation: 5 683

1This is incredible. I knew about magic numbers from the famous inverse squareroot trick, but I didn't know it could be used for an arbitrary divisor. This is Bull :P – qwr – 2014-06-23T07:05:42.147

Yep, 0xAAAAAAAB = (2^33 + 1)/3 and 171 = (2^9 + 1)/3. I picked the smallest constant that does the trick. Hmm, actually it also seems to work with 86 = (2^8 + 2)/3 – aditsu quit because SE is EVIL – 2014-06-23T07:11:05.750

Rats, even 43 = (2^7 + 1)/3 works, not sure how I missed it. Edited now. – aditsu quit because SE is EVIL – 2014-06-23T07:16:39.830

4

C - 15 (?) tokens

int div3_m1(unsigned int n) {
    n = (n & 0xf) + (n >> 4);
    n = (n & 0x3) + (n >> 2);
    n = (n & 0x3) + (n >> 2);
    return n == 0 || n == 3;
}

Since 4 ≡ 1 (mod 3), we have 4n ≡ 1 (mod 3). The digit summing rule is not limited to summing the digits, but also allows us to arbitrarily break the number into sequences of digits and sum all of them up while maintaining the congruency.

An example in base 10, divisor = 9:

1234 ≡ 12 + 34 ≡ 1 + 2 + 3 + 4 ≡ 123 + 4 ≡ 1 (mod 9)

All statements in the program makes use of this property. It can actually be simplified to a loop that runs the statement n = (n & 0x3) + (n >> 2); until n < 4, since the statement simply breaks the number in base-4 at the least significant digit and add the 2 parts up.

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Posted 2014-06-23T03:20:09.733

Reputation: 5 683

+1: interestingly this works for n up to 512 (actually n = 590), but I'm not quite sure why. – Paul R – 2014-06-23T06:01:59.733

@PaulR: It won't work for bigger numbers due to carry (note that I used addition in the calculation). Also note the repeated lines. – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ – 2014-06-23T06:06:52.820

Yes, I'm just not sure why it works for 9 bit values, since it only seems to be testing 8 bits? – Paul R – 2014-06-23T06:16:49.993

for 9-bit numbers after the first addition it become at most 5 bits, after the first n = (n & 0x3) + (n >> 2); the result is reduced to 3 bits and the repetition caused it to remain only 2 bits http://stackoverflow.com/a/3421654/995714

– phuclv – 2014-06-23T06:50:30.573

1oh I've made a mistake. A 5-bit number + a 4-bit number can result in a 6-bit number. But if n <= 588 adding the top 4 bits and bottom 2 bits of that 6-bit number produce an only 4-bit sum. Again adding that results in a 2-bit number. 589 and 590 results in 3 bits in the last sum but incidentally they aren't divisible by 3 so the result is correct – phuclv – 2014-06-23T07:09:41.670

2

Python (2 tokens?)

1&66166908135609254527754848576393090201868562666080322308261476575950359794249L>>x

Or

1&0x9249249249249249249249249249249249249249249249249249249249249249L>>x

Or

1&0b1001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001>>x

ɐɔıʇǝɥʇuʎs

Posted 2014-06-23T03:20:09.733

Reputation: 4 449

2Duplicate of Howard's comment – aditsu quit because SE is EVIL – 2014-06-23T08:31:34.647

@aditsu ... Great minds think alike? I swear I didn't see that before I posted this. – ɐɔıʇǝɥʇuʎs – 2014-06-23T08:32:59.863

2

JavaScript - 3 tokens

function div3(n) {
    var a = n * 0.3333333333333333;
    return (a | 0) == a;
}

This abuses the fact that using bitwise operators on a number truncates it to an integer in JavaScript.

Tyilo

Posted 2014-06-23T03:20:09.733

Reputation: 1 372

Should be 4 tokens: =, *, |, == – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ – 2014-06-25T07:55:11.913

1I don't think variable assignment counts as a token. – Tyilo – 2014-06-26T19:22:28.660

1

C - 4 tokens

int div3(int x) {
    return ((x * 43) >> 7) * 3 == x;
}

Works up to 383.

Previous version (bigger constants):

int div3(int x) {
    return ((x * 171) >> 9) * 3 == x;
}

Works up to 1535

aditsu quit because SE is EVIL

Posted 2014-06-23T03:20:09.733

Reputation: 22 326

1

bash – ???

Not sure how to score this.

seq 0 85 | awk '{print $1 * 3}' | grep -w [number] | wc -l

e.g.

$ seq 0 85 | awk '{print $1 * 3}' | grep -w 11 | wc -l
0

$ seq 0 85 | awk '{print $1 * 3}' | grep -w 12 | wc -l
1

$seq 0 85 | awk '{print $1 * 3}' | grep -w 254 | wc -l
0

$seq 0 85 | awk '{print $1 * 3}' | grep -w 255 | wc -l
1

user15259

Posted 2014-06-23T03:20:09.733

Reputation:

1

Python 0

I posted eariler but I used conditionals. Here's to using no conditionals and no tokens, just keywords

def g(x): return ([[lambda : g(sum(int(y) for y in list(str(x)))),lambda: 0][[False,True].index(x in[0,1,2,4,5,7,8])], lambda: 1][[False,True].index((lambda y: y in[3,6,9])(x))])()

uses the trick that multiple of 3s have digits which add to 3

Edit: Removed unnecessary lambda

def g(x):return([[lambda: g(sum(int(y) for y in list(str(x)))),lambda:0][[False,True].index(x in[0,1,2,4,5,7,8])], lambda:1][[False,True].index(x in[3,6,9])])()

Edit: Golfed further (117 chars) still no tokens

exec"g=`x:(((`:g(sum(int(y)for y in str(x)),`:0)[x in[0,1,2,4,5,7,8]],`:1)[x in[3,6,9]])()".replace('`','lambda ')

Killed direct access for python's nifty getitem Longer at 132 char

exec"g={0}x:((({0}:g(sum(int(y)for y in str(x))),{0}:0{1}0,1,2,4,5,7,8]),{0}:1{1}3,6,9]))()".format('lambda ',').__getitem__(x in[')

http://www.codeskulptor.org/#user34_uUl7SwOBJb_0.py

Dylan Madisetti

Posted 2014-06-23T03:20:09.733

Reputation: 3 381

Array access [] is not allowed, though. – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ – 2014-06-25T07:56:39.613

It is? After these rules, http://codegolf.stackexchange.com/tags/atomic-code-golf/info

– Dylan Madisetti – 2014-06-25T13:21:08.613

Well, the question doesn't use the rule in the tag wiki. The question has restriction on operations allowed. Note the word only. – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ – 2014-06-25T14:43:59.703

@n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Well it's a good thing python has a native attribute for that too – Dylan Madisetti – 2014-06-25T16:04:29.037

1

Befunge 93 - 5 tokens

Fixed - division removed.

v      @._1.@
         \   
         0   
         +   
         3   
>&>3-:0\`|   
  ^      <   

Gets input, keeps subtracting 3 until it's smaller than 0, direct the pointer up ('|'), then adds 3. If the value is 0 then the pointer moves right ("1.@" outputs '1') else moves left ("@." outputs '0'). '@' terminates the program.

AndoDaan

Posted 2014-06-23T03:20:09.733

Reputation: 2 232

1

Ruby, 6(?) tokens

I'm really not sure how to count tokens. OP, can you score me?

I think it's 6... 1, 0, 0, *, 255, x

Note that the * is not integer multiplication.

def div3(x)
  ([1,0,0]*255)[x]
end

Not that Charles

Posted 2014-06-23T03:20:09.733

Reputation: 1 905

Wouldn't a token in the OP's sense be only one of the above listed in the question? – C5H8NNaO4 – 2014-06-23T22:25:36.640

@C5H8NNaO4 So what? 0? – Not that Charles – 2014-06-24T02:28:49.580

@C5H8NNaO4 maybe 4 for constants? – Not that Charles – 2014-06-24T03:15:17.040

1

Batch - 7 Tokens

I think

@echo off
for /L %%a in (0,3,%1) do set a=%%a
if %a%==%1 echo 1

Returns 1 if the given number (as stdin) is divisible by three.

unclemeat

Posted 2014-06-23T03:20:09.733

Reputation: 2 302

Are loops allowed? – sergiol – 2017-01-28T13:57:00.240

0

Tcl, 83 bytes

proc T n {while \$n>9 {set n [expr [join [split $n ""] +]]};expr {$n in {0 3 6 9}}}

Try it online!

sergiol

Posted 2014-06-23T03:20:09.733

Reputation: 3 055

Failed outgolf: 96 bytes proc T n {set n [expr [join [split [expr [join [split $n ""] +]] ""] +]];expr {$n in {0 3 6 9}}} Try it online!

– sergiol – 2018-04-10T14:38:30.657

Another fail:87 bytes proc T n {expr {[expr [join [split [expr [join [split $n ""] +]] ""] +]] in {0 3 6 9}}}

Try it online!

– sergiol – 2018-04-10T14:59:36.273

0

Python - 25 tokens

To get things started, I have a lengthy solution that is a implementation of one of the answers in the link in my first post. n is input.

a = (n>>7)-((n&64)>>6)+((n&32)>>5)-((n&16)>>4)+((n&8)>>3)-((n&4)>>2)+((n&2)>>1)-(n&1)
print(a==0 or a==3)

or is equivalent to ||.

qwr

Posted 2014-06-23T03:20:09.733

Reputation: 8 929

0

JavaScript - 3 Tokens

Test it on your browser's console:

a = prompt().split('');
sum = 0;

do {
  sum = a.reduce(function(p, c) {
     return parseInt(p) + parseInt(c); 
  });

  a = sum.toString().split('');

} while(a.length > 1)

alert([3, 6, 9].indexOf(+sum) > -1)

William Barbosa

Posted 2014-06-23T03:20:09.733

Reputation: 3 269

How did you come to that conclusion? I count about 37 tokens. – nyuszika7h – 2014-06-23T12:38:43.457

"A token is any of the above excluding constants and variables". How did you count 37? – William Barbosa – 2014-06-23T12:39:54.987

1Oh, I see. The OP seems to disagree with the info page of [tag:atomic-code-golf]. – nyuszika7h – 2014-06-23T12:42:56.433

Actually, now I'm not sure whether I'm right or not. My score would be 70+ according to the atomic code golf fiddle. – William Barbosa – 2014-06-23T12:46:08.383

1The problem is not about the number of tokens, but about what operations you're using. I don't think toString, parseInt, loops, arrays, etc. are allowed. – aditsu quit because SE is EVIL – 2014-06-23T13:55:51.427

0

JavaScript
not sure about the token#

function mod3 (i) { return {'undefined':'100','0':'0'}[[0][i]][i.toString (3).split('').pop ()]}

or if the output for 0 is allowed to be 1;

function mod3 (i) { return '100'[i.toString (3).split('').pop ()]}

C5H8NNaO4

Posted 2014-06-23T03:20:09.733

Reputation: 1 340

2I have to say, I'm not sure what rules apply to this challenge. Are functioncalls and propertyaccesses allowed? – C5H8NNaO4 – 2014-06-23T21:47:25.233