Compare the digits of two integers in each decimal position - mysql

I am not sure I am describing the problem using the correct terms, my math English is not that good.
What I need to do is check if they match for each digit of two integers based on the position of the digit: ones, tens, .. etc
For example check the following table of different numbers and the wanted comparison result:
number1 | number2 | desired result
-----------------------------------
100 | 101 | 001
443 | 143 | 300
7001 | 8000 | 1001
6001 | 8000 | 2001
19 | 09 | 10
Basically I need the absolute value of subtraction for each digit alone. So for the first example:
1 0 0
1 0 1 -
--------
0 0 1
And second:
4 4 3
1 4 3 -
-------
3 0 0
And third:
7 0 0 1
8 0 0 0 -
---------
1 0 0 1
This needs to be done in mysql. Any ideas please?

This should do the job if your numbers are below 10000.
If they exceed, simply modify the query ;)
SELECT number1,
number2,
REVERSE(CONCAT(ABS(SUBSTRING(REVERSE(number1), 1, 1) - SUBSTRING(REVERSE(number2), 1, 1)),
IF(CHAR_LENGTH(number1) > 1, ABS(SUBSTRING(REVERSE(number1), 2, 1) - SUBSTRING(REVERSE(number2), 2, 1)), ''),
IF(CHAR_LENGTH(number1) > 2, ABS(SUBSTRING(REVERSE(number1), 3, 1) - SUBSTRING(REVERSE(number2), 3, 1)), ''),
IF(CHAR_LENGTH(number1) > 3, ABS(SUBSTRING(REVERSE(number1), 4, 1) - SUBSTRING(REVERSE(number2), 4, 1)), ''))) as `desired result`
FROM numbers
for 3 digit numbers:
SELECT number1,
number2,
CONCAT(
ABS(SUBSTRING(number1, 1, 1) - SUBSTRING(number2, 1,1)),
ABS(SUBSTRING(number1, 2, 1) - SUBSTRING(number2, 2,1)),
ABS(SUBSTRING(number1, 3, 1) - SUBSTRING(number2, 3,1))
)
FROM numbers
actually you don't have reverse the string at all. this comes from a more mathematical approach I tried before ;)

if you want to do it with integers only, it can be done this way (for 5 digits as an example):
select abs(number1/10000 - number2/10000) * 10000 +
abs(number1/1000 % 10 - number2/100 % 10) * 1000 +
abs(number1/100 % 10 - number2/100 % 10) * 100 +
abs(number1/10 % 10 - number2/10 % 10) * 10 +
abs(number1 % 10 - number2 % 10)

Related

Good explanation on why x-1 "looks" the way it does in binary

Let's take the number 28 in binary:
0b11100 # 28
If we subtract 1 from the number it looks like this:
0b11011 # 27
How I would explain how it 'looks' is that when subtracting 1 from a number, the right-most 1-bit is set to zero and all zeros after it are set to one. For example:
0b10101 - 1
= 0b10100
0b01000 - 1
= 0b00111
0b10000000 - 1
= 0b01111111
What would be the best explanation as to why this occurs though? I'm sure it's a property of binary twos complement, but I'm trying to figure out the best way to explain this to myself so that I can gain a deeper understanding of it.
Binary numbers have general form of N = dn x b^n + dn-1 x b^n-1… d1 x b^1 + d0 x b^0 where b is a base (2), d is a digit < base (0, 1) and n is position.
We write down binary numbers without b (because we know that's always 2) and also without its n exponent which goes implicitly from 0 for least significant digit (rightmost), 1 next to rightmost, etc.
For example your number 28 is 1x 2^4 + 1x 2^3 + 1x 2^2 + 0x 2^1 + 0x 2^0 = 1x 16 + 1x 8 + 1x 4 + 0x 2 + 0x 1 .
In binary:
1 - 1 = 0
0 - 1 = 1 and you carry that - 1 to the next position on left (same as when you do 10 - 1 in decimal, 0 - 1 is 9 and carry - 1 to order of tenths)
When subtracting 1 you go from the rightmost position, if there's 0 you turn it to 1 and carry subtraction up to next (left) position (and that chains all the way left until you find position where you can subtract without affecting higher position)
0b01000 - 1 can be written as 0x 2^4 + 1x 2^3 + 0x 2^2 + 0x 2^1 + 0x 2^0 - 1 x 2^0. In plain decimal that is 8 - 1 = 7 and 7 in binary is 0x 2^4 + 0x 2^3 + 1x 2^2 + 1x 2^1 + 1x 2^0 (4 + 2 + 1)
It does not matter what base you are in, the math does not change:
1000
- 0001
========
This is base 10, easier to see:
1 0 0 0
- 0 0 0 1
=============
We start in the ones column (base to the power 0), the top number is smaller than the bottom so we have to borrow, but what we find is that next column does not have anything and so on so we have to work over until we can borrow something, that value is base larger than the column it is in so if you borrow from the hundreds column into the tens column that is 10 tens so:
So first borrow:
0 10 0 0
- 0 0 0 1
=============
Second borrow:
0 9 10 0
- 0 0 0 1
=============
Third borrow:
0 9 9 10
- 0 0 0 1
=============
And now we can work the base to the power one column:
0 9 9 10
- 0 0 0 1
=============
9
And in this case can easily finish it up:
0 9 9 10
- 0 0 0 1
=============
0 9 9 9
So base 5:
1 0 0 0
- 0 0 0 1
===================
0 5 0 0
- 0 0 0 1
===================
0 4 5 0
- 0 0 0 1
===================
0 4 4 5
- 0 0 0 1
===================
0 4 4 5
- 0 0 0 1
===================
0 4 4 4
And base 2:
1 0 0 0
- 0 0 0 0
==============
0 10 0 0
- 0 0 0 0
==============
0 1 10 0
- 0 0 0 0
==============
0 1 1 10
- 0 0 0 0
==============
0 1 1 10
- 0 0 0 0
==============
0 1 1 1
Twos complement comes into play when you actually implement this in logic, we know from elementary programming classes that when we talk about "twos complement" we learn to "invert and add one" to negate a number. And we know from grade school math that x - y = x + (-y) so:
0
1000
- 0001
=======
This is the same as:
1 <--- add one
1000
+ 1110 <--- invert
=======
Finish:
10001
1000
+ 1110
=======
0111
So for subtraction you invert/ones complement the second operand and the carry in and feed these to an adder. Some architectures invert the carry out and call it a borrow, some just leave it unmodified. When doing it this way as we see above the carry out is a 1 if there was NO borrow. It is a zero if there was a borrow.
I believe this is a base 2 thing only due to having only zero or one. How do you invert a base 10 number? 1000 - 1 = 1000 + 9998 + 1, hmm actually that works.
So base 10 100 - 1 = 99, base 9 100 - 1 = 88, base 8 (octal) 100 - 1 = 77, base 7 100 - 1 = 66 and so on.

getting Sum Floor and Group by to work

Ok all i have a question about sum and group by what i have currently is a error and i don't know how to fix basically the error is in regards to this line of code
SELECT PlayerName
,floor(SUM(PlayerScore / 500)) + floor(SUM(PPlayerScore / 1000)) + floor(SUM(S4 / 5)) * 2 + floor(Sum(P7 / 3)) * 2 + SUM(prereg) + SUM(st) + SUM(hb) AS BB
,floor(SUM(PlayerScore / 500)) + floor(SUM(PPlayerScore / 1000)) + floor(SUM(S4 / 5)) * 2 + floor(Sum(P7 / 3)) * 2 + SUM(PlayerBallots) + SUM(prereg) + SUM(st) + SUM(hb) AS TB
,SUM(PlayerBallots) AS PB
FROM player
the same issue is throughout the line and it is this
from this floor sum command
if 4 players have scores of 1100 1300 1800 and 1000 the sum of that will show 5 when the reality is it should only show 4 i tried adding in a group by operator it will only show the total for 1 player
is it possible to do what I'm trying or not
thank you in advance
To help a little i will shorten down the code and explain what i need it to do with an example
floor(SUM(PPlayerScore /1000))
so for each 1000 points a player scores he gets 1 ballot
so if
jane has 1100 gets 1 ballot floor 1.1
joe gets 1300 gets 1 ballot floor of 1.3
jerry gets 1800 1 ballot floor of 1.8
jane gets 1000 gets 1 ballot floor of 1
the issue is with current code i get 5 when in reality there is only 4 ballots

MySQL: Count days within a given range excluding weekends, include start and end if they are weekdays

I know this has been answered in some posts but my requirement is rather different.
What I want is to count all weekdays within range which will include start date and end date. For example:
#s = 2017-05-15, #e = 2017-05-30
using this query (which i found on here):
5 * (DATEDIFF(#E, #S) DIV 7) + MID('0123444401233334012222340111123400001234000123440', 7 * WEEKDAY(#S) + WEEKDAY(#E) + 1, 1)
this returns 11 but what I expect is 12:
[15, 16, 17, 18, 19, 22, 23, 24, 25, 26, 29, 30]
maybe either start or end date is not counted?
Anyone have an idea?
So for my requirement, this should be the matrix:
| M T W T F S S
-|--------------
M| 1 2 3 4 5 5 5
T| 5 1 2 3 4 4 4
W| 4 5 1 2 3 3 3
T| 3 4 5 1 2 2 2
F| 2 3 4 5 1 1 1
S| 1 2 3 4 5 0 0
S| 1 2 3 4 5 5 0
which translate into this string:
1234555512344445123333451222234511112345001234550
Finally, this query solves my problem:
SET #s = STR_TO_DATE('2017-5-01', '%Y-%m-%d');
SET #e = STR_TO_DATE('2017-5-31', '%Y-%m-%d');
SET #weekDays = 5 * (DATEDIFF(#e, #s) DIV 7) + MID('1234555512344445123333451222234511112345001234550', 7 * WEEKDAY(#s) + WEEKDAY(#e) + 1, 1);
This gives me correct result, which is count all weekdays from start date (#s) tp end date (#e).
Hope someone would find this helpful in the future.

Add 25 & 30 as binary number

Using 8 bit registers and signed magnitude representation.
I thought 25 in BCD is 010 0101 but my text book says it as 001 1001. Can somebody explain?
25 / 2 = 12r1 (12 with a remainder of 1)
12 / 2 = 6r0 (6 with a remainder of 0)
6 / 2 = 3r0 (3 with a remainder of 0)
3 / 2 = 1r1 (1 with a remainder of 0)
1 / 2 = 0r1 (0 with a remainder of 0)
So 11001 (working backward up the tree) is the binary equivalent to 25.
Another way to think about it is with powers of 2:
(1*16) + (1*8) + (0*4) + (0*2) + (1*1) = 25
And it's worth noting, just as in base 10, leading zeros do not change the value of a number. (00025 == 25) (0011001 == 11001).
The leading zeros are there in your case because your needing to populate an 8 bit register (there needs to be 8 binary digits regardless of their value).

Finding matches between 30,000+ data sets

For simplicity sake, lets use a case example of 3 colors with corresponding numbers (there is actually 30,000+ different 'colors' and 254 different 'numbers' in real life though)
Red - 0, 1, 2, 3, 10, 15
Green - 0, 2, 3, 20
Blue - 2, 10, 11, 12
I want to find the matches between them (rgb, rg, rb), as well as keep a tally of the number of #s shared between the set:
rgb = 1
rg = 2
rb = 2
Finally it'll need to determine a ratio of the number of #s shared compared to the number of distinct #s in the set.
rgb = 1/9 (since it has a distinct: 0, 1, 2, 3, 10, 11, 12, 15, 20)
rg = 2/7 (0, 1, 2, 3, 10, 15, 20)
rb = 2/8 (0, 1, 2, 3, 10, 11, 12, 15)
So the total output would be
match | # of matches | % |
rgb | 1 | 1/9
rg | 2 | 2/7
rb | 2 | 2/8
The algorithm I was able to come up w/is you have each color in a table and map the numbers associated with it (aka red (table Name), 0, 1, 2, 3, 10, 15 (data)). Then take the color with the most 'numbers' and compare it to every other color's hours, find matches. Once done with that color you can 100% ignore it and move onto the next color and do comparisons with n-1.
Take the example:
1) Select red
2) Does any other color share 0
3) Does any other color share 1
....etc
4) Select blue
5) Does any other color minus red share .....
I know that there has to be a more efficient way to do this, any suggestions?
Thanks for the help.
As there are only 254 (or 255 if your 0-254 comment is correct), then you can express the sets of 'numbers' for each 'colour' as a 256-bit integer. Then the number of shared numbers for r and g is just the bitcount of (r and b) and the number of distinct numbers is the bitcount of (r or b), so using your example,
if R is the bit-set for red, G is the bitset for B etc:
match | # of matches | % |
rgb | bitcount(R and G and B) | bitcount(R and G and B)/bitcount(R or G or B) |
rg | bitcount(R and G) | bitcount(R and G)/bitcount(R or G) |
rb | bitcount(R and B) | bitcount(R and B)/bitcount(R or B) |