Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Saturday, July 16, 2016

Finding out what numbers have been added to come up with a sum

Finding out what numbers have been added to come up with a sum


Sorry for the title. I wasn't sure how to ask this question.

I have a form on a website that asks a question. The answers are in check box form. Each answer is saved into my database with a 'score', the values look like this:

Allergy 1  Cardiology  2  Chest Disease   4  Dermatology 8  Emergency Room  16  Ambulance Trips 32  Gastroenterology    64  General Medicine    128  Gynecology  256  Hematology  512  Neurology   1024  Obstetrics  2048  Opthamology 4096  Orthopedics 8192  Physical Therapy    16384  Plastic Surgery 32768  Podiatry    65536  Proctology  131072  Psychiatry  262144  Surgery Performed   524288  Thoracic Surgery    1048576  Urology 2097152  Outside X-Rays  4194304  Diagnostic Tests (outside)  8388608  

As you can see, the score is the previous value times two. When a user fills out the form, the answer is saved in the database as one value - all the answers added together.

For example, a user selected the values: Allergy, General Medicine, Hematology, Obstetrics. In the database, the answer for this question is saved as 2689.

Is there a way to figure out what answers have been selected by only having the answer to the question?

For example, I would query my database and pull the 2689 value, and I need to determine what answers were checked.

edit: I was hoping to reverse engineer the answer in PHP.

Answer by Mikeb for Finding out what numbers have been added to come up with a sum


Remember that integers are stored in binary - so each of these flags (Allergy = 1) etc. will correspond to a single bit being true or false in the binary representation of the sum.

For example, 2689 in binary is 0000 1010 1000 0001 which, if you think of it as an array of bits, where the least significant bit (right most in that array) is the least significant flag (allergy) then we can easily see that the first (allergy), eighth (gen. medicine), tenth (hematology) and twelfth (obs) slots of the array are marked with a 1 for true.

The largest value in your array of flags is 24th bit in a 32 bit integer. You could define up to 8 more flags in this system before having to use a larger integer.

Answer by Fred Foo for Finding out what numbers have been added to come up with a sum


Yes, there is. Note that each k'th "score" is of the form 2^(k - 1), which corresponds to a bitstring with only the k'th bit set. If you know which bits are set, you can reconstruct the sum.

Taking 2689 as an example, we first need to write it out in binary:

2689 = 101010000001b  

Counting from the right, we see that the first, eighth, tenth and twelfth bits are set, so (as you can verify)

2689 = 2^0 + 2^7 + 2^9 + 2^11       = 1 + 128 + 512 + 2048  

The actual implementation of this can be done efficiently using bitwise operations. By taking the AND of the value and each of the "scores" in turn, then checking whether that gives a non-zero value, we can check which scores went into the sum.

Answer by David Z for Finding out what numbers have been added to come up with a sum


Yes, this is a common pattern called bit masking. Use your language's binary AND operator on the value corresponding to a given answer and the value submitted from the form to see if the given answer was one of the selected choices. For example, if the answer submitted and saved is 2689 as in your example, you can check whether "chest disease" was one of the selected choices by seeing if 2689 & 4 is nonzero. (& should be substituted with whatever the binary AND operator is in your language of choice.)

Note that this only works as long as all the values corresponding to individual choices are powers of 2. In general, the question posed in your title, about finding out what numbers from a given set have been added to come up with a given sum, is an instance of something called the knapsack problem and is only known to be solvable by checking every possible combination, which is very inefficient. (NP-complete, specifically)

Answer by atk for Finding out what numbers have been added to come up with a sum


Since all your numbers seem to be powers of two, you just need to store the input value in a long enough integer to hold it, then bit mask.

if( value & 1 ) then 1 was part of the selection  if( value & 2 ) then 2 was part of the selection  if( value & 3 ) then 3 was part of the selection  and so on  

Answer by SpacedMonkey for Finding out what numbers have been added to come up with a sum


You can find the values by ANDing with powers of 2.

20 = 1
21 = 2
22 = 4
23 = 8
...
223 = 8388608

You can find out the value of 2n using binary shifting like this: 1 << n

php like code:

$item[] = {"Allergy", "Cardiology", ..., "Diagnostic Tests (outside)"};  $answer = 2689;    for ( $power = 0; $power < count($item); $power++ ) {       if ( 1 << $power & $answer ) {         echo $item[$power] . "\n";     }  }  

Edit: made it more php friendly

Answer by User_allowed for Finding out what numbers have been added to come up with a sum


this will do exactly what you wanted :

  

Happy coding


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.