Why my sum_consecutives not iterating all ove the array? - python

Hello there i'm trying sum_consecutives as the function name mention in array example:
[1,1,7,7,3] should return [2,14,3]
Problem:
Looks like my algorithm not working with all the array i get this result everytime [2,14]
the function:
def sum_consecutives(s):
sum = 0
X = []
for i in range(0,len(s)-1):
print( i)
if s[i] == s[i+1]:
sum += s[i]
else:
X.append(sum+s[i])
sum = 0
return X

Your algorithm won't work because you're iterating from index 0 until index len(s) - 1, excluding the last element since the range function is end-exclusive (range(0, 5) iterates from 0 to 4). You can iterate over all elements and introduce a new variable to store the last element:
def sum_consecutives(values):
result = []
# Stores the first consecutive element
last_elem = None
for curr_elem in values:
# If the last element is not initialized,
# initializes it and proceed with the iteration
if last_elem is None:
last_elem = curr_elem
continue
# If the current element is equal to the last
# element, push the sum to the result list
if last_elem == curr_elem:
result.append(last_elem + curr_elem)
# Otherwise, push both elements to the result list
else:
result.append(last_elem)
result.append(curr_elem)
# Reset the last element set
last_elem = None
# If there's an element not paired (i.e. not None),
# push its value to the result array
if last_elem is not None:
result.append(last_elem)
return result
Some tests:
assert sum_consecutives([1, 1, 7, 7, 3]) == [2, 14, 3]
assert sum_consecutives([1]) == [1]
assert sum_consecutives([1, 1]) == [2]
assert sum_consecutives([1, 2, 1]) == [1, 2, 1]
Also, avoid naming your variable sum, it'll shadow the sum built-in.

Related

finding index[] of odd values in a list of integers?

I am trying to find the index value of some odd integers in a list. The program at its current stage only returns a new list containing only the odd integers.
image of my code
This program returns the values [3, 5, 7]. How would i be able to retrieve the index of these odd values instead? For example, [0, 1, 3, 5] for the list shown above.
I have tried "position = dataItem1.index()". I understand that i would need to input an index value within the index brackets.
you can use also use enumerate : it returns the index of the element and the element (also, in python you can loop directly over the elements of a list, no need of while loops). I also encourage the use of .append() to add an element to a list, this is clearly more efficient than concatenate two lists as you do:
l = [0, 3, 2, 3, 4, 7, 6]
def get_odds_index(l):
res = []
for idx, val in enumerate(l):
if val % 2 != 0:
res.append(idx)
return res
get_odds_index(l)
Instead of adding the element on that index in the odd list, just add index
Like this
def positionOfOdds(arr):
odds = []
length = len(arr)
index = 0
while index < length:
data = arr[index]
if data % 2 != 0:
odds.append(index)
index += 1
return odds
you already know the index, it is the loop variable
def positionOfOdds(arr):
odds = []
length = len(arr)
index = 0
while index < length:
data = arr[index]
if data % 2 != 0:
odds = odds + [index]
index += 1
return odds
You use an array called odds to store the odd numbers, to get the indexes you can create instead an array to store the indexes of the odd numbers, which I called odds_idxs. It should look something like this:
num_list = [0, 3, 2, 3, 4, 7, 6]
def position_of_odds(num_list):
odds_idxs = []
length = len(num_list)
index = 0
while index < length:
if num_list[index] % 2 != 0:
odds_idxs = odds_idxs + [index]
index = index + 1
return odds_idxs

How can I increment list items one by one and stop as soon as the sum of the list items has reached a target value?

I have a list of integers, and I want to add 1 to each integer in the list with every iteration of a while loop. More specifically, I want to perform this operation on the list's integers one by one (left to right) instead of all at once, and stop the loop as soon as the its conditional becomes False, even if that means stopping before the end of the list.
First, I tried the following:
def myfunction(someinput):
myintegerlist = [0, 0, 0]
while sum(myintegerlist) < someinput:
myintegerlist[0:] = [x+1 for x in myintegerlist[0:]]
return myintegerlist, sum(myintegerlist)
This doesn't do what I want, because it simultaneously adds 1 to all integers in the list. Thus if someinput = 4, it returns 6 as the sum and [2, 2, 2] as the list, whereas I would like it to stop at [2, 1, 1] before exceeding the input number. So I tried
while sum(myintegerlist) < someinput:
myintegerlist[indexplace] = [x+1 for x in myintegerlist[indexplace]]
indexplace += 1
This was just a guess, and throws "TypeError: 'int' object is not iterable". But I am stuck on how to get through the list items one by one and add 1 to them. Is there a good way to move incrementally through the list with each iteration? Or should I be trying something completely different?
Keep track of the index where you need to add the 1 during the while loop:
def myfunction(someinput):
myintegerlist = [0, 0, 0]
increment_index = 0 # next place to add 1
while sum(myintegerlist) < someinput:
myintegerlist[increment_index % len(myintegerlist)] += 1 # add 1 to the element, modulo length of the list to keep the index in range
increment_index += 1
return myintegerlist, sum(myintegerlist)
print(myfunction(4))
Result:
([2, 1, 1], 4)
Normally, in order to iterate over the values in a list you would just use
for value in myintegerlist:
# ...
but this doesn't allow you to directly change the value in the list.
You have to create a loop over the indices of the list.
for i in range(len(myintegerlist)):
value = myintegerlist[i]
In particular, by assigning to myintegerlist[i] you can change the values in the list.
for i in range(len(myintegerlist)):
value = myintegerlist[i]
myintegerlist[i] = new_value
Now you need one additional step, because you don't just want to iterate over each list index once, but possibly many times, until a condition is met. In order to keep the iteration going, you can use the cycle function from the itertools module.
from itertools import cycle
for i in cycle(range(len(myintegerlist))):
# i = 0, 1, 2, 0, 1, 2, 0, 1, ...
Now you can just add 1 to the value at the current list index and break the loop if the sum of the values has reached the desired amount:
for i in cycle(range(len(myintegerlist))):
if sum(myintegerlist) >= someinput:
break
myintegerlist[i] += 1
It is bad idea to start every time from 0. Too much meaningless iterations if someinput is a large number.
def get_els(sum_value: int, num_of_els: int = 3) -> tuple:
_list = [int(sum_value / num_of_els)] * num_of_els
if sum(_list) == sum_value:
return _list, sum_value
while True:
for idx in range(0, num_of_els):
_list[idx] += 1
if sum(_list) == sum_value:
return _list, sum_value
print(get_els(2))
print(get_els(4))
print(get_els(5))
print(get_els(10))
print(get_els(20))
Output:
([1, 1, 0], 2)
([2, 1, 1], 4)
([2, 2, 1], 5)
([4, 3, 3], 10)
([7, 7, 6], 20)
More over, if length of list is only 3 elements then loop is not necessary at all:
def get_els(sum_value: int) -> tuple:
_list = [int(sum_value / 3)] * 3
if sum_value % 3 == 0:
return _list, sum_value
if sum_value % 3 > 1:
_list[0] += 1
_list[1] += 1
else:
_list[0] += 1
return _list, sum_value

Finding numbers that cannot be paired

I've a function which aim is to find numbers that you cannot pair with others. If a number cannot be paired up with another identical number, then you will have to return it.
example:
[1,1,1,1, 2, 3, 4]
expected result:
[2,3,4]
def pair(input):
while len(input) > 2:
for i in range(len(input) - 1):
for j in range(len(input) - 1):
print(input)
if input[i] == input[j]:
input.pop(i)
input.pop(j)
print(input)
else:
break
return input
print(pair([1,1,1,1, 2, 3, 4]))
If you can use a library, you could use a Counter from collections, and just return the values in the list that have an odd count (since that implies there is one of those numbers that cannot be paired with another):
from collections import Counter
ll = [ 1, 2, 1, 3, 2, 3, 1, 4, 1, 2, 3, 4 ]
c = Counter(ll)
[num for num, cnt in c.items() if cnt % 2 == 1]
Output:
[2, 3]
One way to solve this problem is to find the unique elements in the list, and if an element occurs an odd number of times the in the list, returned it.
def pair(lst):
set_lst = set(lst)
output = []
for elem in set_lst:
if lst.count(elem) % 2 != 0:
output.append(elem)
return output
print(pair([1, 1, 1, 1, 2, 3, 4]))
Keeping track of the numbers that occurred an odd number of times:
def pair(lst):
odd = set()
for x in lst:
odd ^= {x}
return list(odd)
print(pair([1,1,1,1, 2, 3, 4]))
According your example input list is sorted. In this case #KetZoomer's solution is not effective, because it searching for the elem in whole list and counting it every time (lst.count(elem))
If you counted number of 1's you don't need to search for 2 in whole list from 0th element to last element again.
You should to use something like this:
def pairs(lst: list) -> list:
if len(lst) > 0:
# set first element
current_el = lst[0]
duplicate_count = 1
values_without_pair = []
else:
return []
# loop for elements starting from 2nd
for i in range(1, len(lst)):
# if looped element same as stored in memory increase count and go to next element
if current_el == lst[i]:
duplicate_count += 1
# if element is changed then check count value is even or not
# and set new element for checking
else:
if duplicate_count % 2 != 0:
values_without_pair.append(current_el)
duplicate_count = 1
current_el = lst[i]
# process last element
if duplicate_count % 2 != 0:
values_without_pair.append(current_el)
return values_without_pair
print(pairs([1,1,1,1,2,3,4]))

Problem while performing insertion sort while simultaneously adding values

I made a program to take elements from a list and a tuple simultaneously {ie. one from list then from tuple and then back from list and so on} and placing them in a new list and sorting them while inserting using insertion sort. The problem I am facing is the numbers are not sorting properly.
the output I'm getting [8, 6, 9, 4, 3, 1, 2, 5, 7]
the output I want. [1,2,3,4,5,6,7,8,9]
list = [8,6,4,2]
tuple = (9,5,7,1,3)
final = [list[0],] # creating a final list with the value list[0]
list.pop(0) # removing the first element from list
l = len(list)
t = len(tuple)
# now comparing whoes length is greater and assigning it to j
if l > t:
j = l
else:
j = t
b = 0 # variable to keep the count of elements in the final list starting from 0 to n-1
for i in range(j):
n = b
if i < l: # Making sure the index dosen't exceed the list
temp = list[i]
final.append(temp) # appending the value to last
while temp < final[n] & n>-1:
final[n+1] = final[n]
n = n-1
final[n+1] = temp
b+=1 # a value is added to final list so the total no of elements increases
n=b
if i < t: # Making sure the index dosen't exceed the tuple
temp = tuple[i]
final.append(temp)
while temp < final[n] & n>-1:
final[n+1] = final[n]
n = n-1
final[n+1] = temp
b+=1
print(final)
You can just use the .sort() method to get the correct order.
...
b+=1
final.sort()
print(final)

Selection Sort Python

This may seem like a simple question but when I attempted to implement selection sort in Python, I do not get a sorted list. Is there something wrong with my implementation? The subsetting may be a problem.
source = [4,2,1,10,5,3,100]
for i in range(len(source)):
mini = min(source[i:]) #find minimum element
min_index = source[i:].index(mini)-1 #find index of minimum element
source[i:][min_index]= source[i:][0] #replace element at min_index with first element
source[i:][0] = mini #replace first element with min element
print source
I think there were a couple issues.
First, when your do source[i:], I believe that returns a new array of the sub-elements requested and not part of the original array, thus if you modify it, your don't modify the original. Second, you were subtracting 1 from an index when you shouldn't.
source = [4,2,1,10,5,3,100]
for i in range(len(source)):
mini = min(source[i:]) #find minimum element
min_index = source[i:].index(mini) #find index of minimum element
source[i + min_index] = source[i] #replace element at min_index with first element
source[i] = mini #replace first element with min element
print source
This gives:
[1, 2, 3, 4, 5, 10, 100]
Here is how I would rewrite your code. Of course in Python I would just use list.sort() to sort a list, but here is a selection sort in Python.
We make a generator expression that returns tuples of (value, i) for a value and its index from the list. Then when min() evaluates to find minimum, it finds the lowest tuple value; since the value comes first in the tuple before the index, the value will be the important part, and min() will find the lowest value. (If there is a tie, min() will use the second part of the tuple, the index, as a tie-breaker. But for sort we don't care how ties are broken.)
Now, instead of searching through the sub-list to find the min value, and then searching through it again to figure out the index, we search through it once and get both min value and index.
But we don't actually care about the min value; we care about the index. So after min() is done, we just throw away the actual value but keep the index. Adjust the index to be correct in the whole list (not in the slice of the list) and then we can swap.
We use the standard Python idiom for swapping two values. Python will build a tuple object to be the intermediate, then unpack this tuple into the left-hand-side.
lst = [4,2,1,10,5,3,100]
for i_sortpos in range(len(lst)):
# Make a generator expression to return (value, i) pairs.
genexp = ((n, i) for i, n in enumerate(lst[i_sortpos:]))
# Use genexp with min() to find lowest and its index.
# (Use '_' for variable name for the actual value; we don't use it.)
_, i_min = min(genexp)
# Adjust index to be correct in full list.
i_min += i_sortpos
# Swap the number at i_sortpos with the lowest found.
lst[i_sortpos], lst[i_min] = lst[i_min], lst[i_sortpos]
print(lst)
EDIT: And here is a refinement of the above. A slice from a list actually allocates a new list; our code here doesn't need a new list, it just needs a convenient way to examine a sublist. The itertools module offers a function, islice(), that returns an iterator that iterates over a slice of a list. This avoids repeatedly creating and destroying lists as we examine each sublist.
I believe this is the most efficient way to do selection sort in Python. (You could get rid of the part where we bind the generator expression to the name genexp and save a few microseconds... just make the call to min() a long one-liner. But it's not really worth the loss of readability.)
import itertools as it
lst = [4,2,1,10,5,3,100]
for i_sortpos in range(len(lst)):
# Make a generator expression to return (value, i) pairs.
# Use it.islice() for to look at sublist.
genexp = ((n, i) for i, n in enumerate(it.islice(lst, i_sortpos, len(lst))))
# Use genexp with min() to find lowest and its index.
# (Use '_' for variable name for the actual value; we don't use it.)
_, i_min = min(genexp)
# Adjust index to be correct in full list.
i_min += i_sortpos
# Swap the number at i_sortpos with the lowest found.
lst[i_sortpos], lst[i_min] = lst[i_min], lst[i_sortpos]
print(lst)
def selectionSort(List_):
for i in range(len(List_)):`
#track the current smallest value
smallIndex = i
#loop from the current smallest value
for j in range(i+1,len(List_))
if List_[j] < List_[smallIndex]:
#if new value is less that our smallest value,change
#smallest value to this
smallIndex = j
if smallIndex != i:
#swap the values
List_[smallIndex],List_[i] = List_[i],List_[smallIndex]
#return sorted list
return List_
def ss(l):
for i in range(0,len(l)):
d=l.index(min(l[i:]))
c=l[i]
l[i]=min(l[i:])
l[d]=c
print(l) #it prints each step of selection sort
y=[10,9,1,5,0,6]
ss(y)
def selSort(L):
"""
Find the smallest element in the list and put it (swap it) in the first location,
Find the second element and put it (swap it) in the second locaiton, and so on.
"""
for i in range(len(L) - 1):
minIndx = i
minVal= L[i]
j = i + 1
while j < len(L):
if minVal > L[j]:
minIndx = j
minVal= L[j]
j += 1
temp = L[i]
L[i] = L[minIndx]
L[minIndx] = temp
return L
Call:
print( selSort([120,11,0,1,3,2,3,4,5,6,7,8,9,10]) )
Output
[0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 120]
s = [1,8,4,9,3,6,2]
for i in range(len(s)):
maxi = max(s[0:len(s)-i]) #find max element
tempi = s.index(maxi) # find index of max element
temp = s[len(s)-1-i] #assign last element as temp
s[len(s)-1-i] = maxi #put max element in last position
s[tempi] = temp # put the element initially at last in its new
print s
Find the position(first and last), swap the elements if last is lower.
nums = [4,2,1,10,5,3,100]
def sort(nums):
###Find the position and now first 0th element is sorted and rest is unsorted
#Second iteration first 2 element is sorted
for i in range(len(nums)-1):
miniposition = i
for j in range(i,len(nums)):
if nums[j] < nums[miniposition]:
miniposition = j
temp = nums[i]
nums[i] = nums[miniposition]
nums[miniposition] = temp
sort(nums)
print (nums)
First iteration(swapped 4 and 1)
[1, 2, 4, 10, 5, 3, 100]
[1, 2, 4, 10, 5, 3, 100]
[1, 2, 3, 10, 5, 4, 100]
[1, 2, 3, 4, 5, 10, 100]
[1, 2, 3, 4, 5, 10, 100]
[1, 2, 3, 4, 5, 10, 100]
Other way
nums = [4,2,1,10,5,3,100]
i = 0
while i<len(nums):
#smallest element in the sublist
smallest = min(nums[i:])
#index of smallest element
index_of_smallest = nums.index(smallest)
#swapping
nums[i],nums[index_of_smallest] = nums[index_of_smallest],nums[i]
i=i+1
print (nums)
a slight variation of the solution provided
def selection_sort(l):
i = 0
while i < len(l):
minium_value = min(l[i:]) # minium value at ith iteration
minium_value_index = l[i:].index(minium_value) # minium value index at i th iteration
if minium_value < l[i]: # if the current value already min, skip
l[i + minium_value_index] = l[i] # put current value in min value's index - swap 1
l[i] = minium_value # set current value with min value- swap 2
i += 1
return l
def selection_sort_min(): # sorting number
for i in range(len(num)-1):
current_min_index = i
for j in range(i+1,len(num)):
if num[j] < num[current_min_index] :
current_min_index = j
num[i],num[current_min_index] = num [current_min_index],num[i]
print(num)
num = [23,89,12,0,3,7,33]
selection_sort_min()
here is what I think is a good way to sort a list of numbers and I hope it helps:
list=[5,4,3,1,6,8,10,9]
listsorted=[]
for i in range(len(list)):
x=min(list)
list.remove(x)
listsorted.append(x)
print listsorted
and the result will be [1, 3, 4, 5, 6, 8, 9, 10]
I think the "accepted" answer here is unhelpful. If we look at e.g.
mini = min(source[i:]) #find minimum element
min_index = source[i:].index(mini) #find index of minimum element
not only is this inefficient in terms of creating list slices unnecessarily, but they are searched unnecessarily. It's reasonably concise but I don't think it's the best solution.
def Selection_Sort(Sarray):
length = len(Sarray)
i = 0
j = 0
for i in range(length):
j = i+1
for j in range(length):
if Sarray[i] < Sarray[j]
t = Sarray[i]
Sarray[i] = Sarray[j]
Sarray[j] = t
j = j+1
i = i+1
return Sarray
Code of select sort from MIT online course .
def selSort(L):
for i in range(len(L) - 1):
minIndx = i
minVal = L[i]
j = i+1
while j < len(L):
if minVal > L[j]:
minIndx = j
minVal = L[j]
j += 1
if minIndx != i:
temp = L[i]
L[i] = L[minIndx]
L[minIndx] = temp
def selectSort(L):
for i in range(len(L)):
print L
minIndex = i
minValue = L[i]
j = i + 1
while j < len(L):
if minValue > L[j]:
minIndex = j
minValue = L[j]
j +=1
temp = L[i]
L[i] = L[minIndex]
L[minIndex] = temp

Categories