Calculate n % 12

27

3

Calculate n modulo 12 for an unsigned 32 bit integer.

The Rules:

  • Must work for all n between 0 and 23. Other numbers optional.
  • Must only use any of the operators +-*, ~&^| or <<, >> as commonly defined on 32 bit uints.
  • May use arbitrary number of constant uints.
  • May not use any form of pointers, including arrays, or any if statements, including things that compile to if statements such as ternary operators or "greater than" operators.

The scoring:

  • Operators + - and the bitwise operators ~ & ^ | << >> (NOT, AND, XOR, OR, bit shifts) give a score of 1, * gives a score of 2.
  • Lowest total score wins.

nbubis

Posted 2014-06-20T00:05:32.077

Reputation: 1 019

This question's score is currently equal to the highest number supported by many answers. – HyperNeutrino – 2017-05-03T05:49:49.107

6You might want to define the operators for users of languages other than C/Java. I understand +-* are add, subtract, multiply; ~&^| are bitwise NOT,AND,XOR,OR; and << >> are bitshifts. – Level River St – 2014-06-20T00:52:55.513

@steveverrill - thanks. That is indeed the intention. – nbubis – 2014-06-20T00:53:39.283

Can I use for i in x:y:z, .dostuff? – Οurous – 2014-06-20T01:43:42.720

Can I set a variable equal to a value to use in a expression? – xnor – 2014-06-20T02:42:46.193

@Ourous - not unless you want to count the for increments in the score. – nbubis – 2014-06-20T05:12:59.740

@xnor - you can use any uint32. – nbubis – 2014-06-20T05:13:32.387

4most compilers will optimize n % 12 to a multiplication and a shift like in hacker's delight, so this is trivial, just output the assembly and see – phuclv – 2014-06-20T06:42:46.357

Can I use -=? – Οurous – 2014-06-20T06:46:41.857

Can I use multiple lines and the assignment operator? – Thomas Weller – 2014-06-20T11:35:11.590

@Ourous I doubt that it helps. a -= b can be replaced with a = a - b which has no higher a score by the questions scoring system. – Cruncher – 2014-06-20T13:12:30.083

@LưuVĩnhPhúc http://stackoverflow.com/questions/8021772/assembly-language-how-to-do-modulo Apparently, they just use a builtin.

– isaacg – 2014-06-21T08:05:18.643

@isaacg they'll do it with multiply and shift like this, this, this or this instead of simple divisions like that

– phuclv – 2014-06-21T08:15:06.667

Would be better to just say "may not use ternary or comparison operators", rather than assuming that they actually compile to conditional branch instructions in the underlying assembly. – None – 2014-06-22T11:07:07.450

What if my language uses * as the modulo operator? – Braden Best – 2014-06-23T00:10:50.730

Answers

29

4

(Language is irrelevant)

n-((48&(11-n))>>2)

Woo! Got to 4.

11-n will ensure all of the high order bits are set if and only if n>= 12.

48&(11-n) == if n>11 then 48 else 0

(48&(11-n))>>2 == if n>11 then 12 else 0

n-((48&(11-n))>>2) is the answer

isaacg

Posted 2014-06-20T00:05:32.077

Reputation: 39 268

1Aww shucks, you beat me to this approach! I was only moments away from posting n - (((11 - n) & 0xC0000000) >> 28). Well done, I don't think it can be done in less than four. – Runer112 – 2014-06-20T03:01:38.183

1@Runner112 Yeah, I was hoping no one would beat me to it as I posted it. Well done on finding it for yourself, though – isaacg – 2014-06-20T03:03:21.950

1Awesome :) 4 is indeed an accomplishment. – nbubis – 2014-06-20T05:19:41.037

11

4

A solution with a lookup table (it looks up i ^ (i % 12)):

i ^ (0x1d4c000 >> (i & 0xfc) & 30)

4

Here's another solution with 4 operations:

i - ((0xffff >> (i - 12)) & 12)

It assumes that the count operand of bitshifts is implicitly taken mod 32, i.e. x >> -1 is the same as x >> 31.

5

Another approach, using a lookup table:

i - (16773120 >> i & 1) * 12

copy

Posted 2014-06-20T00:05:32.077

Reputation: 6 466

7

bash – 1

echo `seq 0 11` `seq 0 11` | awk '{print $(number+1)}'

e.g.

$ echo `seq 0 11` `seq 0 11` | awk '{print $(0+1)}'
0

$ echo `seq 0 11` `seq 0 11` | awk '{print $(11+1)}'
11

$ echo `seq 0 11` `seq 0 11` | awk '{print $(12+1)}'
0

$ echo `seq 0 11` `seq 0 11` | awk '{print $(23+1)}'
11

user15259

Posted 2014-06-20T00:05:32.077

Reputation:

1This isn't valid because it uses pointers. – curiousdannii – 2014-06-21T04:56:27.193

@curiousdannii What pointers are you referring to? The stdin and stdout streams? Sure, internally, they are pointers, but then we might as well disqualify Java because it uses the Integer class internally for a lot of things. – Cole Johnson – 2014-06-21T18:31:46.400

Isn't $() effectively equivalent to a pointer? – curiousdannii – 2014-06-21T23:32:36.937

@curiousdannii - awk documentation says they're built-in variables. – None – 2014-06-22T08:44:54.140

5

C, little-endian - 2

This is probably cheating but I think it satisfies the rules...

union {
    int i;
    struct {
        int a:4;
        int b:2;
        int c:10;
    } s;
    struct {
        int a:2;
        int b:14;
    } t;
} u;

u.i = 11-n;
u.s.a = 0;
u.s.c = 0;
result = n-u.t.b;

R.. GitHub STOP HELPING ICE

Posted 2014-06-20T00:05:32.077

Reputation: 191

How does it work? – nbubis – 2014-06-20T18:55:49.527

1Sorta cheating, since you're using = 0 instead of & 0x0, which should count as an additional 2 operations. But +1 for the creativity :) – nbubis – 2014-06-20T19:03:58.017

4

PHP - score 0

I wonder how is it possible that noone came with this before me!!!

$n = 18;
$s = str_repeat("a", $n);
$s2 = preg_replace('/aaaaaaaaaaaa/', '', $s);
echo strlen($s2);

Tomas

Posted 2014-06-20T00:05:32.077

Reputation: 2 333

1@seequ One could also argue that this invalid because of it's use of RAM (yes, at low level, ram is technically an indexed array) ¯_(ツ)_/¯ – Stan Strum – 2017-09-27T20:46:02.143

2Nice. I think there may be an issue though, since arrays are disallowed. Really nice though. – AJMansfield – 2014-06-22T02:03:01.703

@AJMansfield One could argue this doesn't have arrays but strings (yes, at low level strings are byte arrays). :) – seequ – 2014-06-22T17:24:12.853

2

C, score 5

Works up to 23, not guaranteed above that.

( ((n+4)>>2)&4 ) + n & 15

((n+4)>>2)&4 returns 4 for n>=12. Add it to n and you get the right answer in the least significant 4 bits, then truncate the other bits.

Level River St

Posted 2014-06-20T00:05:32.077

Reputation: 22 049

Well done!! Now let's see if someone can get to 4.. – nbubis – 2014-06-20T00:48:49.570

2

whatever language: 5

not going to win, but participating because fun and maybe because it's easier to understand then others:

n - ((n+20)>>5)*12

this is equivalent to

n - (n>11)*12

this is equivalent because when you add 20 to 12, you get 32, thus the 5th bit becomes 1. This is only when n > 1 as 32 is the smallest number where the 5th bit becomes 1.

also note that is easily expandable for a higher range, as you can do

n - ((n+20)>>5)*12 - ((n+41)>>5)*12

to reach a range until 35

Pinna_be

Posted 2014-06-20T00:05:32.077

Reputation: 144

1

C - 6

(n - (((n * 0xAAAB) >> 19)) * 12 )

nbubis

Posted 2014-06-20T00:05:32.077

Reputation: 1 019

This should either be part of the question or just another answer. I suggest the latter. – Jwosty – 2014-06-20T01:12:17.580

@Jwosty - changed. – nbubis – 2014-06-20T23:16:13.200

1

Python 2.x - 4

j=input();m=lambda a,b:a*b;a=(m(j,357913942)>>32);print j-m(12,a)

Is = an operator?

In that case the score is 6.

j-12*(j*357913942>>32)

BTW @steveverrill 's solution can be directly used in Python as well.

Works for the range 0 .. 23

So whats going on ? Multiply by 357913942 and divide by 2^32 (or right shift 32)

Willem

Posted 2014-06-20T00:05:32.077

Reputation: 1 528

I like how you used a function to multiplicate only once. but imho you just renamed multiplication to the function m(,), which for me means you used it twice. – Pinna_be – 2014-06-20T20:27:03.630

depends how the rules are interpreted, but you have a valid point – Willem – 2014-06-21T04:38:29.220

0

Kona - 5

Might be invalid because I'm not sure if the floor operator is allowed, but I've got two * and a minus:

mod:{x-(_0.08333*x)*12}

Which should work for any integer.

Kyle Kanos

Posted 2014-06-20T00:05:32.077

Reputation: 4 270

I'm not sure about the floor operation, but I'm definitely sure that the first multiplication is operating on something other than 32-bit integers. – Runer112 – 2014-06-20T02:37:22.257

@Runer112: OP says input must be 32 bit and operators are as defined they normally are with 32 bit uints; it says nothing about non-integer values in the code. – Kyle Kanos – 2014-06-20T02:42:01.330

Unless I'm misunderstanding something, 0.08333*x doesn't seem like multiplication as defined on 32-bit uints, because 0.08333 is not a 32-bit uint. – Runer112 – 2014-06-20T02:47:14.907

@Runer112: Actually, the way I read it is that &|~ >> << are as defined with 32 bit uints (as it doesn't really make sense to do 1.0 << 3, does it?). – Kyle Kanos – 2014-06-20T02:48:51.987

If you have to floor it, I know that, at least in JavaScript, n|0 is equivalent to a floor function – Isiah Meadows – 2014-06-20T04:33:45.153

1"May use arbitrary number of constant uints." - i.e. cannot use arbitrary floats. – nbubis – 2014-06-20T05:12:18.120

1@nbubis: that line does not actually put a restriction on floats. – Kyle Kanos – 2014-06-20T10:29:36.467

0

Cobra - 2 (or 3)

def modulo12(n as uint32) as uint32
        for i in 11:n to int64:12,n-=12
        return n

This might be bending the rules a bit, but I've asked and was allowed to use this.

It also works for any number.

Οurous

Posted 2014-06-20T00:05:32.077

Reputation: 7 916