Distribute value over list - python

Given the amount S=25 and list L = [10,20,30] I want to distribute S over L in the following way:
output -> [10, 15, 0]
I wrote the following code, which does the job:
S = 25
l = [10,20,30]
res= []
b = True
for value in l:
if b == True:
if S - value >0:
res.append(value)
else:
res.append(S)
b= False
S -= value
else:
res.append(0)
Is it possible to rewrite it, maybe as a one-liner? (numpy is allowed)

Slightly shorter and more readable:
def distribute(S, L):
res = []
for e in L:
res.append(min(e, S))
S = max(0, S-e)
return res
While you can make this (or anything really) a one-liner, I wouldn't force it. It's better to keep things readable.
You can also use an equivalent generator function:
def distribute(S, L):
for e in L:
yield min(e, S)
S = max(0, S-e)
list(distribute(S, l))

This is one way, but please do not get attached to one-liners for the sake of them being one-liners. Often they are not the best method, either in terms of readability or performance.
from itertools import accumulate
S = 25
l = [10, 20, 30]
res = [i if j <= S else max(0, S-k) \
for i, j, k in zip(l, accumulate(l), accumulate([0]+l))]
# [10, 15, 0]

numpy
Since OP specifically asked for numpy, let's assume this is about large arrays. I think distribute in the OP subject was a key word, because this is very similar to conversion between PDF and CDF (https://en.wikipedia.org/wiki/Cumulative_distribution_function) and the inverse:
a = numpy.array([10, 20, 30])
c = a.cumsum() # [10, 30, 60]
b = c.clip(0, 25) # [20, 25, 25]
numpy.ediff1d(b, to_begin=b[0]) # [10, 15, 0]

Related

Modify function to accept tables as well (Python 3)

I've designed a simple function that looks at an inputted list of numbers, identifies the minimum and maximum values, then substitutes both of them for the midpoint value between them, the function is here:
def mainfunction(list_of_numbers):
smallest_number = list_of_numbers[0]
for a in list_of_numbers:
if a < smallest_number:
smallest_number = a
largest_number = list_of_numbers[0]
for b in list_of_numbers:
if b > largest_number:
largest_number = b
midpoint = (smallest_number + largest_number)/2
final_list = [x if (x != largest_number and x != smallest_number) else midpoint for x in list_of_numbers]
return final_list
print(mainfunction([10, 7, 14, 3, -200, 8, 1, -12, 250]))
Unfortunately, I can't get the function to work on TABLES of numbers, is there an easy way to convert a table of numbers into a list? Any info would be appreciated, cheers!
You can use itertools.chain
from itertools import chain
a = [[3,4], [15,16], [19,20]]
res = list(chain.from_iterable(a))
print(res)
Output:
[3, 4, 15, 16, 19, 20]
with list comprehension
res = [x for lst in a for x in lst]

Check if the elements of a range are within a list of lists

I have a sorted list and a range contains multiple lists:
>>> n= [10, 20, 30, 40]
>>> m= [[1, 20], [21, 30]]
What I am trying to do is to check if all the elements of the n list are within either of the existing ranges in m or not. For instance, from the above example, 40 is not within any of the ranges.
I tried to extend the answer to the question in the following post, but seems it is not working.
Checking if all elements of a List of Lists are in another List of Lists Python
is_there = set(tuple(x) for x in [n]).issubset(tuple(x) for x in m)
You should go through each element in n and check if it's in the range of each list of m. Assuming you are only working with ints:
[any(x in range(r[0], r[1]) for r in m) for x in n]
If you want to include the end of your range, just add 1:
[any(x in range(r[0], r[1]+1) for r in m) for x in n]
The simple approach is to check all the elements:
items = [10, 20, 30, 40]
ranges = [[1, 20], [21, 30]]
result = all(any(low <= i <= high for low, high in ranges) for i in items)
For fun, you can make the containment check a bit different by using actual range objects:
range_objects = [range(low, high + 1) for low, high in ranges]
filtered_items = all(any(i in r for r in range_objects) for i in items)
If you wanted to get the matching items:
good = [i for i in items if any(low <= i <= high for low, high in ranges)]
You could also get the bad elements instead:
bad = [i for i in items if all(i < low or i > high for low, high in ranges)]
That way, your original result is just not bad.
Since you said, "a sorted list", you can use the following logic of min and max. The outside will be True if any of the elements in n will be outside the given ranges. It will be False, if none of the elements is outside the ranges
n= [10, 20, 30, 40] # < as per you, this is sorted
m= [[1,20], [21,30]]
outside = any([(min(n) < i[0] and max(n)> i[1]) for i in m])
# True
Edit Answering the test case asked by #Peter DeGlopper in the comment below
m = [[1, 20], [31, 40]]
n = [10, 20, 25, 30, 40]
outside = any([(l < i < r for i in n) for l, r in m])
# True

Python: form a list based on the same values

consider x = [10,10,20,20,20,30]
How do i form another list_x1 which contains only same values example: list_x1 = [10,10]
and list_x2 =[20,20] and list_x3 =[30] ?
You can use counter.
from collections import Counter
x = [10, 10, 20, 20, 20, 30]
my_counter = Counter(x)
d = {'list_x{0}'.format(key): [key] * my_counter[key] for key in my_counter}
>>> d
{'list_x10': [10, 10], 'list_x20': [20, 20, 20], 'list_x30': [30]}
One of the issues with your request is that you would need to pre-assign variables, which aren't initially know. I've used a dictionary as a container to hold them.
For a list, [10] * 3 results in [10, 10, 10]. So, [k] * my_counter multiplies the unique key value by the number of occurrences.
With itertools.groupby
>>> from itertools import groupby
>>> x = [10,10,20,20,20,30]
>>> [list(g) for k, g in groupby(x)]
[[10, 10], [20, 20, 20], [30]]
Perhaps the best way is #Alexander's idea with collections, but I always find it helpful to look at more 'native' python code to see what's going on. So here's a way to do it:
x = [10,10,20,20,20,30]
def foo(iterable):
for val in iterable:
cnt = iterable.count(val)
iterable = list(filter(lambda x: x != val, iterable))
if cnt:
yield [val]*cnt
for _ in foo(x):
print(_)
Note that the complexity factor is going to be fairly high. Certainly not O(n) because you have to:
Iterate through each of the values in our main for val in iterable
Iterate through each of the values every time we call iterable.count
Iterate through each of the values when we filter() them to prevent duplicates.
Using collections.Counter:
>>> def list_gen(in_list, elem):
... count = collections.Counter(in_list)
... return [elem] * count[elem]
...
>>> a
[1, 2, 3, 2, 3]
>>> list_gen(a, 2)
[2, 2]
This isn't exactly what you're looking for, but this code will generate a list of lists separating the values.
x = [10, 10, 20, 20, 20, 30]
uniques = set(x)
output = []
for unique in uniques:
unique_count = x.count(unique)
temp = []
for i in range(0, unique_count):
temp.append(unique)
output.append(temp)
You can then use list comprehensions on output

First common element from two lists

x = [8,2,3,4,5]
y = [6,3,7,2,1]
How to find out the first common element in two lists (in this case, "2") in a concise and elegant way? Any list can be empty or there can be no common elements - in this case None is fine.
I need this to show python to someone who is new to it, so the simpler the better.
UPD: the order is not important for my purposes, but let's assume I'm looking for the first element in x that also occurs in y.
This should be straight forward and almost as effective as it gets (for more effective solution check Ashwini Chaudharys answer and for the most effective check jamylaks answer and comments):
result = None
# Go trough one array
for i in x:
# The element repeats in the other list...
if i in y:
# Store the result and break the loop
result = i
break
Or event more elegant would be to encapsulate the same functionality to functionusing PEP 8 like coding style conventions:
def get_first_common_element(x,y):
''' Fetches first element from x that is common for both lists
or return None if no such an element is found.
'''
for i in x:
if i in y:
return i
# In case no common element found, you could trigger Exception
# Or if no common element is _valid_ and common state of your application
# you could simply return None and test return value
# raise Exception('No common element found')
return None
And if you want all common elements you can do it simply like this:
>>> [i for i in x if i in y]
[1, 2, 3]
A sort is not the fastest way of doing this, this gets it done in O(N) time with a set (hash map).
>>> x = [8,2,3,4,5]
>>> y = [6,3,7,2,1]
>>> set_y = set(y)
>>> next((a for a in x if a in set_y), None)
2
Or:
next(ifilter(set(y).__contains__, x), None)
This is what it does:
>>> def foo(x, y):
seen = set(y)
for item in x:
if item in seen:
return item
else:
return None
>>> foo(x, y)
2
To show the time differences between the different methods (naive approach, binary search an sets), here are some timings. I had to do this to disprove the suprising number of people that believed binary search was faster...:
from itertools import ifilter
from bisect import bisect_left
a = [1, 2, 3, 9, 1, 1] * 100000
b = [44, 11, 23, 9, 10, 99] * 10000
c = [1, 7, 2, 4, 1, 9, 9, 2] * 1000000 # repeats early
d = [7, 6, 11, 13, 19, 10, 19] * 1000000
e = range(50000)
f = range(40000, 90000) # repeats in the middle
g = [1] * 10000000 # no repeats at all
h = [2] * 10000000
from random import randrange
i = [randrange(10000000) for _ in xrange(5000000)] # some randoms
j = [randrange(10000000) for _ in xrange(5000000)]
def common_set(x, y, ifilter=ifilter, set=set, next=next):
return next(ifilter(set(y).__contains__, x), None)
pass
def common_b_sort(x, y, bisect=bisect_left, sorted=sorted, min=min, len=len):
sorted_y = sorted(y)
for a in x:
if a == sorted_y[min(bisect_left(sorted_y, a),len(sorted_y)-1)]:
return a
else:
return None
def common_naive(x, y):
for a in x:
for b in y:
if a == b: return a
else:
return None
from timeit import timeit
from itertools import repeat
import threading, thread
print 'running tests - time limit of 20 seconds'
for x, y in [('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'h'), ('i', 'j')]:
for func in ('common_set', 'common_b_sort', 'common_naive'):
try:
timer = threading.Timer(20, thread.interrupt_main) # 20 second time limit
timer.start()
res = timeit(stmt="print '[', {0}({1}, {2}), ".format(func, x, y),
setup='from __main__ import common_set, common_b_sort, common_naive, {0}, {1}'.format(x, y),
number=1)
except:
res = "Too long!!"
finally:
print '] Function: {0}, {1}, {2}. Time: {3}'.format(func, x, y, res)
timer.cancel()
The test data was:
a = [1, 2, 3, 9, 1, 1] * 100000
b = [44, 11, 23, 9, 10, 99] * 10000
c = [1, 7, 2, 4, 1, 9, 9, 2] * 1000000 # repeats early
d = [7, 6, 11, 13, 19, 10, 19] * 1000000
e = range(50000)
f = range(40000, 90000) # repeats in the middle
g = [1] * 10000000 # no repeats at all
h = [2] * 10000000
from random import randrange
i = [randrange(10000000) for _ in xrange(5000000)] # some randoms
j = [randrange(10000000) for _ in xrange(5000000)]
Results:
running tests - time limit of 20 seconds
[ 9 ] Function: common_set, a, b. Time: 0.00569520707241
[ 9 ] Function: common_b_sort, a, b. Time: 0.0182240340602
[ 9 ] Function: common_naive, a, b. Time: 0.00978832505249
[ 7 ] Function: common_set, c, d. Time: 0.249175872911
[ 7 ] Function: common_b_sort, c, d. Time: 1.86735751332
[ 7 ] Function: common_naive, c, d. Time: 0.264309220865
[ 40000 ] Function: common_set, e, f. Time: 0.00966861710078
[ 40000 ] Function: common_b_sort, e, f. Time: 0.0505980508696
[ ] Function: common_naive, e, f. Time: Too long!!
[ None ] Function: common_set, g, h. Time: 1.11300018578
[ None ] Function: common_b_sort, g, h. Time: 14.9472068377
[ ] Function: common_naive, g, h. Time: Too long!!
[ 5411743 ] Function: common_set, i, j. Time: 1.88894859542
[ 5411743 ] Function: common_b_sort, i, j. Time: 6.28617268396
[ 5411743 ] Function: common_naive, i, j. Time: 1.11231867458
This gives you an idea of how it will scale for larger inputs, O(N) vs O(N log N) vs O(N^2)
One liner, using next to take the first item from a generator:
x = [8,2,3,4,5]
y = [6,3,7,2,1]
first = next((a for a in x if a in y), None)
Or more efficiently since set.__contains__ is faster than list.__contains__:
set_y = set(y)
first = next((a for a in x if a in set_y), None)
Or more efficiently but still in one line (don't do this):
first = next((lambda set_y: a for a in x if a in set_y)(set(y)), None)
Using a for loops with in will result in a O(N^2) complexity, but you can sort y here and use binary search to improve the time complexity to O(NlogN).
def binary_search(lis,num):
low=0
high=len(lis)-1
ret=-1 #return -1 if item is not found
while low<=high:
mid=(low+high)//2
if num<lis[mid]:
high=mid-1
elif num>lis[mid]:
low=mid+1
else:
ret=mid
break
return ret
x = [8,2,3,4,5]
y = [6,3,7,2,1]
y.sort()
for z in x:
ind=binary_search(y,z)
if ind!=-1
print z
break
output:
2
Using the bisect module to perform the same thing as above:
import bisect
x = [8,2,3,4,5]
y = [6,3,7,2,1]
y.sort()
for z in x:
ind=bisect.bisect(y,z)-1 #or use `ind=min(bisect.bisect_left(y, z), len(y) - 1)`
if ind!=-1 and y[ind] ==z:
print z #prints 2
break
I assume you want to teach this person Python, not just programming. Therefore I do not hesitate to use zip instead of ugly loop variables; it's a very useful part of Python and not hard to explain.
def first_common(x, y):
common = set(x) & set(y)
for current_x, current_y in zip(x, y):
if current_x in common:
return current_x
elif current_y in common:
return current_y
print first_common([8,2,3,4,5], [6,3,7,2,1])
If you really don't want to use zip, here's how to do it without:
def first_common2(x, y):
common = set(x) & set(y)
for i in xrange(min(len(x), len(y))):
if x[i] in common:
return x[i]
elif y[i] in common:
return y[i]
And for those interested, this is how it extends to any number of sequences:
def first_common3(*seqs):
common = set.intersection(*[set(seq) for seq in seqs])
for current_elements in zip(*seqs):
for element in current_elements:
if element in common:
return element
Finally, please note that, in contrast to some other solutions, this works as well if the first common element appears first in the second list.
I just noticed your update, which makes for an even simpler solution:
def first_common4(x, y):
ys = set(y) # We don't want this to be recreated for each element in x
for element in x:
if element in ys:
return element
The above is arguably more readable than the generator expression.
Too bad there is no built-in ordered set. It would have made for a more elegant solution.
Using for loops seems easiest to explain to someone new.
for number1 in x:
for number2 in y:
if number1 == number2:
print number1, number2
print x.index(number1), y.index(number2)
exit(0)
print "No common numbers found."
NB Not tested, just out of my head.
This one uses sets. It returns the first common element or None if no common element.
def findcommon(x,y):
common = None
for i in range(0,max(len(x),len(y))):
common = set(x[0:i]).intersection(set(y[0:i]))
if common: break
return list(common)[0] if common else None
def first_common_element(x,y):
common = set(x).intersection(set(y))
if common:
return x[min([x.index(i)for i in common])]
Just for fun (probably not efficient), another version using itertools:
from itertools import dropwhile, product
from operator import __ne__
def accept_pair(f):
"Make a version of f that takes a pair instead of 2 arguments."
def accepting_pair(pair):
return f(*pair)
return accepting_pair
def get_first_common(x, y):
try:
# I think this *_ unpacking syntax works only in Python 3
((first_common, _), *_) = dropwhile(
accept_pair(__ne__),
product(x, y))
except ValueError:
return None
return first_common
x = [8, 2, 3, 4, 5]
y = [6, 3, 7, 2, 1]
print(get_first_common(x, y)) # 2
y = [6, 7, 1]
print(get_first_common(x, y)) # None
It is simpler, but not as fun, to use lambda pair: pair[0] != pair[1] instead of accept_pair(__ne__).
Use set - this is the generic solution for arbitrary number of lists:
def first_common(*lsts):
common = reduce(lambda c, l: c & set(l), lsts[1:], set(lsts[0]))
if not common:
return None
firsts = [min(lst.index(el) for el in common) for lst in lsts]
index_in_list = min(firsts)
trgt_lst_index = firsts.index(index_in_list)
return lsts[trgt_lst_index][index_in_list]
An afterthought - not an effective solution, this one reduces redundant overhead
def first_common(*lsts):
common = reduce(lambda c, l: c & set(l), lsts[1:], set(lsts[0]))
if not common:
return None
for lsts_slice in itertools.izip_longest(*lsts):
slice_intersection = common.intersection(lsts_slice)
if slice_intersection:
return slice_intersection.pop()

How does one find the largest consecutive set of numbers in a list that are not necessarily adjacent?

For instance, if I have a list
[1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11]
This algorithm should return [1,2,3,4,5,6,7,8,9,10,11].
To clarify, the longest list should run forwards. I was wondering what is an algorithmically efficient way to do this (preferably not O(n^2))?
Also, I'm open to a solution not in python since the algorithm is what matters.
Thank you.
Here is a simple one-pass O(n) solution:
s = [1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11,42]
maxrun = -1
rl = {}
for x in s:
run = rl[x] = rl.get(x-1, 0) + 1
print x-run+1, 'to', x
if run > maxrun:
maxend, maxrun = x, run
print range(maxend-maxrun+1, maxend+1)
The logic may be a little more self-evident if you think in terms of ranges instead of individual variables for the endpoint and run length:
rl = {}
best_range = xrange(0)
for x in s:
run = rl[x] = rl.get(x-1, 0) + 1
r = xrange(x-run+1, x+1)
if len(r) > len(best_range):
best_range = r
print list(best_range)
Not that clever, not O(n), could use a bit of optimization. But it works.
def longest(seq):
result = []
for v in seq:
for l in result:
if v == l[-1] + 1:
l.append(v)
else:
result.append([v])
return max(result, key=len)
You can use The Patience Sort implementation of the Largest Ascending Sub-sequence Algorithm
def LargAscSub(seq):
deck = []
for x in seq:
newDeck = [x]
i = bisect.bisect_left(deck, newDeck)
deck[i].insert(0, x) if i != len(deck) else deck.append(newDeck)
return [p[0] for p in deck]
And here is the Test results
>>> LargAscSub([1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11])
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> LargAscSub([1, 2, 3, 11, 12, 13, 14])
[1, 2, 3, 11, 12, 13, 14]
>>> LargAscSub([11,12,13,14])
[11, 12, 13, 14]
The Order of Complexity is O(nlogn)
There was one note in the wiki link where they claimed that you can achieve O(n.loglogn) by relying on Van Emde Boas tree
How about using a modified Radix Sort? As JanneKarila pointed out the solution is not O(n). It uses Radix sort, which wikipedia says Radix sort's efficiency is O(k·n) for n keys which have k or fewer digits.
This will only work if you know the range of numbers that we're dealing with so that will be the first step.
Look at each element in starting list to find lowest, l and highest, h number. In this case l is 1 and h is 11. Note, if you already know the range for some reason, you can skip this step.
Create a result list the size of our range and set each element to null.
Look at each element in list and add them to the result list at the appropriate place if needed. ie, the element is a 4, add a 4 to the result list at position 4. result[element] = starting_list[element]. You can throw out duplicates if you want, they'll just be overwritten.
Go through the result list to find the longest sequence without any null values. Keep a element_counter to know what element in the result list we're looking at. Keep a curr_start_element set to the beginning element of the current sequence and keep a curr_len of how long the current sequence is. Also keep a longest_start_element and a `longest_len' which will start out as zero and be updated as we move through the list.
Return the result list starting at longest_start_element and taking longest_len
EDIT: Code added. Tested and working
#note this doesn't work with negative numbers
#it's certainly possible to write this to work with negatives
# but the code is a bit hairier
import sys
def findLongestSequence(lst):
#step 1
high = -sys.maxint - 1
for num in lst:
if num > high:
high = num
#step 2
result = [None]*(high+1)
#step 3
for num in lst:
result[num] = num
#step 4
curr_start_element = 0
curr_len = 0
longest_start_element = -1
longest_len = -1
for element_counter in range(len(result)):
if result[element_counter] == None:
if curr_len > longest_len:
longest_start_element = curr_start_element
longest_len = curr_len
curr_len = 0
curr_start_element = -1
elif curr_start_element == -1:
curr_start_element = element_counter
curr_len += 1
#just in case the last element makes the longest
if curr_len > longest_len:
longest_start_element = curr_start_element
longest_len = curr_len
#step 5
return result[longest_start_element:longest_start_element + longest_len-1]
If the result really does have to be a sub-sequence of consecutive ascending integers, rather than merely ascending integers, then there's no need to remember each entire consecutive sub-sequence until you determine which is the longest, you need only remember the starting and ending values of each sub-sequence. So you could do something like this:
def longestConsecutiveSequence(sequence):
# map starting values to largest ending value so far
map = collections.OrderedDict()
for i in sequence:
found = False
for k, v in map.iteritems():
if i == v:
map[k] += 1
found = True
if not found and i not in map:
map[i] = i + 1
return xrange(*max(map.iteritems(), key=lambda i: i[1] - i[0]))
If I run this on the original sample date (i.e. [1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11]) I get:
>>> print list(longestConsecutiveSequence([1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11]))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
If I run it on one of Abhijit's samples [1,2,3,11,12,13,14], I get:
>>> print list(longestConsecutiveSequence([1,2,3,11,12,13,14]))
[11, 12, 13, 14]
Regrettably, this algorithm is O(n*n) in the worst case.
Warning: This is the cheaty way to do it (aka I use python...)
import operator as op
import itertools as it
def longestSequence(data):
longest = []
for k, g in it.groupby(enumerate(set(data)), lambda(i, y):i-y):
thisGroup = map(op.itemgetter(1), g)
if len(thisGroup) > len(longest):
longest = thisGroup
return longest
longestSequence([1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11, 15,15,16,17,25])
You need the Maximum contiguous sum(Optimal Substructure):
def msum2(a):
bounds, s, t, j = (0,0), -float('infinity'), 0, 0
for i in range(len(a)):
t = t + a[i]
if t > s: bounds, s = (j, i+1), t
if t < 0: t, j = 0, i+1
return (s, bounds)
This is an example of dynamic programming and is O(N)
O(n) solution works even if the sequence does not start from the first element.
Warning does not work if len(A) = 0.
A = [1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11]
def pre_process(A):
Last = {}
Arrow = []
Length = []
ArgMax = 0
Max = 0
for i in xrange(len(A)):
Arrow.append(i)
Length.append(0)
if A[i] - 1 in Last:
Aux = Last[A[i] - 1]
Arrow[i] = Aux
Length[i] = Length[Aux] + 1
Last[A[i]] = i
if Length[i] > Max:
ArgMax = i
Max = Length[i]
return (Arrow,ArgMax)
(Arr,Start) = pre_process(A)
Old = Arr[Start]
ToRev = []
while 1:
ToRev.append(A[Start])
if Old == Start:
break
Start = Old
New = Arr[Start]
Old = New
ToRev.reverse()
print ToRev
Pythonizations are welcome!!
Ok, here's yet another attempt in python:
def popper(l):
listHolders = []
pos = 0
while l:
appended = False
item = l.pop()
for holder in listHolders:
if item == holder[-1][0]-1:
appended = True
holder.append((item, pos))
if not appended:
pos += 1
listHolders.append([(item, pos)])
longest = []
for holder in listHolders:
try:
if (holder[0][0] < longest[-1][0]) and (holder[0][1] > longest[-1][1]):
longest.extend(holder)
except:
pass
if len(holder) > len(longest):
longest = holder
longest.reverse()
return [x[0] for x in longest]
Sample inputs and outputs:
>>> demo = list(range(50))
>>> shuffle(demo)
>>> demo
[40, 19, 24, 5, 48, 36, 23, 43, 14, 35, 18, 21, 11, 7, 34, 16, 38, 25, 46, 27, 26, 29, 41, 8, 31, 1, 33, 2, 13, 6, 44, 22, 17,
12, 39, 9, 49, 3, 42, 37, 30, 10, 47, 20, 4, 0, 28, 32, 45, 15]
>>> popper(demo)
[1, 2, 3, 4]
>>> demo = [1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11]
>>> popper(demo)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>>
This should do the trick (and is O(n)):
target = 1
result = []
for x in list:
for y in result:
if y[0] == target:
y[0] += 1
result.append(x)
For any starting number, this works:
result = []
for x in mylist:
matched = False
for y in result:
if y[0] == x:
matched = True
y[0] += 1
y.append(x)
if not matched:
result.append([x+1, x])
return max(result, key=len)[1:]

Categories