I'm trying to write a MergeSort function that splits the array into 4 arrays and not into 2 like the regular MergeSort..
I tried to follow the 2-way mergeSort and implement it to the 4-way but I keep getting stuck in recursive calls and I can't understand where's the problem..
I wrote a merge_sort_4 function that calls itself 4 times and merge4 function that should merge 4 arrays and not 2.
I know some people in my class solved it with 3 calls to the regular Merge function but I think it kinda misses the point of this challenge..
If the only way of solving it is by using the regular Merge please tell me, if not, please help me find the problem
Here's my code
def merge_sort_4(lst, start, end):
if start < end:
quarter1 = (start + end) // 4
quarter2 = (start + end) // 2
quarter3 = (end - quarter1 - 1)
merge_sort_4(lst, start, quarter1)
merge_sort_4(lst, quarter1 + 1, quarter2)
merge_sort_4(lst, quarter2 + 1, quarter3)
merge_sort_4(lst, quarter3 + 1, end)
merge4(lst, start, quarter1, quarter2, quarter3, end)
def merge4(lst, start, q1, q2, q3, end):
first_q_list = lst[start:q1 + 1]
sec_q_list = lst[q1 + 1:q2 + 1]
third_q_list = lst[q2 + 1:q3 + 1]
last_q_list = lst[q3 + 1:end + 1]
first_q_list.append(float('inf'))
sec_q_list.append(float('inf'))
third_q_list.append(float('inf'))
last_q_list.append(float('inf'))
i = 0 # first sublist index
j = 0 # sec sublist index
m = 0 # third sublist index
n = 0 # last sublist index
for k in range(start, end + 1):
if first_q_list[i] <= sec_q_list[j] and first_q_list[i] <= third_q_list[m] and first_q_list[i] <= last_q_list[
n]:
lst[k] = first_q_list[i]
i += 1
elif sec_q_list[j] <= third_q_list[m] and sec_q_list[j] <= last_q_list[n]:
lst[k] = sec_q_list[j]
j += 1
elif third_q_list[m] <= last_q_list[n]:
lst[k] = third_q_list[m]
m += 1
else:
lst[k] = last_q_list[n]
n += 1
thanks in advance for your help!
Okay, so I have some ideas about things that are probably wrong here, but you've not really given much indication of what help you need, so first I want to point you in the right direction for how to figure this out yourself.
Before you even write any code to go inside merge4 and merge_sort_4, can you describe what are their preconditions and postconditions? I.e., what do you require to be true before one of them is called, both about the state of the list and the arguments passed to it? What is its job? What does it guarantee to have done when it has finished? What values can start have, and what values can end have?
I'm hoping that you're going to describe some constraints such as that 0 <= start <= end < len(lst) for calling merge_sort_4 and that 0 <= start <= q1 <= q2 <= q3 <= end <= len(lst) for calling merge4, and that merge4 requires the four sublists to be sorted and will guarantee that the entire range from list index start to end is sorted.
Now - are those things actually true? Can you walk through the code with example values and see what would happen? Can you add assertions into the algorithm to catch the first time one of them isn't true? Can you test the pieces of the algorithm separately on small pieces of test data to see if they behave as you expect?
Try and see if you can figure it out on your own, but if not, here's one place I suggest you start looking...
...
...
I would expect that quarter1, quarter2 and quarter3 should all fall within the range of start to end but I think the calculations you have there might not be doing what you expect. Try some different values of start and end and see if you are surprised what comes out.
There is an issue with using sentinel values (float('inf')). Consider the case when the ends of multiple runs have been reached, for example when first_q_list[i] == sec_q_list[j] == float('inf'), in which case the float('inf') at first_q_list[i] is copied to lst[k] and i is incremented beyond the end of first_q_list[].
The code needs to check for reaching the end of a run each time it copies an element, and if so, drop down to a 3 way merge of the remaining runs. Later dropping to 2 way merge and then finally a copy of the rest of the one remaining run.
The code could be improved, consider the case where third_q_lst[] or last_q_lst[] has the smallest element, it takes 6 compares to get to those cases. By using nested if + else, this can be reduced to just 3 compares along any path to determine which run has the smallest element. Example for 3 way merge to find smallest of a, b, c, with only 2 compares for any of the 3 possible cases:
if(a <= b)
if(a <= c)
a is smallest
else
c is smallest
else
if(b <= c)
b is smallest
else
c is smallest
Link to java example of a 4 way top down hybrid merge sort + insertion sort (for small runs). I haven't bothered porting it to Python because Python is so slow, and due to Python being an interpretive language, 4 way merge sort would probably be slower in Python than 2 way (with a compiled language, 4 way is about 15% faster than 2 way).
How can I implement the Merge Sort algorithm with 4-way partition without the error ArrayIndexOutOfBoundsException?
I understand what each of the individual operators does by itself, but I don't know how they interact in order to get the correct results.
def kill(n, k):
#Takes int n and replaces the bit k from right with 0. Returns the new number
return n & ~(1<<k-1)
I tested the program with the n as 37 and k as 3.
def b(n,s=""):
print (str(format(n, 'b')) +" "+ s)
def kill(n, k):
b(n, "n ")
b(1<<k-1, "1<<k-1")
b(~(1<<k-1), "~(1<<k-1) ")
b( n & ~(1<<k-1)," n & ~(1<<k-1) ")
return n & ~(1<<k-1)
#TESTS
kill(37, 3)
I decided to run through it step by step.
I printed both the binary representations of both n and ~(1<<k-1) but after that I was lost. ~(1<<k-1) gave me -101 and I'm not sure how to visualize that in binary. Can someone go through it step by step with visualizations for the binary?
All numbers below are printed in binary representation.
Say, n has m digits in binary representation. Observe that n & 11...1 (m ones) would return n. Indeed, working bitwise, if x is a one-bit digit (0 or 1), then x & 1 = x.
Moreover, observe that x & 0 = x. Therefore, to set up kth digit of number n to 0, we need to do operation and (&) with 11111..1011..1, where 0 is exactly on kth location from the end.
Now we need to generate 11111..1011..0. It has all ones except one digit. If we negate it, we get 00000..0100..1 which we get by 1 << k-1.
All in all: 1 << k-1 gives us 00000..0100..0. Its negation provides 11111..1011..1. Finally, we do & with the input.
Exactly how does the % operator work in Python, particularly when negative numbers are involved?
For example, why does -5 % 4 evaluate to 3, rather than, say, -1?
Unlike C or C++, Python's modulo operator (%) always return a number having the same sign as the denominator (divisor). Your expression yields 3 because
(-5) / 4 = -1.25 --> floor(-1.25) = -2
(-5) % 4 = (-2 × 4 + 3) % 4 = 3.
It is chosen over the C behavior because a nonnegative result is often more useful. An example is to compute week days. If today is Tuesday (day #2), what is the week day N days before? In Python we can compute with
return (2 - N) % 7
but in C, if N ≥ 3, we get a negative number which is an invalid number, and we need to manually fix it up by adding 7:
int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;
(See http://en.wikipedia.org/wiki/Modulo_operator for how the sign of result is determined for different languages.)
Here's an explanation from Guido van Rossum:
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
Essentially, it's so that a/b = q with remainder r preserves the relationships b*q + r = a and 0 <= r < b.
In python, modulo operator works like this.
>>> mod = n - math.floor(n/base) * base
so the result is (for your case):
mod = -5 - floor(-1.25) * 4
mod = -5 - (-2*4)
mod = 3
whereas other languages such as C, JAVA, JavaScript use truncation instead of floor.
>>> mod = n - int(n/base) * base
which results in:
mod = -5 - int(-1.25) * 4
mod = -5 - (-1*4)
mod = -1
If you need more information about rounding in python, read this.
Other answers, especially the selected one have clearly answered this question quite well. But I would like to present a graphical approach that might be easier to understand as well, along with python code to perform normal mathematical modulo in python.
Python Modulo for Dummies
Modulo function is a directional function that describes how much we have to move further or behind after the mathematical jumps that we take during division over our X-axis of infinite numbers.
So let's say you were doing 7%3
So in forward direction, your answer would be +1, but in backward direction-
your answer would be -2. Both of which are correct mathematically.
Similarly, you would have 2 moduli for negative numbers as well. For eg: -7%3, can result both in -1 or +2 as shown -
Forward direction
Backward direction
In mathematics, we choose inward jumps, i.e. forward direction for a positive number and backward direction for negative numbers.
But in Python, we have a forward direction for all positive modulo operations. Hence, your confusion -
>>> -5 % 4
3
>>> 5 % 4
1
Here is the python code for inward jump type modulo in python:
def newMod(a,b):
res = a%b
return res if not res else res-b if a<0 else res
which would give -
>>> newMod(-5,4)
-1
>>> newMod(5,4)
1
Many people would oppose the inward jump method, but my personal opinion is, that this one is better!!
As pointed out, Python modulo makes a well-reasoned exception to the conventions of other languages.
This gives negative numbers a seamless behavior, especially when used in combination with the // integer-divide operator, as % modulo often is (as in math.divmod):
for n in range(-8,8):
print n, n//4, n%4
Produces:
-8 -2 0
-7 -2 1
-6 -2 2
-5 -2 3
-4 -1 0
-3 -1 1
-2 -1 2
-1 -1 3
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3
Python % always outputs zero or positive*
Python // always rounds toward negative infinity
* ... as long as the right operand is positive. On the other hand 11 % -10 == -9
There is no one best way to handle integer division and mods with negative numbers. It would be nice if a/b was the same magnitude and opposite sign of (-a)/b. It would be nice if a % b was indeed a modulo b. Since we really want a == (a/b)*b + a%b, the first two are incompatible.
Which one to keep is a difficult question, and there are arguments for both sides. C and C++ round integer division towards zero (so a/b == -((-a)/b)), and apparently Python doesn't.
You can use:
result = numpy.fmod(x,y)
it will keep the sign , see numpy fmod() documentation.
It's also worth to mention that also the division in python is different from C:
Consider
>>> x = -10
>>> y = 37
in C you expect the result
0
what is x/y in python?
>>> print x/y
-1
and % is modulo - not the remainder! While x%y in C yields
-10
python yields.
>>> print x%y
27
You can get both as in C
The division:
>>> from math import trunc
>>> d = trunc(float(x)/y)
>>> print d
0
And the remainder (using the division from above):
>>> r = x - d*y
>>> print r
-10
This calculation is maybe not the fastest but it's working for any sign combinations of x and y to achieve the same results as in C plus it avoids conditional statements.
It's what modulo is used for. If you do a modulo through a series of numbers, it will give a cycle of values, say:
ans = num % 3
num
ans
3
0
2
2
1
1
0
0
-1
2
-2
1
-3
0
I also thought it was a strange behavior of Python. It turns out that I was not solving the division well (on paper); I was giving a value of 0 to the quotient and a value of -5 to the remainder. Terrible... I forgot the geometric representation of integers numbers. By recalling the geometry of integers given by the number line, one can get the correct values for the quotient and the remainder, and check that Python's behavior is fine. (Although I assume that you have already resolved your concern a long time ago).
#Deekshant has explained it well using visualisation. Another way to understand %(modulo) is ask a simple question.
What is nearest smaller number to dividend that can be divisible by divisor on X-axis ?
Let's have a look at few examples.
5 % 3
5 is Dividend, 3 is divisor. If you ask above question 3 is nearest smallest number that is divisible by divisor. ans would be 5 - 3 = 2. For positive Dividend, nearest smallest number would be always right side of dividend.
-5 % 3
Nearest smallest number that is divisible by 3 is -6 so ans would be -5 - (-6) = 1
-5 %4
Nearest smallest number that is divisible by 4 is -8 so ans would be -5 - (-8) = 3
Python answers every modulo expression with this method. Hope you can understand next how expression would be going to execute.
I attempted to write a general answer covering all input cases, because many people ask about various special cases (not just the one in OP, but also especially about negative values on the right-hand side) and it's really all the same question.
What does a % b actually give us in Python, explained in words?
Assuming that a and b are either float and/or int values, finite (not math.inf, math.nan etc.) and that b is not zero....
The result c is the unique number with the sign of b, such that a - c is divisible by b and abs(c) < abs(b). It will be an int when a and b are both int, and a float (even if it is exactly equal to an integer) when either a or b is an int.
For example:
>>> -9 % -5
-4
>>> 9 % 5
4
>>> -9 % 5
1
>>> 9 % -5
-1
The sign preservation also works for floating-point numbers; even when a is divisible by b, it is possible to get distinct 0.0 and -0.0 results (recalling that zero is signed in floating-point), and the sign will match b.
Proof of concept:
import math
def sign(x):
return math.copysign(1, x)
def test(a: [int, float], b: [int, float]):
c = a % b
if isinstance(a, int) and isinstance(b, int):
assert isinstance(c, int)
assert c * b >= 0 # same sign or c == 0
else:
assert isinstance(c, float)
assert sign(c) == sign(b)
assert abs(c) < abs(b)
assert math.isclose((a - c) / b, round((a - c) / b))
It's a little hard to phrase this in a way that covers all possible sign and type combinations and accounts for floating-point imprecision, but I'm pretty confident in the above. One specific gotcha for floats is that, because of that floating-point imprecision, the result for a % b might sometimes appear to give b rather than 0. In fact, it simply gives a value very close to b, because the result of the division wasn't quite exact:
>>> # On my version of Python
>>> 3.5 % 0.1
0.09999999999999981
>>> # On some other versions, it might appear as 0.1,
>>> # because of the internal rules for formatting floats for display
What if abs(a) < abs(b)?
A lot of people seem to think this is a special case, or for some reason have difficulty understanding what happens. But there is nothing special here.
For example: consider -1 % 3. How much, as a positive quantity (because 3 is positive), do we have to subtract from -1, in order to get a result divisible by 3? -1 is not divisible by 3; -1 - 1 is -2, which is also not divisible; but -1 - 2 is -3, which is divisible by 3 (dividing in exactly -1 times). By subtracting 2, we get back to divisibility; thus 2 is our predicted answer - and it checks out:
>>> -1 % 3
2
What about with b equal to zero?
It will raise ZeroDivisionError, regardless of whether b is integer zero, floating-point positive zero, or floating-point negative zero. In particular, it will not result in a NaN value.
What about special float values?
As one might expect, nan and signed infinity values for a produce a nan result, as long as b is not zero (which overrides everything else). nan values for b result in nan as well. NaN cannot be signed, so the sign of b is irrelevant in these cases.
Also as one might expect, inf % inf gives nan, regardless of the signs. If we are sharing out an infinite amount of as to an infinite amount of bs, there's no way to say "which infinity is bigger" or by how much.
The only slightly confusing cases are when b is a signed infinity value:
>>> 0 % inf
0.0
>>> 0 % -inf
-0.0
>>> 1 % inf
1.0
>>> 1 % -inf
-inf
As always, the result takes the sign of b. 0 is divisible by anything (except NaN), including infinity. But nothing else divides evenly into infinity. If a has the same sign as b, the result is simply a (as a floating-point value); if the signs differ, it will be b. Why? Well, consider -1 % inf. There isn't a finite value we can subtract from -1, in order to get to 0 (the unique value that we can divide into infinity). So we have to keep going, to infinity. The same logic applies to 1 % -inf, with all the signs reversed.
What about other types?
It's up to the type. For example, the Decimal type overloads the operator so that the result takes the sign of the numerator, even though it functionally represents the same kind of value that a float does. And, of course, strings use it for something completely different.
Why not always give a positive result, or take the sign of a?
The behaviour is motivated by integer division. While % happens to work with floating-point numbers, it's specifically designed to handle integer inputs, and the results for floats fall in line to be consistent with that.
After making the choice for a // b to give a floored division result, the % behaviour preserves a useful invariant:
>>> def check_consistency(a, b):
... assert (a // b) * b + (a % b) == a
...
>>> for a in range(-10, 11):
... for b in range(-10, 11):
... if b != 0:
... check_consistency(a, b) # no assertion is raised
...
In other words: adding the modulus value back, corrects the error created by doing an integer division.
(This, of course, lets us go back to the first section, and say that a % b simply computes a - ((a // b) * b). But that just kicks the can down the road; we still need to explain what // is doing for signed values, especially for floats.)
One practical application for this is when converting pixel coordinates to tile coordinates. // tells us which tile contains the pixel coordinate, and then % tells us the offset within that tile. Say we have 16x16 tiles: then the tile with x-coordinate 0 contains pixels with x-coordinates 0..15 inclusive, tile 1 corresponds to pixel coordinate values 16..31, and so on. If the pixel coordinate is, say, 100, we can easily calculate that it is in tile 100 // 16 == 6, and offset 100 % 16 == 4 pixels from the left edge of that tile.
We don't have to change anything in order to handle tiles on the other side of the origin. The tile at coordinate -1 needs to account for the next 16 pixel coordinates to the left of 0 - i.e., -16..-1 inclusive. And indeed, we find that e.g. -13 // 16 == -1 (so the coordinate is in that tile), and -13 % 16 == 3 (that's how far it is from the left edge of the tile).
By setting the tile width to be positive, we defined that the within-tile coordinates progress left-to-right. Therefore, knowing that a point is within a specific tile, we always want a positive result for that offset calculation. Python's % operator gives us that, on both sides of the y-axis.
What if I want it to work another way?
math.fmod will take the sign of the numerator. It will also return a floating-point result, even for two integer inputs, and raises an exception for signed-infinity a values with non-nan b values:
>>> math.fmod(-13, 16)
-13.0
>>> math.fmod(13, -16)
13.0
>>> math.fmod(1, -inf) # not -inf
1.0
>>> math.fmod(inf, 1.0) # not nan
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
It otherwise handles special cases the same way - a zero value for b raises an exception; otherwise any nan present causes a nan result.
If this also doesn't suit your needs, then carefully define the exact desired behaviour for every possible corner case, figure out where they differ from the built-in options, and make a wrapper function.
This is a follow-up to my question yesterday:
CMS kindly provided this example of using bitwise operators to add two numbers in C:
#include<stdio.h>
int add(int x, int y) {
int a, b;
do {
a = x & y;
b = x ^ y;
x = a << 1;
y = b;
} while (a);
return b;
}
int main( void ){
printf( "6 + 3 = %d", add(6,3));
printf( "6 - 3 = %d", add(6,-3));
return 0;
}
It works great and I then ported it to Python as follows:
def add(x, y):
while True:
a = x & y
b = x ^ y
x = a << 1
y = b
if a == 0:
break
return b
print "6 + 3 = %d" % add(6,3)
print "6 - 3 = %d" % add(6,-3)
They both work for addition and the C program works for subtraction as well. However, the Python program enters an infinite loop for subtraction. I am trying to get to the bottom of this and have posted the program here for further experimentation: http://codepad.org/pb8IuLnY
Can anyone advise why there would be a difference between the way C handles this and the way CPython handles this?
As I pointed out in my response to CMS' answer yesterday, left-shifting a negative number is undefined behavior in C so this isn't even guaranteed to work in C (the problem is how to handle the signed bit, do you shift it like a value bit or is it not affected by a shift? The standards committee couldn't agree on a behavior so it was left undefined).
When this happens to work in C it relies on fixed bit-width integers so that the leftmost bit gets pushed off the end when you do a shift (it also requires the sign bit to be treated as a value bit for shifting purposes). All integer types in C are fixed-bit but Python numbers can be arbitrarily large. Left-shifting a number in Python just causes it to keep getting larger:
>>> 1 << 100
1267650600228229401496703205376L
You could try something like this:
x = (a << 1) & 0xffffffff
To limit the result to 32-bits, the problem is that the left shift operator in Python doesn't shift the sign bit of a signed number (which is part of what is required to make this particular solution work). There might be a way to change the behavior of the shift operator but I don't know how.
Shifting negative numbers doesn't have consistent interpretation between python and C.
if i, j are two integers:
addition:
printf("%d",(i^j)|((i&j)<<1));
I've noticed that you're assuming that python works with numbers the same way as C does.
Thats not entirely true. Meaning C's int numbers have a fixed length of 16 bits. For detailed info on C datatypes you can refer to C_data_types on en.wikipedia.org
Python, on the other hand, is said to have a virtually infinite length for int numbers.
Adding positive integers may work the same way. But subtracting or adding negative integers shouldn't be a simple mapping translation.
An easy way to understand this is a little example on negative numbers:
Imagine a fixed length integer representation of 3 bits:
#Unsigned#
000 : 0
001 : 1
010 : 2
011 : 3
100 : 4
101 : 5
110 : 6
111 : 7
#Signed:#
000 : 0
001 : 1
010 : 2
011 : 3
100 : -4
101 : -3
110 : -2
111 : -1
This works cool because you can see that 1-3=1+(-3), -3 is 101 that's 5 if unsigned. So 1+5=6, 6 : 110 : -2. This means that 1-3=-2.
it also becomes buggy when overflowing:
-4 + -1 = 3 not -5 because it's out of range!
3 + 1 = -4 not 4 because it's out of range!
As you may see this works for fixed length but it doesn't work this way in Python.
For anyone are still interested, to resolve issue in python, just add a new case and switch the order of x and y inside the function, and return the negative value, though this put "-" in the function, but this presented a way using bit-wise operator. For anyone still wish to argue using operator "-" in the following question, I could argue that for the case of 2 - 6, the right answer is -4 where "-" exists in the answer, so it might be okay to add it when x is smaller than y. Hope this helps.
#A substract to substract two integers using bits operators
#refer to: https://www.geeksforgeeks.org/subtract-two-numbers-without-using-arithmetic-operators/
def subtractBits(x, y):
xRAW = x
yRAW = y
if x < y:
x = y
y = xRAW
# Iterate till there
# is no carry
while (y != 0):
# borrow contains common
# set bits of y and unset
# bits of x
borrow = (~x) & y
# Subtraction of bits of x
# and y where at least one
# of the bits is not set
x = x ^ y
# Borrow is shifted by one
# so that subtracting it from
# x gives the required sum
y = borrow << 1
if xRAW < yRAW:
return -x
else:
return x
print(subtractBits(100, 50))
print(subtractBits(1, 3))
print(subtractBits(40, 0))
print(subtractBits(0, 40))
print(subtractBits(5, 5))