how to separate and sort numbers in python? - python-3.x

Given a variable containing integer numbers with the provisions of the number 0 (zero) in the variable is a separator between one number with another number. The numbers will be separated and ordered by the numbers in the numbers themselves. After that, the numbers from the sort will be rejoined without separating with the output in the form of integer numbers. Make a method / function that accepts parameters only a series of numbers and produces output like the description above.
def sort(nums):
for i in range (15):
minpos = 1
for j in range (i,6):
if nums[j] < nums[minpos]:
minpos = j
temp = nums[i]
nums[i] = nums[minpos]
nums[minpos] = temp
nums = [5,9,5,6,5,6,0,1,5,9,4,6,6,0,5,6]
sort(nums)
print(nums)
The output should be 55566914566956 , but actual output is [5, 5, 5, 5, 6, 6, 9, 0, 1, 5, 9, 4, 6, 6, 0, 6]

You can try the following function:
def sort(nums):
curr = []
ret = ''
for i in nums:
if i == 0:
ret += ''.join(map(str, sorted(curr)))
curr = []
else:
curr.append(i)
ret += ''.join(map(str, sorted(curr)))
return ret
print(sort([5,9,5,6,5,6,0,1,5,9,4,6,6,0,5,6]))
Prints:
55566914566956

def sort(nums):
result = list()
sub_array = list()
for i in nums:
if i == 0:
# sort sub array and append it to result
sub_array.sort()
result.extend(sub_array)
sub_array = list()
else:
sub_array.append(i)
# ensure that the last sub_array is also treated
sub_array.sort()
result.extend(sub_array)
return result
nums = [5,9,5,6,5,6,0,1,5,9,4,6,6,0,5,6]
result = sort(nums)
print(result)
The easiest way is to loop through your list and create a sub array of numbers up until you find a '0'. At this point, simply order your sub array, append it to your result list and continue until the end of your input string.

Related

Sum of consecutive data in List - Python

I have a long list of number of which a sample look something like shown below:
L = [0, 1, 2, 0, 0, 2, 3, 1, 0, 10, 0, 2, 4, 5, 0, 0, 7, 8, 9, 0, ...]
singleData = []
sumofTwo = []
sumofThree = []
sumofFour = []
.
.
What I want to be able to do is categorize a data OR sum of two or more consecutive data into the respective lists based on the COUNT of numbers involved in the sum operation. So, if there is an occurrence of zero between two numbers, then their sum would not be considered.
For example, if I take the list above, the sum of 1 and 2 is to be added to the list sumofTwo. Similarly, if it is the sum of three consecutive numbers without the occurrence of 0's then the sum is expected to be in the sumofThree list (sum of 2,3,1; 2,4,5 and 7, 8, 9). If a number occurs between two or more 0's then it is to be appended to the singleData list (eg. 10).
How can i achieve this considering that in the list(L) there can be a sum of random consecutive numbers? Example, sum of 6 or 7 or 8 or any consecutive numbers?
I was able to segregate only a single number between 0's and the sum of two numbers. Following is the code:
for i in range(len(l)):
try:
if i == 0:
if l[i] == 0:
continue
elif l[i] != 0 and l[i+1] == 0:
singleData.append(l[i])
elif l[i] != 0 and l[i+1] != 0:
sumofTwo.append(l[i]+l[i+1])
elif i == len(l)-1:
if l[i] != 0 and l[i-1] == 0:
singleData.append(l[i])
else:
if l[i] != 0:
if l[i+1] == 0 and l[i-1] == 0:
singleData.append(l[i])
elif l[i+1] != 0:
sumofTwo.append(l[i]+l[i+1])
except IndexError:
print("Index out of range")
I realized that my code will only get messier with more cases of the sum of consecutive numbers and ultimately end up with error.
Can anybody help me out? Thanks in advance :))))
I would recommend using a dictionary to store the results:
L = [0, 1, 2, 0, 0, 2, 3, 1, 0, 10, 0, 2, 4, 5, 0, 0, 7, 8, 9, 0]
consecutive_sums = {} # Create an empty dictionary
I would also recommend directly iterating through the list, rather than using range(len(L). e.g.
for number in L:
print(number)
Then, you can just create a counter variable to check how long the current sequence is, and reset the counter when you get to a zero.
L = [0, 1, 2, 0, 0, 2, 3, 1, 0, 10, 0, 2, 4, 5, 0, 0, 7, 8, 9, 0]
consecutive_sums = {} # Create an empty dictionary
counter = 0
sum = 0
for number in L:
if number == 0: # Save the current sum and reset counter
# Check if we've already had a sequence of this length.
# If so, we have already added a list, so can append to it.
if counter in consecutive_sums:
consecutive_sums[counter].append(sum)
else: # If this is the first time we've had this length sequence
# we need to create a new key value pair in the dictionary.
# Note that the value is a list containing `sum`.
# Make sure to use a list so that you can append to it later.
consecutive_sums[counter] = [sum]
# Reset counter and sum
counter = 0
sum = 0
else: # Increment counter
counter += 1
sum += number
print(consecutive_sums)
Note that this code will not sort the dictionary keys, so the sums of sequences of length 1 may not appear at the beginning. But you can access it using consecutive_sums[1].
Also note that this version of the code also counts sequences of length 0. I suspect this is not what you want, but I'll let you figure out how to fix it!
Output:
{0: [0, 0, 0], 2: [3], 3: [6, 11, 24], 1: [10]}
EDIT:
I've intentionally tried to solve this using just builtin functions and datatypes. But if you really want to be fancy, you can use collections.defaultdict.
Below is an alternative version which uses defaultdict:
from collections import defaultdict
L = [0, 1, 2, 0, 0, 2, 3, 1, 0, 10, 0, 2, 4, 5, 0, 0, 7, 8, 9, 0]
consecutive_sums = defaultdict(list) # Create an empty defaultdict of type list
counter = 0
sum = 0
for number in L:
if number == 0: # Save the current sum and reset counter
# The magic of defaultdict:
# We don't need to check if the key exists.
# If it doesn't exist yet, defaultdict will automatically make
# an empty list for us to append to!
consecutive_sums[counter].append(sum)
# Reset counter and sum
counter = 0
sum = 0
else: # Increment counter
counter += 1
sum += number
print(consecutive_sums)
The first thing I would do is to organize a bit better our output lists, so that each can be accessed in the same way using the number of consecutive numbers. As #daviewales suggested, you could do this with a dictionary with lists as values, something like sums = {}, so that sums[1] would be the same as singleData, sums[2] the same as sumofTwo, and so on. That way, you will avoid a lot of if to know in what list you should put your data, you'll just need to use stuff like sums[nbOfValuesInSum].
Second thing, you could write a function that detects your sequences of non-zero values. A possibility would be a function that takes a list and a start index, and returns the start and end indexes of the next "interesting" sequence. It would look like this :
def findNextSequence(l, start):
while l[start] == 0:
if start == len(l)-1:
return None # there is no non-zero value left
start+=1
# when we exit the loop, start is the index of the first non-zero value
end = start + 1
while l[end] != 0:
if end == len(l)-1:
break
end+=1
# and now end is the index of the first zero value after the sequence
return (start, end)
Then you can call it in a loop, like this:
i = 0
while True:
bounds = findNextSequence(l, i)
if bounds is None:
break # there is no non-zero value left
seq = l[bounds[0]:bounds[1]] # get the start and end index of the sequence
if len(seq) not in sums:
sums[len(seq)] = []
sums[len(seq)].append(sum(seq)) # see? No need to explicitly check len(seq) to know what list I want
i = bounds[1] # get ready for the next iteration
if i == len(l):
break
NB : no need to pass l as a parameter of findNextSequence if it's a global variable

tribonacci sequence python code skips for loop within while loop

I wanted to use a for loop within a while loop to add up the last 3 numbers of the list and generate a new number to append into the existing list. However, the code would not enter the for loop within the while loop and I have no clue why.
What the function is supposed to do:
Take in a list of numbers (as signature)
Total up the LAST 3 numbers in the list and produce the next number to be appended
Continue step 2 until length of list == n
#my code
def tribonacci(signature, n):
total = 0
for i in range(len(signature)):
num = signature[i]
total += num
signature.append(total)
while len(signature) < n:
for j in range(-1,-4):
num = signature[j]
total += num
signature.append(num)
return signature
#Some sample test code:
print(tribonacci([1, 1, 1], 10))
print("Correct output: " + "[1, 1, 1, 3, 5, 9, 17, 31, 57, 105]")
print(tribonacci([0, 0, 1], 10))
print("Correct output: " + "[0, 0, 1, 1, 2, 4, 7, 13, 24, 44]")
print(tribonacci([300, 200, 100], 0))
print("Correct output: " + "[]")
UPDATE!
As suggested, I resetted the total count in the while loop by creating a total_2 = 0. I've also added the -1 to the range and changed .append(num) in the while loop block to .append(total_2).
def tribonacci(signature, n):
total = 0
for i in range(len(signature)):
num = signature[i]
total += num
signature.append(total)
while len(signature) < n:
total_2 = 0
for j in range(-1,-4, -1):
num = signature[j]
total_2 += num
signature.append(total_2)
return signature
However, this code doesnt work the 3rd print test code where n = 0. One of the users shared a much shorter code which works for ALL of the test code.
Try range(-1,-4,-1). You need to tell python to go backwards.
Just for the reference, I've implemented your function with a few improvements:
def tribonacci(signature, n):
signature = signature[:n]
while len(signature) < n:
signature.append(sum(signature[-3:]))
return signature

How many times should I loop to cover all cases of possible sums?

I am trying to solve this competitive programming problem using python3. The problem asks, given an array of size n, split the array into three consecutive, contiguous parts such that the first part has maximum sum and equals the sum of the third part. The elements in the array are positive integers.
My approach:
inputN = int(input())
inputString = input()
usableString = stringToList(inputString)
counting = 0
sum1 = usableString[0]
sum3 = usableString[-1]
maxSum1 = 0
countFromLeft = 1
countFromRight = 2
while counting < inputN-1:
if sum1 > sum3:
sum3 += usableString[-countFromRight]
countFromRight += 1
elif sum3 > sum1:
sum1 += usableString[countFromLeft]
countFromLeft += 1
elif sum1 == sum3:
maxSum1 = sum1
sum1 += usableString[countFromLeft]
countFromLeft += 1
counting += 1
print(maxSum1)
We read in the array elements and store them in a list usableString.
We set two variables sum1 and sum3 to the first and last elements of the list respectively.
We set a variable to keep track of the maximum sum of the first part of the list.
Finally, we set a variable counting to 0 which will represent the number of elements we have added from the list into sum1 or sum3.
The rest of the logic is in the while loop, which just checks if sum1 is larger than sum3 or the other way around and otherwise if they equal. After each iteration we add 1 to counting as an extra element has been included in a part. The while loop should stop when the number of elements used (i.e counting) is equal to the number of elements in the array - 1, since we added the first and last elements before entering the loop, which makes (array - 2), however, we still need to loop one additional time to check if sum1 and sum3 are equal.
I checked your submitted algorithm, and the problem is your stringToList function:
def stringToList(s):
list=[]
for elem in s:
if elem != " ":
list.append(int(elem))
return list
As far as I can tell, your main algorithm is completely fine, but stringToList does one crucial thing incorrectly:
>>> stringToList('2 4 6 8 10')
[2, 4, 6, 8, 1, 0]
# should be
[2, 4, 6, 8, 10]
As it treats each character individually, the two digits of 10 are turned into 1, 0. A simpler method which performs correctly would be to do the following:
# explanation
>>> input()
'2 4 6 8 10'
>>> input().split(' ')
['2', '4', '6', '8', '10']
>>> map(int, input().split(' ')) # applies the int function to all elements
<map object at 0x...>
>>> list(map(int, input().split(' '))) # converts map object into list
[2, 4, 6, 8, 10]
Sorry it took so long, I ended up making my own algorithm to compare to yours, ran my own tests, and then ran your code with the input to list method I just explained, and figured the only difference was your stringToList function. Took a while, but I hope it helps!
Just for the fun, here's my algorithm and turns out it was pretty similar to yours!
array = [1, 3, 2, 1, 4]
n = len(array)
slice = [0, n]
sum = [array[0], 0]
bestSum = 0
while slice[0] < slice[1]-1:
i = 0 if (sum[0] < sum[1]) else 1
slice[i] += 1-(2*i)
sum[i] += array[slice[i]]
if sum[0] == sum[1]: bestSum = sum[0]
# print(array[ : slice[0]+1], array[slice[0]+1 : slice[1]], array[slice[1] : ])
print(bestSum)

Finding subset List of Python List based on an input integer

I want a subset list from input List based on input integer value.
For Example:
Input List: [3,7,9,11,12]
Input Value: 2
Output List: [1,7,9,11,12]
# 2 is subtracted from first element of list
Input List: [3,7,9,11,12]
Input Value: 5
Output List: [5,9,11,12]
#5 is subtracted from list in sequence manner, first 3 is subtracted then remaining 2 is subtracted from 7 hence output is [5,9,11,12]
Use numpy.cumsum() if modules are allowed:
import numpy as np
input_list = np.asarray([3, 7, 9, 11, 12])
input_integer = 5
output_list = input_list[input_list.cumsum() > input_integer]
output_list[0] -= input_integer - input_list[input_list.cumsum() <= input_integer].sum()
print(output_list)
Output:
[ 5 9 11 12]
What i did there:
Since total sum is to be subtracted from starting, using cumulated sum will tell you where to crop the list from.
Then set the first element = first elem - (input_integer - cropped list's sum)
Recursive solution:
def subfrom( lst, n ):
if n<=0 or lst == []:
# No change necessary
return lst
if lst[0] <= n:
# First element gets removed
# Return the list you get by removing the leftover from the rest of the list
return subfrom( lst[1:], n-lst[0] )
# Reducde first element
return [lst[0]-n] + lst[1:]
Another solution:
# First set of test variables
list1 = [3,7,9,11,12]
input1 = 2
# Second set of test variables
list2 = [3,7,9,11,12]
input2 = 5
def eval_list(input_value, iterable, output = None):
if output is None:
output = []
for i, v in enumerate(iterable):
current = iterable[i]
if input_value > 0:
if v <= input_value:
input_value -= current
else:
current -= input_value
input_value = 0
output.append(current)
else:
output.append(current)
return output
Run for each data set and output results:
res1 = eval_list(input1, list1)
res2 = eval_list(input2, list2)
print(f"Set 1: {res1}")
print(f"Set 2: {res2}")
Output:
Set 1: [1, 7, 9, 11, 12]
Set 2: [5, 9, 11, 12]

Reduce time complexity of program

I have written a function to remove items specified in a given list.
def remove_given_elements(arr1) :
b = []
x = int(input("Enter the number of items to be removed :"))
for i in range(x) :
y = int(input("Enter the position to be removed :"))
b.append(y)
arr3 = []
pos = 0
for i in range(len(arr1)) :
arr3.append(arr1[i])
for j in range(len(b)):
if pos == b[j]:
arr3.pop(b[j])
arr3.append(None)
pos += 1
arr4 = []
for i in arr3:
if i != None :
arr4.append(i)
return arr4
a = [100,200,323,434,512,656]
print("After removing elements",remove_given_elements(a))
Output :
Enter the number of items to be removed :3
Enter the position to be removed :1
Enter the position to be removed :3
Enter the position to be removed :4
After removing elements [100, 323, 656]
As, i am new to programming. I really don't know any methods to decrease my worst case time complexity. Any kind of help is appreciated or please guide me to use proper methods which decreases time complexity.
You can ask before for the positions and store them in a tuple. Then apply the function.
def remove(_list, pos):
return [v for i, v in enumerate(_list) if i not in pos]
positions = (1, 2, 3)
l = [1, 2, 3, 4, 5, 6, 7]
result = remove(l, positions)
print(result)
The function return a List Comprehension

Resources