Change index value in generator expression python - python

i'm new to python and I'm trying to do a condition inside a generator expression, and if my condition is met, I want to divide the index by 2, and add the index to a list. Else, i want to multiply by 3 and add 1. Also the order needs to be from n to 1. I cant really figure out where I update the index.
My code so far as follows:
def foo(n):
print(list(i // 2 if i % 2 == 0 else i * 3 + 1 for i in reversed(range(n + 1))))
Assuming n=5, output should be:
[5, 16, 8, 4, 2, 1]
My output:
[16, 2, 10, 1, 4, 0]
I saw that you can iterate using something like:
for i in range(start, end, -1)
How do I change the " -1 " to match my condition? (i=i/2 in case of even number, i*3+1 else).
Or I'm completely off course in which case I would like a hint. Thanks!

Related

Binary Search in Python: correct slicing

Please, help me unterstand the silly question about how binary sort algorithm's works.
So, lets take input array of [4, 5, 6, 7, 8, 11, 20] where i'm searching for index of 6 value (see the code).
As I take it should work this way:
First of all we take the pivot(middle) point of (end-start)/2=7 as of index=3
After the first iteration we got array's slice of [4, 5, 6] where we searching the mid point again. With result of index=1 and value = 5.
After second iteration we get the only array of 6, which meets the basic condition and we getting correct result.
To prove my assumption I added an output of the cutted array I should get at the second and third step.
But surprisingly it was [4, 5] on the 2nd and [] on the third step in opposite to [4,5,6] and [6] I expected?
Relating to slicing documentation a[start:stop] # items start through stop-1, so the last one isn't included.
But how homes, I'm getting the correct result assuming i'm working with [4,5,6] and [6] in opposite to incorrect output?
The code is:
def binarySearch(arr, start, end, x):
print('the input array is: ' + str(arr[start:end]))
if end>=start:
mid_idx=(start+end)//2
print('mid index is: ' + str(mid_idx))
if arr[mid_idx]==x:
return mid_idx
elif arr[mid_idx]>x:
return binarySearch(arr,start,mid_idx-1, x)
else:
return binarySearch(arr,mid_idx+1,end, x)
else:
return None
arr=[4, 5, 6, 7, 8, 11, 20]
res=binarySearch(arr, 0, len(arr),6)
print(res)
The output is:
the input array is: [4, 5, 6, 7, 8, 11, 20]
mid index is: 3
the input array is: [4, 5]
mid index is: 1
the input array is: []
mid index is: 2
2
It is good that you are surprised, because the code is not correct. It mixes two ways to interpret the end argument. Some implementations will treat end as included in the range to consider, while others treat end as the index after the intended range (this way is how slices/ranges are defined in Python).
The mix in your code can be seen here:
The calling code assumes the end argument as after the range
Your debugging print assumes the end argument as after the range
The first ("left") recursive call assumes the end argument is inclusive
The if condition assumes the end argument is inclusive.
You obviously cannot mix the two approaches and must make changes to make it consistent.
So either (excluding):
def binarySearch(arr, start, end, x):
print('the input array is: ' + str(arr[start:end]))
if end>start:
mid_idx=(start+end)//2
print('mid index is: ' + str(mid_idx))
if arr[mid_idx]==x:
return mid_idx
elif arr[mid_idx]>x:
return binarySearch(arr,start,mid_idx, x)
else:
return binarySearch(arr,mid_idx+1,end, x)
else:
return None
arr=[4, 5, 6, 7, 8, 11, 20]
res=binarySearch(arr, 0, len(arr),6)
print(res)
Or (including):
def binarySearch(arr, start, end, x):
print('the input array is: ' + str(arr[start:end+1]))
if end>=start:
mid_idx=(start+end)//2
print('mid index is: ' + str(mid_idx))
if arr[mid_idx]==x:
return mid_idx
elif arr[mid_idx]>x:
return binarySearch(arr,start,mid_idx-1, x)
else:
return binarySearch(arr,mid_idx+1,end, x)
else:
return None
arr=[4, 5, 6, 7, 8, 11, 20]
res=binarySearch(arr, 0, len(arr)-1,6)
print(res)

Check if content of index equals content of next index

array = [1, 1, 1, 1, 1, 1, 2]
new_array = [x for x in array if array[array.index(x)] != array[array.index(x) + 1]]
print(new_array)
Hi, I'm trying to write a program that will check if a content of an index (example: list[0]) equals to next index and if not append the number that differs and I tried to use a new skill I learned which is list comprehension and I don't quite understand why doesn't it work how it should work
To make it more clear what I mean is if I am given an array with all numbers the same except one number which in this case is two I want to append it in a list I also added a picture to make it even more clear
You can use this simple one liner
print(a[0] if a.count(a[0]) == 1 else min(set(a).difference(a[:1])))
Note: I'm using min() to just to get the element from set.
Output:
>>> a=[1, 1, 2]
>>> print(a[0] if a.count(a[0]) == 1 else min(set(a).difference(a[:1])))
2
>>> a = [17, 17, 3, 17, 17, 17, 17]
>>> print(a[0] if a.count(a[0]) == 1 else min(set(a).difference(a[:1])))
3
IndexError: list index out of range means you are passing an index that isn't present in the list. And that error is raised in this part:
array[array.index(x) + 1]
When x is the last element error is raised. Because there is no index after the last element. In your case, using list comprehension isn't the best choice, you should prefer for loop.
it may help you:
list = [1, 1, 2, 3, 4, 4]
for i, j in enumerate(list[:-1]):
if j == list[i+1]:
#dosomething

Slicing is not working correctly in python

Why the code listed below is not working:
a=[1,2,3,4,5,6,7,8,9]
print(a[1::-1])
This code should print [2,1,9,8,7,6,5,4,3].But it is printing [2,1].Why is this happening?
I'm guessing that your logic for the code printing [2, 1, 9, 8, 7, 6, 5, 4, 3] is that is starts at the first index (2), then decrements to print the 0th index (1). Then it sets the index to the last one (index 8 which is 9) and goes back from there. So:
1 -> 0 -> 8 -> 7 -> ... -> 3
However, what happens with list slicing, is the index stops at 0. i.e. it never goes beyond the length of the list, or 0. So it goes like:
1 -> 0
If you want to print [2, 1, 9, 8, 7, 6, 5, 4, 3] using list slicing, the following code should work:
print(a[1::-1] + a[:1:-1])
Here, we add the two lists that go from index 1-0, and from the last index of the list to 1
in step parameter you are giving -1 so it will go from end to start, hence it will printing [2,1]
So, you entered -1 at last. Then python will simply write(print) the words from right to left i.e. 9,8,7,6,5,4,3,2,1.
Now, python will go from +1 i.e. 2 to last integer i.e. 1.

Python SUM_WITH_FLAG

I entered to my college newly in recent and my major is CS.
I am very struggling with python programming and I need you guys help very seriously!
def sum_with_flag(alist,flag):
''' sum_with_flag(list,int) -> int
Returns the sum of all elements in the list. When `flag` is
seen in the list, `flag` is not added to the list. Additionally
everything after `flag` is not added to the list until `flag` is
seen again. In general, a number is added to the list only if
it is not equal to flag and there are an even number of occurances
of flag before it.
For example, if `flag` is 12
[1,12,5,7,12,8,12,1]
The function returns 1+8 = 9.
1 is counted
12 is flag, so 5 and 7 are not counted
12 is flag, so we count 8
12 is flag, so we do not count 1
sum_with_flag([1,12, 5, 7, 12, 8, 12, 1], 12)
9
sum_with_flag([1, 2, 3, 4], 0)
10
sum_with_flag([1, 2, 3, 4], 2)
1
sum_with_flag([1, 2, 1, 2, 1], 2)
2
sum_with_flag([1, 2, 1], 1)
0
sum_with_flag([1, 2, 1, 2, 1, 2, 1, 2, 1], 1)
4
'''
And here is my code.
for each in alist:
if each == flag:
del alist[flag:flag]
return sum(alist)
What is wrong with mine??
My second code is (it is not completed yet. Because I don't know what to change.)
A = True
for each in alist:
if each == flag:
A = not A
return sum(alist)
Your function is destructive: it will modify the list passed into it. It is generally bad form to do so unless your function's purpose is to modify the argument.
In alist[flag:flag], flag is treated as an index, but it is a value - it can be outside the index range, and even if not, it doesn't target anything that fits the requirements. E.g. in sum_with_flag([1,12, 5, 7, 12, 8, 12, 1], 12), alist doesn't even have 12 elements.
del alist[flag:flag] would delete any elements with flag <= index < flag, which is zero elements (given that no index is both less than flag and greater or equal to it at the same time).
The correct implementation would be to have a boolean variable that tells you whether you're including elements into a sum or not. It would start with a value True, indicating that you are. You also need a variable for the running sum, starting at zero. When you encounter an element that is equal to flag, you flip this variable. If an element is not equal to flag, then add it to the running sum, but only if you are currently in the adding mode.

Python syntax / understanding

def counting_sort(array, maxval):
"""in-place counting sort"""
m = maxval + 1
count = [0] * m # init with zeros
for a in array:
count[a] += 1 # count occurences
i = 0
for a in range(m): # emit
for c in range(count[a]): # - emit 'count[a]' copies of 'a' #CONFUSED
array[i] = a
i += 1
return array
print counting_sort( [1, 4, 7, 2, 1, 3, 2, 1, 4, 2, 3, 2, 1], 7 )
# prints: [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 7]
So in the code above i dont understand the line I marked with confused, 4 lines before the last.
Might be because I am new to python or just stupid.
What happends in the first case? When the range is [ ] ? ... "for each c in the range of empty array....?
i dont get array[i] = a on the line under aswell. If a is the first element in the counting array which might be zero, how can it be added....? Really confused...
Cheers!
You've apparently figured out that count[a] will be 0, and that range(count[a]) will therefore be [].
So, what you're asking is, what does this do:
for i in []:
do_stuff(i)
The answer is that it loops over each of the 0 elements—in other words, it doesn't loop at all. It just does nothing.*
This is explained in the docs for the for statement:
… The suite is then executed once for each item provided by the iterator… When the items are exhausted (which is immediately when the sequence is empty…) … the loop terminates.
And that implicitly explains your second bit of confusion:
If a is the first element in the counting array which might be zero, how can it be added
When count[a] is 0, you will never get into the loop, so that case cannot ever arise.
* If the for statement has an else clause, it does run the else clause.
range will give you a list with specified start and end values. For example
print range(5)
will print
[0, 1, 2, 3, 4]
When you say, range(m) or range(count[a]) it will generate a list till m or count[a] starting from 0.
About array[i] = a
In the range(m), for each element, the code checks the count[a]. If the count[a] is 0, the second loop will not be executed. (range(0) will produce an empty list) So, for when a is 0 array[i] = a will not be executed.
I simplified part of you code, maybe it it can help you understand the core of the algorithm well . After counting all the elements in the array, we can reconstruct a sorted array only with the information stored in count[].
array=[]
for a in range(m):
array.extend([a]*count[a])

Categories