0

I recently had a C# technical assessment for a job application where one of the questions was:

Question 11: Implement the function int Mult27(int a) such that it returns the result of a multiplied by 27. Do so using only the following functions (provided):

  • SHL(a,b) shifts all the bits of integer a left by b places.
  • ADD(a,b) adds two integers giving a+b.
  • SUB(a, b) subtracts two integers to give a-b.
  • Do so using as few calls to these functions as possible, assume a is always a positive integer.

    public class AnswerEleven
    {
        int SHL(int a, int b)
        {
            return a << b;
        }
    
        int ADD(int a, int b)
        {
            return a + b;
        }
    
        int SUB(int a, int b)
        {
            return a - b;
        }
    
        public int Mult27(int a)
        {
    
        }
    }
    

I'm pretty sure I wasn't allowed to use operators like %, and I couldn't use string conversions or other types. I couldn't think of how to do it other than bit shifting to the left to get the power of 2 (which only solves by powers of 2) or using division by two and the subtraction method (which doesn't help). But it seems like there may be multiple ways to solve the problem.

I ended up submitting without being able to finish the problem and it's been bothering me that I can't find an answer without using a typical but not allowed method. Any ideas?

phuclv
  • 37,963
  • 15
  • 156
  • 475
evm87
  • 13
  • 1
  • 1
    Like: * 32 - 5 ? (`return SHL(a , 5) - SHL(a, 2) - a;` or `return SUB(SUB (SHL(a , 5), SHL(a, 2)), a);`) which has only __four__ calls. – TaW Jul 22 '18 at 11:23
  • Hint: you can multiply by 6, by multiplying by 4 and 2, and adding the results (4a+2a = 6a). Or by using 8a-2a=6a – Hans Kesting Jul 22 '18 at 11:36
  • note that `*32 - 5` will overflow if the input is large – phuclv Aug 10 '18 at 06:40

3 Answers3

4

Deconstructing integers into powers of 2 can be done in various ways. Here is a simple one:

27x = 32x - 5x = 32x - 4x - x

Hence you can write

public int Mult27(int a)
{
    return SUB(SUB(SHL(a, 5), SHL(a, 2)), a);
}

This uses only four calls to your allowed functions. Hard to top I believe..

TaW
  • 53,122
  • 8
  • 69
  • 111
  • Ahh I see, seems so obvious now. Using bit shifting to get 32*x, then subtracting 5x after bit shifting again. At least now I know for next time. Thanks! – evm87 Jul 22 '18 at 15:39
  • 2
    Four calls is optimal, but the only proof I have is exhaustive enumeration – harold Jul 22 '18 at 16:33
2

How about this:

public int Mult27(int a)
{
    return ADD(ADD(SHL(a, 4), SHL(a, 3)), SUB(SHL(a, 2), a));
}

var ae = new AnswerEleven();
Console.WriteLine(ae.Mult27(1));
Console.WriteLine(ae.Mult27(2));

That gives 27 and 54.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • 1
    That for us ignorants is equivalent to doing `((a * 16) + (a * 8)) + ((a * 4) - a)` – xanatos Jul 22 '18 at 11:34
  • Ah right, breaking 27 into multiples of the power of 2 to get a*28, then subtracting the one last value of a. Very helpful, thank you! – evm87 Jul 22 '18 at 15:41
0
public int Mult27(int a)
{
    a = ADD(a, SHL(a, 1));    // or SUB(SHL(a, 2), a) → a = 3a
    return ADD(a, SHL(a, 3)); // 3a + 8*3a = 27a
}

This has the nice property that it avoids the overflow when shifting by 5 like when expanding 27x = 32x - 5x

Here's an alternate version that also uses 4 calls

int a4 = SHL(a, 2);                 // a4 = a*4
return SUB(SUB(SHL(a4, 3), a4), a); // a4*8 - a4 - a
phuclv
  • 37,963
  • 15
  • 156
  • 475