1

Given an array A, its binarian(A) is defined as 2^A[0] + 2^A[1] + .... 2^A[n]; Questions asks to find anther shortest array B whose binarian(B) is same as A's.

For example, A=[1,0,2,0,0,2],thus if B=[3,2,0], this satisfies the requirements, and the output is 3.

Could you guys provide some ideas of how to solve this problem? Thanks.

Diego
  • 216
  • 1
  • 11
Jason
  • 39
  • 8
  • 2
    Count the number of '1' bits in the binary form of `binarian(A)`? If you need to actually generate `B`, its elements are the positions (rightmost being zero) of those `1` bits. – jasonharper Oct 16 '19 at 15:34
  • Thanks for commenting; at this point, I am not familiar with how to simulate the binary addition to count the "1" bits as you mentioned. Would you please provide more details? Thanks. – Jason Oct 16 '19 at 15:48
  • Why do you think you need to "simulate" anything? In Python, you'd just write `bin(binarian(A)).count('1')` (assuming that you've implemented `binarian()` already). Or is the requirement to find the answer without ever explicitly calculating `binarian(A)`? That's a bit more work: repeatedly find pairs of numbers `N` in `A`, and replace them with a single instance of `N+1`, until there are no such pairs remaining. – jasonharper Oct 16 '19 at 15:53
  • When asking about homework (1) **Be aware of your school policy**: asking here for help may constitute cheating. (2) Specify that the question is homework. (3) **Make a good faith attempt** to solve the problem yourself first (include your code in your question). (4) **Ask about a specific problem** with your existing implementation; see [Minimal, complete, verifiable example](https://stackoverflow.com/help/minimal-reproducible-example). Also, [here](https://meta.stackoverflow.com/questions/334822/how-do-i-ask-and-answer-homework-questions) is guidance on asking homework questions. – Prune Oct 16 '19 at 16:21
  • @jasonharper Thanks! I understood your way. – Jason Oct 16 '19 at 18:09
  • @Prune Wrong direction. This is actually an interview question I got stuck on. – Jason Oct 16 '19 at 18:10

5 Answers5

3

Here's a solution we add the power of 2 doing the carry propagation by hand. It can handle stupidly big inputs like A=[1000000000, 1000000000, 1000000001].

def shortest_equivalent_binarian(A): 
   s = set() 
   for a in A: 
       while a in s: # carry propagation
           s.remove(a) 
           a += 1 
       s.add(a) 
   return sorted(s, reverse=True)
# reverse is not necessary for correctness, but gives the same B as in your example
One Lyner
  • 1,964
  • 1
  • 6
  • 8
  • Thanks. In Python, I think I would just use its own module: bin(binarian), and like what jasonharper suggested, we can count the "1"'s occurrence. But I think your way shows more algorithmic detail. – Jason Oct 16 '19 at 18:21
  • The point here is *not to compute* the value of `binarian(A)`, as it would be too big for the `A` I give as an example. – One Lyner Oct 17 '19 at 08:08
1

Without outright answering what sounds like an assignment question, i'll just point out that any time you have a pair of 2x you can replace it with a single 2x+1... As for the actual algorithm since you don't need to care about the order of the members of A you should put them all into a bag/multiset structure and go from there as you build B.

norlesh
  • 1,749
  • 11
  • 23
1

This is my solution in PHP

function solution($a){
    // write your code in PHP7.0
    $binarian = 0;
    foreach ($a as $val){
        $binarian += pow(2, $val);
    }

    $b = [];
    while($binarian > 0){
        $el = intval(log($binarian, 2));
        array_push($b, $el);
        $binarian -= pow(2, $el);
    }
    
    return $b;
    
}
Zaman
  • 117
  • 1
  • 2
  • 10
0
# find the binarian
binarian = sum(2**a for a in A)
# find the powers of two that are present in A
# We do this by making a list of which bits are True in the binarian.
#   we check each bit, using len(bin()) to as an easy log2
#   we only include powers of two that produce 1 when and'ed with the binarian
B = [pwr for pwr in range(len(bin(binarian)) - 2) if (2**pwr & binarian)]

There's no way more efficient to construct a number out of powers of two, then to simply list which bits are flipped. This is what that does. It scans through bits from least-significant to most-significant, and only outputs if the bit is flipped.

This produces an ascending list (e.g. [0, 2, 3]. If you want a descending list (e.g. [3, 2, 0], you can wrap the range() call in reversed().

Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
  • This is not very efficient for [1000000000, 1000000000, 100000001...] – Matt Timmermans Oct 16 '19 at 16:17
  • @MattTimmermans My python has trouble even calculating 2**1000000000 - since this solution relies on actually *calculating* the binarian, of course it's going to have trouble with very large, difficult-to-calculate, numbers. The other answer is a strictly mathematical answer, this is a mechanical/arithmetic-based answer. – Green Cloak Guy Oct 16 '19 at 16:25
0

That's how I have solved this in Javascript

  function solution(A) {
    let binarian = 0;
    // only positive values
    A = A.filter((x) => x > -1);
    // get the total of the binarian
    for (let i = 0; i < A.length; i++) {
      binarian += Math.pow(2, A[i]);
    }
    // time to prepare your own binarian the shortest one!
    let b = [];
    while (binarian > 0) {
      let element = parseInt(Math.log2(binarian), 10);
      b.push(element);
      binarian -= Math.pow(2, element);
    }
    return b.length;
  }
Mr. Pyramid
  • 3,855
  • 5
  • 32
  • 56
  • this is amazing. can you briefly explain how this works? @Mr. Pyramid –  Sep 30 '22 at 06:58