How to generalize the Australian shuffle? - python

def australian(deck,n):
i=0
s=deck
if len(deck) < 12:
while i < n :
i=i+1
s=s[0::2]+s[1::4]+s[3::4]
s=s[::-1]
return(s)
if len(deck) < 26:
while i<n:
i=i+1
s=s[0::2]+s[1::4]+s[3::8]+s[7::8]
s=s[::-1]
return(s)
if len (deck) < 48:
while i<n:
i=i+1
s=s[0::2]+s[1::4]+s[3::8]+s[7:8]+s[15:16]
s=s[::-1]
return(s)
this is my first code for the Australian shuffle. I wanted to generalize it to make it work for a bigger deck.
I wrote a second code with a method that should work, but I can't figure out how to put it in a loop for it to work with all combinations.
def Down_Under_shufffle(lst):
basic=lst[0::2]#les impaires
length = len(basic)
middle_index = length//2#list/4 :: middle index = 4
s=basic[:middle_index]
s1=s[:2]
s2=s1[:1]
s3=s2[:1]
a = [element * (2**1) for element in s]#multiplie les elemnts
a1= [element * (2**2) for element in s1]
a2 = [element * (2**3) for element in s2]
a3= [element * (2**4) for element in s3]
toto=basic+a+a1+a2+a3
toto=toto[::-1]
return(toto)
print(Down_Under_shufffle([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]))

I think the whole thing can be simplified. Below there are two approaches
This deals the items in arr one by one:
def down_under_shuffle_items( arr ):
a = arr.copy() # arr would be destroyed without this step.
result = []
while len( a ) > 1:
result.append( a.pop( 0 ) ) # Remove the top item and append to result
a.append( a.pop( 0 ) ) # Remove the new top item and append to the end of a
return result + a # If a is empty this adds nothing
This deals all the even items, for me [0::2] are even, and removes them from a. It then continues to loop as long as a has more than one item in it.
If the length of a is less than the length of dealt the first card in a needs to be removed and then added to the end of a. This was faster when I tested it.
def down_under_shuffle( arr ):
a = arr.copy() # arr would be destroyed without this step
result = []
while len( a ) > 1: # Loop while a isn't empty
dealt = a[ :: 2 ] # deal the even cards
a = a[ 1::2 ] # Keep the odd cards
result += dealt # add dealt cards to result
if len( a ) < len( dealt ): # If the last card was dealt, move a[0] to a[-1], rotating a
a.append( a.pop(0) )
return result + a # If a is empty this adds nothing
Results:
deck = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]
down_under_shuffle_items( deck )
# [0, 2, 4, 6, 8, 10, 1, 5, 9, 3, 11, 7]
down_under_shuffle( deck )
# [0, 2, 4, 6, 8, 10, 1, 5, 9, 3, 11, 7]

Related

How to rearrange list in python

I want to rearrange my list in python but there are some rules about it. These next few pictures describe how beavers jump into a hole, while others go accross and the ones in the hole go out.
Original array
Beavers fill in the hole
Others go accross
Everyone else come out
Now there's where it gets complicated. What if i have more than 1 hole. I've managed to figure out everything myself up to this point. Now all i'm asking is how would any of you approach this and if there's any tricks i could use for sorting the list. This is my code so far:
bobri = "54321"
luknje = [4, 2, 4]
bobri_original = bobri
bobri_original_list = list(bobri_original)
bobri_list = list(bobri)
i = 1
gli = 0
for st in range(len(luknje)):
i = 1
globina = luknje[st]
# Prvega zapisem in zbrisem iz glavnega seznama
last_bober = bobri_list[-1]
bobri_list.remove(str(last_bober))
bobri_luknja = [last_bober]
if globina == 1:
for n in range(len(bobri_list)):
bobri_luknja.append(bobri_list[n])
bobri_list = bobri_luknja
else:
while i <= globina - 1:
last_bober = bobri_list[-1]
bobri_list.remove(str(last_bober))
bobri_luknja.append(last_bober)
if i == globina - 1:
for n in range(len(bobri_list)):
bobri_luknja.append(bobri_list[n])
bobri_list = bobri_luknja
i += 1
gli += 1
Zdravo (:
def cross_all_holes(initial_list, hole_depths=[]):
# Crossing single hole function.
def cross_the_hole(current_list, hole_depth):
hole_is_filled = False
list_len = len(current_list)
result_list = []
hole = []
# While not result list contain all the items
while len(result_list) < list_len:
# Filling the hole
if not hole_is_filled:
element = current_list.pop()
hole.append(element)
# Checking if it's filled
hole_is_filled = len(hole) == hole_depth
else:
# Crossing the filled hole
if len(current_list):
element = current_list.pop()
# Emptying hole
elif len(hole):
element = hole.pop()
result_list = [element] + result_list
return result_list
# Repeat as much as needed.
current_list = initial_list
for hole_depth in hole_depths:
current_list = cross_the_hole(current_list, hole_depth)
return current_list
Thanks for the task, it was funny (:
In [20]: cross_all_holes([1,2,3,4,5,6,7,8,9,10], [1,3])
Out[20]: [9, 8, 7, 10, 1, 2, 3, 4, 5, 6]
Never thought I would write a function with inputs as 'beavers' and 'holes', but thanks for this moment. The beavers is simply the list of the number of each beaver, and holes is the list with each hole, and the amount of beavers getting into each:
def rearrange(beavers, holes):
l = len(beavers)
for n in range(len(holes)):
back = beavers[-holes[n]:][::-1]
front = beavers[:l - holes[n]]
beavers = back + front
return(beavers)
rearrange([7,6,5,4,3,2,1], [3])
Out: [1, 2, 3, 7, 6, 5, 4]
rearrange([7,6,5,4,3,2,1], [3,4])
Out: [4, 5, 6, 7, 1, 2, 3]

Check if values in list exceed threshold a certain amount of times and return index of first exceedance

I am searching for a clean and pythonic way of checking if the contents of a list are greater than a given number (first threshold) for a certain number of times (second threshold). If both statements are true, I want to return the index of the first value which exceeds the given threshold.
Example:
# Set first and second threshold
thr1 = 4
thr2 = 5
# Example 1: Both thresholds exceeded, looking for index (3)
list1 = [1, 1, 1, 5, 1, 6, 7, 3, 6, 8]
# Example 2: Only threshold 1 is exceeded, no index return needed
list2 = [1, 1, 6, 1, 1, 1, 2, 1, 1, 1]
I don't know if it's considered pythonic to abuse the fact that booleans are ints but I like doing like this
def check(l, thr1, thr2):
c = [n > thr1 for n in l]
if sum(c) >= thr2:
return c.index(1)
Try this:
def check_list(testlist)
overages = [x for x in testlist if x > thr1]
if len(overages) >= thr2:
return testlist.index(overages[0])
# This return is not needed. Removing it will not change
# the outcome of the function.
return None
This uses the fact that you can use if statements in list comprehensions to ignore non-important values.
As mentioned by Chris_Rands in the comments, the return None is unnecessary. Removing it will not change the result of the function.
If you are looking for a one-liner (or almost)
a = filter(lambda z: z is not None, map(lambda (i, elem) : i if elem>=thr1 else None, enumerate(list1)))
print a[0] if len(a) >= thr2 else false
A naive and straightforward approach would be to iterate over the list counting the number of items greater than the first threshold and returning the index of the first match if the count exceeds the second threshold:
def answer(l, thr1, thr2):
count = 0
first_index = None
for index, item in enumerate(l):
if item > thr1:
count += 1
if not first_index:
first_index = index
if count >= thr2: # TODO: check if ">" is required instead
return first_index
thr1 = 4
thr2 = 5
list1 = [1, 1, 1, 5, 1, 6, 7, 3, 6, 8]
list2 = [1, 1, 6, 1, 1, 1, 2, 1, 1, 1]
print(answer(list1, thr1, thr2)) # prints 3
print(answer(list2, thr1, thr2)) # prints None
This is probably not quite pythonic though, but this solution has couple of advantages - we keep the index of the first match only and have an early exit out of the loop if we hit the second threshold.
In other words, we have O(k) in the best case and O(n) in the worst case, where k is the number of items before reaching the second threshold; n is the total number of items in the input list.
I don't know if I'd call it clean or pythonic, but this should work
def get_index(list1, thr1, thr2):
cnt = 0
first_element = 0
for i in list1:
if i > thr1:
cnt += 1
if first_element == 0:
first_element = i
if cnt > thr2:
return list1.index(first_element)
else:
return "criteria not met"
thr1 = 4
thr2 = 5
list1 = [1, 1, 1, 5, 1, 6, 7, 3, 6, 8]
list2 = [1, 1, 6, 1, 1, 1, 2, 1, 1, 1]
def func(lst)
res = [ i for i,j in enumerate(lst) if j > thr1]
return len(res)>=thr2 and res[0]
Output:
func(list1)
3
func(list2)
false

the path complexity (fastest route) to any given number in python

Today I went to a math competition and there was a question that was something like this:
You have a given number n, now you have to like calculate what's the shortest route to that number, but there are rules.
You start with number 1
You end when you reach n
You can get to n either by doubling your previous number, or by adding two previous numbers.
Example: n = 25
Slowest route : 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25
(You just keep adding 1)
Fastest route : 1,2,4,8,16,24,25, complexity = 6
Example: n = 8
Fastest route : 1,2,4,8, complexity = 3
Example : n = 15
Fastest route : 1,2,3,6,9,15, complexity = 5
How do I make a program that can calculate the complexity of a given number n (with n <= 32)?
I already know that for any given number n ( n <= 32 ) that the complexity is lower that 1.45 x 2log(n).
So now I only need to calculate all the routes with complexity below 1.45 x 2log(n) and than compare them and see which one is the fastest 'route'.
But I have no idea how to put all the routes and all this in python, because the number of routes changes when the given number n changes.
This is what I have for now:
number = raw_input('Enter your number here : ')
startnumber = 1
complexity = 0
while startnumber <= number
I accept the challenge :)
The algorithm is relatively fast. It calculates the complexity of the first 32 numbers in 50ms on my computer, and I don't use multithreading. (or 370ms for the first 100 numbers.)
It is a recursive branch and cut algorithm. The _shortest function takes 3 arguments: the optimization lies in the max_len argument. E.g. if the function finds a solution with length=9, it stops considering any paths with a length > 9. The first path that is found is always a pretty good one, which directly follows from the binary representation of the number. E.g. in binary: 111001 => [1,10,100,1000,10000,100000,110000,111000,111001]. That's not always the fastest path, but if you only search for paths that are as least as fast, you can cut away most of the search tree.
#!/usr/bin/env python
# Find the shortest addition chain...
# #param acc List of integers, the "accumulator". A strictly monotonous
# addition chain with at least two elements.
# #param target An integer > 2. The number that should be reached.
# #param max_len An integer > 2. The maximum length of the addition chain
# #return A addition chain starting with acc and ending with target, with
# at most max_len elements. Or None if such an addition chain
# does not exist. The solution is optimal! There is no addition
# chain with these properties which can be shorter.
def _shortest(acc, target, max_len):
length = len(acc)
if length > max_len:
return None
last = acc[-1]
if last == target:
return acc;
if last > target:
return None
if length == max_len:
return None
last_half = (last / 2)
solution = None
potential_solution = None
good_len = max_len
# Quick check: can we make this work?
# (this improves the performance considerably for target > 70)
max_value = last
for _ in xrange(length, max_len):
max_value *= 2
if max_value >= target:
break
if max_value < target:
return None
for i in xrange(length-1, -1, -1):
a = acc[i]
if a < last_half:
break
for j in xrange(i, -1, -1):
b = acc[j]
s = a+b
if s <= last:
break
# modifying acc in-place has much better performance than copying
# the list and doing
# new_acc = list(acc)
# potential_solution = _shortest(new_acc, target, good_len)
acc.append(s)
potential_solution = _shortest(acc, target, good_len)
if potential_solution is not None:
new_len = len(potential_solution)
solution = list(potential_solution)
good_len = new_len-1
# since we didn't copy the list, we have to truncate it to its
# original length now.
del acc[length:]
return solution
# Finds the shortest addition chain reaching to n.
# E.g. 9 => [1,2,3,6,9]
def shortest(n):
if n > 3:
# common case first
return _shortest([1,2], n, n)
if n < 1:
raise ValueError("n must be >= 1")
return list(xrange(1,n+1))
for i in xrange(1,33):
s = shortest(i)
c = len(s) - 1
print ("complexity of %2d is %d: e.g. %s" % (i,c,s))
Output:
complexity of 1 is 0: e.g. [1]
complexity of 2 is 1: e.g. [1, 2]
complexity of 3 is 2: e.g. [1, 2, 3]
complexity of 4 is 2: e.g. [1, 2, 4]
complexity of 5 is 3: e.g. [1, 2, 4, 5]
complexity of 6 is 3: e.g. [1, 2, 4, 6]
complexity of 7 is 4: e.g. [1, 2, 4, 6, 7]
complexity of 8 is 3: e.g. [1, 2, 4, 8]
complexity of 9 is 4: e.g. [1, 2, 4, 8, 9]
complexity of 10 is 4: e.g. [1, 2, 4, 8, 10]
complexity of 11 is 5: e.g. [1, 2, 4, 8, 10, 11]
complexity of 12 is 4: e.g. [1, 2, 4, 8, 12]
complexity of 13 is 5: e.g. [1, 2, 4, 8, 12, 13]
complexity of 14 is 5: e.g. [1, 2, 4, 8, 12, 14]
complexity of 15 is 5: e.g. [1, 2, 4, 5, 10, 15]
complexity of 16 is 4: e.g. [1, 2, 4, 8, 16]
complexity of 17 is 5: e.g. [1, 2, 4, 8, 16, 17]
complexity of 18 is 5: e.g. [1, 2, 4, 8, 16, 18]
complexity of 19 is 6: e.g. [1, 2, 4, 8, 16, 18, 19]
complexity of 20 is 5: e.g. [1, 2, 4, 8, 16, 20]
complexity of 21 is 6: e.g. [1, 2, 4, 8, 16, 20, 21]
complexity of 22 is 6: e.g. [1, 2, 4, 8, 16, 20, 22]
complexity of 23 is 6: e.g. [1, 2, 4, 5, 9, 18, 23]
complexity of 24 is 5: e.g. [1, 2, 4, 8, 16, 24]
complexity of 25 is 6: e.g. [1, 2, 4, 8, 16, 24, 25]
complexity of 26 is 6: e.g. [1, 2, 4, 8, 16, 24, 26]
complexity of 27 is 6: e.g. [1, 2, 4, 8, 9, 18, 27]
complexity of 28 is 6: e.g. [1, 2, 4, 8, 16, 24, 28]
complexity of 29 is 7: e.g. [1, 2, 4, 8, 16, 24, 28, 29]
complexity of 30 is 6: e.g. [1, 2, 4, 8, 10, 20, 30]
complexity of 31 is 7: e.g. [1, 2, 4, 8, 10, 20, 30, 31]
complexity of 32 is 5: e.g. [1, 2, 4, 8, 16, 32]
There is a dynamic programming solution to your problem since you either add any two numbers or multiply a number by 2 we can try all those cases and choose the minimum one also if the complexity of 25 was 5 and the route contains 9 then we know the solution for 9 which is 4 and we can use the solution for 9 to generate the solution for 25.We also need to keep track of every possible minimum solution for m to be able to use it to use it to solve n where m < n
def solve(m):
p = [set([frozenset([])]) for i in xrange(m+1)] #contains all paths to reach n
a = [9999 for _ in xrange(m+1)]
#contains all complexities initialized with a big number
a[1] = 0
p[1] = set([frozenset([1])])
for i in xrange(1,m+1):
for pos in p[i]:
for j in pos: #try adding any two numbers and 2*any number
for k in pos:
if (j+k <= m):
if a[j+k] > a[i]+1:
a[j+k] = a[i] + 1
p[j+k] = set([frozenset(list(pos) + [j+k])])
elif a[j+k] == a[i]+1:
p[j+k].add(frozenset(list(pos) + [j+k]))
return a[m],sorted(list(p[m].pop()))
n = int(raw_input())
print solve(n)
this can solve up to n = 100
For larger numbers you can get a 30% or more speedup by adding a couple lines to remove some redundant calculations from the inner loop. For this the pos2 variable is created and trimmed on each iteration:
def solve(m):
p = [set([frozenset([])]) for i in xrange(m+1)] #contains all paths to reach n
a = [9999 for _ in xrange(m+1)]
#contains all complexities initialized with a big number
a[1] = 0
p[1] = set([frozenset([1])])
for i in xrange(1,m+1):
for pos in p[i]:
pos2 = set(pos)
for j in pos: #try adding any two numbers and 2*any number
for k in pos2:
if (j+k <= m):
if a[j+k] > a[i]+1:
a[j+k] = a[i] + 1
p[j+k] = set([frozenset(list(pos) + [j+k])])
elif a[j+k] == a[i]+1:
p[j+k].add(frozenset(list(pos) + [j+k]))
pos2.remove(j)
return a[m],sorted(list(p[m].pop()))
Brute forcing this
def solve(m, path):
if path[-1] == m:
return path
if path[-1] > m:
return False
best_path = [i for i in range(m)]
test_path = solve (m, path + [path[-1]*2])
if test_path and len(test_path) < len(best_path):
best_path = test_path
for k1 in path[:-1] :
for k2 in path[:-1] :
test_path = solve (m, path + [path[-1] + k1 + k2])
if test_path and len(test_path) < len(best_path):
#retain best
best_path = test_path
return best_path
print (solve(19, [1,2])) #[1, 2, 4, 8, 16, 19]
print (solve(25, [1,2])) #[1, 2, 4, 8, 16, 25]
Runs fairly slow, I'm pretty sure a smarter solution exist but this look semantically correct
A brute force technique that simply searches through all the possible paths until it reaches its target. It is extremely fast as it does not evaluate numbers that have been reached with a lower complexity, but is guaranteed to find the optimal path.
# Use a node class that contains the number as well as a pointer to its parent
class Node:
def __init__(self, number, parent):
self.number = number
self.parent = parent
# get a list of all the numbers to reach this node
def getPath(self):
path = [self.number]
parent = self.parent
while parent != None:
path.append(parent.number)
parent = parent.parent
return path
def solve(start, target):
currentList = [] # List of visited nodes in the previous round
nextList = [Node(start, None)] # List of visited nodes in the next round (start with at least one number)
seen = set([start]) # store all number that have already been seen in the previous round
while nextList: # continue until the final number has reached, on each iteration the complexity grows
currentList = nextList # swap the lists around
nextList = []
for n in currentList:
path = n.getPath() # fetch all the number that are needed to reach this point
if n.number == target: # check of we have reach our target
return path[::-1] # the path is in reverse at this point, so reverse it back
for a in path: # for any combination of the last number and a previous number (including the last, which is the same as multiplying it by 2)
newnumber = a + path[0]
if newnumber <= target and newnumber not in seen: # only evaluate the new number if is is not yet seen already on a lower complexity
nextList.append(Node(newnumber, n))
for n in nextList: # update the seen list
seen.add(n.number)
return [] # if the destination could not be reached
print "path to 25 = ", solve(1, 25)
print "path to 8 = ", solve(1, 8)
print "path to 15 = ", solve(1, 15)
print "path to 500 = ", solve(1, 500)
will output the following:
path to 25 = [1, 2, 4, 8, 16, 24, 25]
path to 8 = [1, 2, 4, 8]
path to 15 = [1, 2, 4, 5, 10, 15]
path to 500 = [1, 2, 4, 8, 16, 32, 64, 96, 100, 200, 400, 500]
I've tested this method to solve variables up to 500, and it was able to solve it in 0.36 seconds.

Python - iterating beginning with the middle of the list and then checking either side

Really not sure where this fits. Say, I have a list:
>>>a = [1, 2, 3, 4, 5, 6, 7]
How can I iterate it in such a way, that it will check 4 first, then 5, then 3, then 6, and then 2(and so on for bigger lists)? I have only been able to work out the middle which is
>>>middle = [len(a)/2 if len(a) % 2 = 0 else ((len(a)+1)/2)]
I'm really not sure how to apply this, nor am I sure that my way of working out the middle is the best way. I've thought of grabbing two indexes and after each iteration, adding 1 and subtracting 1 from each respective index but have no idea how to make a for loop abide by these rules.
With regards as to why I need this; it's for analysing a valid play in a card game and will check from the middle card of a given hand up to each end until a valid card can be played.
You can just keep removing from the middle of list:
lst = range(1, 8)
while lst:
print lst.pop(len(lst)/2)
This is not the best solution performance-wise (removing item from list is expensive), but it is simple - good enough for a simple game.
EDIT:
More performance stable solution would be a generator, that calculates element position:
def iter_from_middle(lst):
try:
middle = len(lst)/2
yield lst[middle]
for shift in range(1, middle+1):
# order is important!
yield lst[middle - shift]
yield lst[middle + shift]
except IndexError: # occures on lst[len(lst)] or for empty list
raise StopIteration
To begin with, here is a very useful general purpose utility to interleave two sequences:
def imerge(a, b):
for i, j in itertools.izip_longest(a,b):
yield i
if j is not None:
yield j
with that, you just need to imerge
a[len(a) / 2: ]
with
reversed(a[: len(a) / 2])
You could also play index games, for example:
>>> a = [1, 2, 3, 4, 5, 6, 7]
>>> [a[(len(a) + (~i, i)[i%2]) // 2] for i in range(len(a))]
[4, 5, 3, 6, 2, 7, 1]
>>> a = [1, 2, 3, 4, 5, 6, 7, 8]
>>> [a[(len(a) + (~i, i)[i%2]) // 2] for i in range(len(a))]
[4, 5, 3, 6, 2, 7, 1, 8]
Here's a generator that yields alternating indexes for any given provided length. It could probably be improved/shorter, but it works.
def backNforth(length):
if length == 0:
return
else:
middle = length//2
yield middle
for ind in range(1, middle + 1):
if length > (2 * ind - 1):
yield middle - ind
if length > (2 * ind):
yield middle + ind
# for testing:
if __name__ == '__main__':
r = range(9)
for _ in backNforth(len(r)):
print(r[_])
Using that, you can just do this to produce a list of items in the order you want:
a = [1, 2, 3, 4, 5, 6, 7]
a_prime = [a[_] for _ in backNforth(len(a))]
In addition to the middle elements, I needed their index as well. I found Wasowski's answer very helpful, and modified it:
def iter_from_middle(lst):
index = len(lst)//2
for i in range(len(lst)):
index = index+i*(-1)**i
yield index, lst[index]
>>> my_list = [10, 11, 12, 13, 14, 15]
>>> [(index, item) for index, item in iter_from_middle(my_list)]
[(3, 13), (2, 12), (4, 14), (1, 11), (5, 15), (0, 10)]

Python finding repeating sequence in list of integers?

I have a list of lists and each list has a repeating sequence. I'm trying to count the length of repeated sequence of integers in the list:
list_a = [111,0,3,1,111,0,3,1,111,0,3,1]
list_b = [67,4,67,4,67,4,67,4,2,9,0]
list_c = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,23,18,10]
Which would return:
list_a count = 4 (for [111,0,3,1])
list_b count = 2 (for [67,4])
list_c count = 10 (for [1,2,3,4,5,6,7,8,9,0])
Any advice or tips would be welcome. I'm trying to work it out with re.compile right now but, its not quite right.
Guess the sequence length by iterating through guesses between 2 and half the sequence length. If no pattern is discovered, return 1 by default.
def guess_seq_len(seq):
guess = 1
max_len = len(seq) / 2
for x in range(2, max_len):
if seq[0:x] == seq[x:2*x] :
return x
return guess
list_a = [111,0,3,1,111,0,3,1,111,0,3,1]
list_b = [67,4,67,4,67,4,67,4,2,9,0]
list_c = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,23,18,10]
print guess_seq_len(list_a)
print guess_seq_len(list_b)
print guess_seq_len(list_c)
print guess_seq_len(range(500)) # test of no repetition
This gives (as expected):
4
2
10
1
As requested, this alternative gives longest repeated sequence. Hence it will return 4 for list_b. The only change is guess = x instead of return x
def guess_seq_len(seq):
guess = 1
max_len = len(seq) / 2
for x in range(2, max_len):
if seq[0:x] == seq[x:2*x] :
guess = x
return guess
I took Maria's faster and more stackoverflow-compliant answer and made it find the largest sequence first:
def guess_seq_len(seq, verbose=False):
seq_len = 1
initial_item = seq[0]
butfirst_items = seq[1:]
if initial_item in butfirst_items:
first_match_idx = butfirst_items.index(initial_item)
if verbose:
print(f'"{initial_item}" was found at index 0 and index {first_match_idx}')
max_seq_len = min(len(seq) - first_match_idx, first_match_idx)
for seq_len in range(max_seq_len, 0, -1):
if seq[:seq_len] == seq[first_match_idx:first_match_idx+seq_len]:
if verbose:
print(f'A sequence length of {seq_len} was found at index {first_match_idx}')
break
return seq_len
This worked for me.
def repeated(L):
'''Reduce the input list to a list of all repeated integers in the list.'''
return [item for item in list(set(L)) if L.count(item) > 1]
def print_result(L, name):
'''Print the output for one list.'''
output = repeated(L)
print '%s count = %i (for %s)' % (name, len(output), output)
list_a = [111, 0, 3, 1, 111, 0, 3, 1, 111, 0, 3, 1]
list_b = [67, 4, 67, 4, 67, 4, 67, 4, 2, 9, 0]
list_c = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2,
3, 4, 5, 6, 7, 8, 9, 0, 23, 18, 10
]
print_result(list_a, 'list_a')
print_result(list_b, 'list_b')
print_result(list_c, 'list_c')
Python's set() function will transform a list to a set, a datatype that can only contain one of any given value, much like a set in algebra. I converted the input list to a set, and then back to a list, reducing the list to only its unique values. I then tested the original list for each of these values to see if it contained that value more than once. I returned a list of all of the duplicates. The rest of the code is just for demonstration purposes, to show that it works.
Edit: Syntax highlighting didn't like the apostrophe in my docstring.

Categories