Related
First, I want to find the highest number in the list which is the second number in the list, then split it in two parts. The first part contains the 2nd highest number, while the second part contains the number from the list that sums to the highest number. Then, return the list
eg: input: [4,9,6,3,2], expected output:[4,6,3,6,3,2] 6+3 sums to 9 which is the highest number in the list
Please code it without itertools.
python
def length(s):
val=max(s)
s.remove(val)
for j in s:
if j + j == val:
s.append(j)
s.append(j)
return s
Here's what I have but it doesn't return what the description states.
Any help would be appreciated as I spent DAYS on this.
Thanks,
The main issue in your code seems to be that you are editing the list s whilst iterating through it, which can cause issues with the compiler and is generally just something you want to avoid doing in programming. A solution to this could be iterating through a copy of the original list.
The second problem is that your program doesn't actually find the second biggest value in the list, just a value which doubles to give you the biggest value.
The final problem (which I unfortunately only noticed after uploading what I thought was a solution) is that the split values are appended to the end of the list rather than to the position where originally the largest value was.
Hopefully this helps:
def length(array):
val = max(array)
idx = array.index(val) # gets the position of the highest value in the array (val)
array.remove(val)
for i in array.copy(): # creates a copy of the original list which we can iterate through without causing buggy behaviour
if max(array) + i == val:
array = array[:idx] + [max(array), i] + array[idx:]
# Redefines the list by placing inside of it: all values in the list upto the previous highest values, the 2 values we got from splitting the highest value, and all values which previously went after the highest value.
return array
This will return None if there is no value which can be added to the second highest value to get the highest value in the given array.
Input:
print(length([1,2,3,4,5]))
print(length([4,8,4,3,2]))
print(length([11,17,3,2,20]))
print(length([11,17,3,2,21]))
Output:
[1, 2, 3, 4, 4, 1]
[4, 4, 4, 4, 3, 2]
[11, 17, 3, 2, 17, 3]
None
Here are the docs on list slicing (which are impossible to understand) and a handy tutorial.
when you say "The first part contains the 2nd highest number" does that mean second highest number from the list or the larger of the two numbers that add up the largest number from list?
Here I assume you just wanted the larger of the two numbers that add up to the largest number to come first.
def length(s:list):
#start by finding the largest value and it's position in the list:
largest_pos = 0
for i in range(len(s)):
if s[i] > s[largest_pos]:
largest_pos = i
# find two numbers that add up to the largest number in the s
for trail in range(len(s)):
for lead in range(trail, len(s)):
if (s[trail] + s[lead]) == s[largest_pos]:
if s[trail] > s[lead]:
s[largest_pos] = s[trail]
s.insert(largest_pos +1, s[lead])
else:
s[largest_pos] = s[lead]
s.insert(largest_pos + 1, s[trail])
return s
# if no two numbers add up to the largest number. return s
return s
Since you are limited to 2 numbers, a simple nested loop works.
def length(s):
val = max(s)
idx = s.index(val)
s.remove(val)
for i in range(len(s) - 1):
for j in range(i + 1, len(s)):
if s[i] + s[j] == val:
s = s[:idx] + [s[i], s[j]] + s[idx:]
return s
print(length([4,9,6,3,2]))
Output:
[4, 6, 3, 6, 3, 2]
I used deque library
first to find the highest element or elements then remove all of them and replace them with second high value and rest like : 9 replace with 6 and 3 in example:
from collections import deque
l = [4, 9, 6, 3, 2]
a = deque(l)
e = a.copy()
s = max(a)
while s in a:
a.remove(s) # remove all highest elements
s2 = max(a) # find second high value
c = s - s2
for i in l:
if i == s:
w = e.index(i) # find index of high values
e.remove(max(e))
e.insert(w, s2)
e.insert(w+1, c)
print(list(e))
I have two lists
a = [1, 4, 12]
b = [2, 13]
I want to know if values in list b are between two values in list a
So, in this case, 2 will fall between 1 and 4. 13 will not fall between any numbers.
I have tried bisect function, but I couldn't get it work. I was able to use it with a single value and a list, but not two lists.
Maybe there's some subtlety that I do not get, but unless I am mistaken, you only have to check whether the elements are between the min and max from a. This is independent of whether the elements in a are sorted, or whether the values from b have to be between consecutive values from a. As long as they are between the min and max, there has to be a "segment" in a those values are in.
>>> a = [1, 4, 12]
>>> b = [2, 13]
>>> n, m = min(a), max(a)
>>> [n < x < m for x in b]
[True, False]
That is, of course, only if (a) you do not need which numbers they are in between, and (b) if not all values in b have to be in the same interval.
If you think I missed something, please comment.
It really depends on what you want it to return. I wrote a code that will return the first pattern that it finds, but with some changes I'm sure it would not be difficult to return all combinations.
def get_between(a, b):
a, b = sorted(a), sorted(b)
for b_value in b:
smaller = None
greater = None
for a_value in a:
if b_value > a_value:
smaller = a_value
elif b_value < a_value:
greater = a_value
if smaller and greater:
return f"{b_value} is between {smaller} and {greater}"
return "There is no such combination"
a = [1, 4, 12]
b = [2, 13]
print(get_between(a, b))
The output on that case will be 2 is between 1 and 4, but you can adapt the return value to be whatever you want.
You can keep two running indices to get a list of all elements that fall between values:
def get_between(arr1, arr2):
# first sort the arrays
arr1 = sorted(arr1)
arr2 = sorted(arr2)
# keep two indices into them
i1 = 0
i2 = 0
# keep track of the values between two values
ret = []
while i1 < len(arr1) - 1 and i2 < len(arr2):
# we're too small to be between a value
# so we should increase the second index
if arr2[i2] < arr1[i1]:
i2 += 1
# we're too large to be between a value
# so we should increase the first index
elif arr2[i2] > arr1[i1 + 1]:
i1 += 1
# we are between a value
# so we should append to the return array
# and move on to the next element
else:
ret.append(arr2[i2])
i2 += 1
return ret
get_between([1, 4, 12], [2, 8, 13]) # [2, 8]
If you don't care much about performance, here's a pythonic solution-
def betwn(rangelist, valuelist):
# Get list of all ranges between each consecutive number of rangelist
rgs = [range(rangelist[n], rangelist[n + 1]) for n in range(len(rangelist) - 1)]
# A function to check whether a given element exists between 2 consecutive numbers of rangelist
verifyfunc = lambda e: any(e in r for r in rgs)
# Return the qualifying elements from valuelist
return [e for e in valuelist if verifyfunc(e)]
Output
>>> betwn([1, 4, 12], [2, 13])
[2]
I am getting a IndexError: list index out of range error. I'm not sure why. Any advice?
The code is trying to see if a list of numbers is an arithmatic progression, in this case every number is added by 2.
def is_arith_progession(num_list):
delta = num_list[1] - num_list[0]
for num in num_list:
if not (num_list[num + 1] - num_list[num] == delta):
return False
else:
return True
print(is_arith_progession([2, 4, 6, 8, 10]))
You are trying access 5th element of num_list array in the second iteration of for loop. After the first iteration num becomes 4, so program crashes when it tries to evaluate num_list[num + 1].
num variable holds the actual element in the list. It is not index to element.
To iterate over indices, you may try for num in range(len(num_list) - 1) which should solve the issue. (Note -1 in the paranthesis)
This:
for num in num_list:
if not (num_list[num + 1] - num_list[num] == delta):
return False
almost certainly doesn't do what you think it does. When you define for num in num_list:, this means that num is an item from the list num_list. num is NOT an index. So, if your list is [2, 4, 6, 8, 10], you go out of bounds when num is 4 (i.e. the second item in your list), because your input list is only length 5 and you try to access index num+1, which is 5 (indexes are 0 based, so 5 is out of bounds)
You probably want something like this:
# Start at index 1, or you'll always return false since delta == index1 - index0
for index in range(1, len(num_list)-1):
if not (num_list[num + 1] - num_list[num] == delta):
return False
or the more pythonic (note there are no indices):
# Again start at index1, zip will handle the edge case of ending nicely so we don't go OB
for num, next_num in zip(num_list[1:], num_list[2:]):
if not (next_num - num == delta):
return False
You are iterating over the values, not the indexes of the array. So, num_list[num] can be out of range. Since you refer to the i+1 element, iterate up to i < n-1
for i, _ in enumerate(num_list[:-1]):
if num_list[i+1] - num_list[i]...
2 things:
num is an element of num_list, not just an index. Getting an index would be for num in range(len(num_list)):, you're effectively calling num_list[num_list[i]];
Even if it was an index, for the last index num in array you are calling numlist[num+1], which is out of array bounds as num is already last;
Do for INDEX in range(len(num_list)-1): and if not (num_list[INDEX + 1] - num_list[INDEX] == delta):. That should do it.
I am analyzing the routine which checks if an array of N integers is a permutation (sequence containing each element from 1 to N).
I am new to python. I can't grasp how this routine gets the correct answer. Could anybody explain the logic behind the loop? especially the use of the counter[element-1].
Is the counter a built-in function working on every element of A? does the counter[element-1] reference position/value of elements of A by default because the loop is defined on an array?
A=[4,1,3,2]
def solution(A):
counter = [0]*len(A)
limit = len(A)
for element in A:
if not 1 <= element <= limit:
return 0
else:
if counter[element-1] != 0:
return 0
else:
counter[element-1] = 1
return 1
Update:
I modified the code to see the values used within the loop, for example
def solution(A):
counter = [0]*len(A)
limit = len(A)
for element in A:
if not 1 <= element <= limit:
print element
print 'outside'
return 0
else:
if counter[element-1] != 0:
print 'element %d' % element
print [element-1]
print counter[element-1]
return 0
else:
counter[element-1] = 1
print 'element %d' % element
print [element-1]
print counter[element-1]
return 1
gives me
element 4
[3]
1
element 1
[0]
1
element 3
[2]
1
element 2
[1]
1
1
I still don't get the logic. For example fot the first element, why [3] gives 1?
The idea behind the code is twofold. A permutation of the list [1, 2, ..., N] has two properties. It has only elements between 1 and N and each element just appear one time in the list.
I will try explain it to you part by part this idea in the code.
def solution(A):
counter = [0]*len(A)
limit = len(A)
Assume as an example, a list [1, 3, 2].
counter is initialized as a list of zeros of size len(A) = 3. Each 0 correspond to one of the elements of the list
for element in A:
if not 1 <= element <= limit:
return 0
This part condition is the most easy one. If the element is not in this range, the list cannot be a permutation of [1, 2,...N]. For instance, [1, 3, 2] is a permutation of [1, 2, 3] but [1, 6, 2] is not.
else:
if counter[element-1] != 0:
return 0
else:
counter[element-1] = 1
This next part is related with the uniqueness of each term. The if checks if a number = element has already passed through this loop. The second else make sure that this number is marked, so if a repeated number is found in the next iterations, the if will be true and return 0.
For instance, for the list [1, 2, 2]. The first 2 would not trigger the if, while the second 2 would trigger it, returning 0. On the other hand, [1, 3, 2], would never trigger the if.
If all the number pass this conditions, the two properties were true and the list is a permutation.
Quite a cunning algorithm actually.
The input is a sequence of length N.
Each element of input is presumed to be an integer (if not, either comparison or indexing will throw an exception).
counter is an array of flags - of length N, too.
No integers outside of [1,N] range are allowed
No duplicates are allowed (see how it's done)
Can you now prove that the only way for both conditions to stay true is for the sequence to be a permutation?
I have a list of integers like:
1 3 4 4 9 7 10 (the number of elements is between 1 and 200000)
and an integer variable D, it lies between 0 and 10^9.
Let it be 5 for example.
I need to count how many pairs in the list have a difference between each other not bigger than a variable D but the tricky part is that if I took the zero element with value 1 and the first element with the value 3(the difference between them meets the condition) I can't use these elements of a list again.
For example for the sequence above the answer is 3 pairs: (1,3) (4,4) (7,9)
I wrote a code which seems to be correct but I need a hint how to change the input sequence and the variable d the way it will output wrong answer
list_of_colors = [1, 3, 4, 4, 9, 7, 10]
d = 5
number_of_pairs = 0
list_of_colors.sort() # the values in the list are not always sorted
i = 0
while True:
if i >= len(list_of_colors):
break
if i != len(list_of_colors) - 1:
# if the number i in list and i+1 is the same or difference between them not greater than a variable d...
if (int(list_of_colors[i]) == int(list_of_colors[i + 1])) or abs(int(list_of_colors[i]) - int(list_of_colors[i + 1])) <= d:
#print list_of_colors[i]," ",list_of_colors[i + 1]
number_of_pairs += 1 # increasing the number of the acceptable pairs
i += 2 # jump over two elements, we already counted them
continue
i += 1
print number_of_pairs
I need another algorithm to compare it with the results of my algorithm on the various range of the input sequence and the variable d
Suggest your ideas please
I have a greedy solution for this problem:
Sort the input sequence.
Parse the sorted sequence as follows:
For ith element in the sequence,
if |a[i+1]-a[i]| <= D,
then pair up the elements. Proceed to process i+2th element.
else
proceed to process i+1th element.
My solution here is to first "clean" the list what means I made the number of elements even. Then I've converted the list into a list of tuples (pairs).
My result for this example is 3 pairs in order to your condition.
list_of_colors = [1, 3, 4, 4, 9, 7, 10]
d = 5
number_of_pairs = 0
list_of_colors.sort() # the values in the list are not always sorted
# remove the last element if the number of elements is odd
if len(list_of_colors) % 2 != 0:
list_of_colors = list_of_colors[:-1]
# create a list of tuples
list_of_colors = [tuple(list_of_colors[i:i+2]) for i in range(0, len(list_of_colors), 2)]
for i in list_of_colors:
if (int(i[0]) == int(i[1])) or abs(int(i[0])) - int(i[1]) <= d:
number_of_pairs += 1
print number_of_pairs