确定整数是否可被3整除


20

您的目标是确定数字是否可被3整除而不使用条件句。输入将是一个从0到255的无符号8位数字。鼓励创新!

您只能使用

  • 平等/不等式(==!=><>=<=

  • 算术(+-x

  • 逻辑运算符(!非,&&和,|| 或)

  • 位运算符(~未,&和,|或,^异或,<<>>>>>算术和逻辑左和右移位)

  • 常量(如果保持较小的值会更好)

  • 变量分配

0如果为假,1则输出,如果为真。

适用标准原子代码高尔夫球规则。如有任何疑问,请在评论中保留。示例方法在这里。令牌是以上任何一种,但不包括常量和变量。


@GregHewgill我的错字,应该是8位数字。
qwr 2014年

2
我们只允许使用上述运算符吗?否则,取模将使这种方法太容易。
Jwosty 2014年

另外,表查找又如何呢?
Greg Hewgill 2014年

3
您可以无条件澄清您的意思吗?它仅限于IF语句,还是也适用于循环之类的东西?
Ruslan 2014年

1
@Ruslan仅允许使用上述内容。
qwr

Answers:


31

C-2个代币

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

似乎可以达到2 31 -1。

归功于zalgo("nhahtdh")乘法逆思想。


1
+1。对<=工作原理有些困惑,并记得0xAAAAAAAB是unsigned int类型的,因此乘法的结果是无符号的。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 2014年

@DigitalTrauma不平等运营商是允许的,不被禁止的
aditsu

@aditsu糟糕!有时我需要更仔细地阅读!+1好答案!
Digital Trauma 2014年

@aditsu,对不起,我是菜鸟,这是如何工作的?
Kartik_Koro 2014年

2
@Kartik_Koro 0xAAAAAAAB * 3 == 1由于溢出,所以对于任何int x,x * 0xAAAAAAAB * 3 == x。另外,对于不同的y,y * 3具有不同的值,因此y = x * 0xAAAAAAAB必须是唯一的y,以使y * 3 == x。如果x是3的倍数,则y必须是x / 3,否则它必须通过溢出工作。一种简单的检查方法是将y与x进行比较。另请参见en.wikipedia.org/wiki/Modular_multiplicative_inverse
aditsu

17

Python,3 2个令牌

蛮力解决方案,但它可行。

0x9249249249249249249249249249249249249249249249249249249249249249>>x&1

感谢Howard减少了1个代币。


哇!您的解决方案可能是最短的(3个令牌),但是我也想鼓励其他答案。
qwr 2014年

11
甚至还有2种令牌解决方案:0x9......>>x&1
2014年

6

C- 5 4(?)令牌

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

适用于任何无符号的32位数字

该代码利用除数的乘法逆模2 32将除法运算转换为乘法运算。

编辑

我的解决方案(发布2分钟后)与aittsu的解决方案具有相同的精神。归功于他的使用==,我的解决方案提高了1个令牌。

参考


1
这难以置信。我从著名的反平方根技巧中知道魔术数字,但是我不知道它可以用于任意除数。这是Bull:P
qwr

是的,0xAAAAAAAB =(2 ^ 33 +1)/ 3和171 =(2 ^ 9 +1)/ 3。我选择了能解决问题的最小常量。嗯,实际上它似乎也适用于86 =(2 ^ 8 + 2)/ 3
aditsu

老鼠,即使43 =(2 ^ 7 +1)/ 3也可以,但不确定我是如何错过的。现在编辑。
2014年

4

C-15(?)令牌

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;
}

由于4≡1(MOD 3),我们有4 Ñ ≡1(模3)。数字求和规则不仅限于对数字求和,还允许我们在保持全等的同时将数字任意分解为数字序列并求和所有数字。

以10为底的示例,除数= 9:

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

程序中的所有语句都使用此属性。实际上,可以将其简化为运行语句n = (n & 0x3) + (n >> 2);直到的循环n < 4,因为该语句只是将base-4中的数字在最低有效位处中断,然后将2个部分加起来。


+1: interestingly this works for n up to 512 (actually n = 590), but I'm not quite sure why.
Paul R

@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̷̰̀ĥ̷̳

Yes, I'm just not sure why it works for 9 bit values, since it only seems to be testing 8 bits?
Paul R

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 stackoverflow.com/a/3421654/995714
phuclv

1
oh 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

2

Python (2 tokens?)

1&66166908135609254527754848576393090201868562666080322308261476575950359794249L>>x

Or

1&0x9249249249249249249249249249249249249249249249249249249249249249L>>x

Or

1&0b1001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001>>x

2
Duplicate of Howard's comment
aditsu

@aditsu ... Great minds think alike? I swear I didn't see that before I posted this.
ɐɔıʇǝɥʇuʎs

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.


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

1
I don't think variable assignment counts as a token.
Tyilo

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


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

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.


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.


Are loops allowed?
sergiol

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

Wouldn't a token in the OP's sense be only one of the above listed in the question?
C5H8NNaO4

@C5H8NNaO4 So what? 0?
Not that Charles

@C5H8NNaO4 maybe 4 for constants?
Not that Charles

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


Array access [] is not allowed, though.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳


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̷̰̀ĥ̷̳

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

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 ||.


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)

How did you come to that conclusion? I count about 37 tokens.
nyuszika7h

"A token is any of the above excluding constants and variables". How did you count 37?
William Barbosa

1
Oh, I see. The OP seems to disagree with the info page of atomic-code-golf.
nyuszika7h

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

1
The 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

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 ()]}


2
I have to say, I'm not sure what rules apply to this challenge. Are functioncalls and propertyaccesses allowed?
C5H8NNaO4

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!


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

Another fail:**87 bytes** proc T n {expr {[expr [join [split [expr [join [split $n ""] +]] ""] +]] in {0 3 6 9}}} Try it online!
sergiol
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.