find second duplicate and period in a python list - python

I've a python list as this one [2, 5, 26, 37, 45, 12, 23, 37, 45, 12, 23, 37, 45, 12, 23, 37]. The real list is really long. The list repeat itself after a certain point in this case after 37. I have no problem finding the number at which it repeats, but i need to truncate the list at the second one. In this case the result would be [2, 5, 26, 37, 45, 12, 23, 37]. For finding the number (37 in this case) i use a function firstDuplicate() found on stackoverflow. Someone can help me ?
def firstDuplicate(a):
aset = set()
for i in a:
if i in aset:
return i
else:
aset.add(i)
pass
pass
pass
LIST = LIST[1:firstDuplicate(LIST)]

You can use the same basic idea of firstDuplicate() and create a generator that yields values until the dupe is found. Then pass it to list(), a loop, etc.
l = [2, 5, 26, 37, 45, 12, 23, 37, 45, 12, 23, 37, 45, 12, 23, 37]
def partitionAtDupe(l):
seen = set()
for n in l:
yield n
if n in seen:
break
seen.add(n)
list(partitionAtDupe(l))
# [2, 5, 26, 37, 45, 12, 23, 37]
It's not clear what should happen if there are no dupes. The code above will yield the whole list in that case.

A function to find the period size and length of repeated numbers should start from the end of the sequence of numbers. This will make it easier to ensure that there is a cycle up to the end of the list and avoid any concerns over non-periodic repetitions at the beginning of the list.
For example:
def getPeriod(seq):
lastPos = { n:p for p,n in enumerate(seq) }
prevPos = { n:p for p,n in enumerate(seq) if p<lastPos[n] }
period = 1
for n in reversed(seq):
if n not in prevPos: break
delta = lastPos[n] - prevPos[n]
if delta%period == 0 or period%delta == 0:
period = max(delta,period)
else: break
nonPeriodic = (i for i,(n,p) in enumerate(zip(seq[::-1],seq[-period-1::-1])) if n != p)
periodLength = next(nonPeriodic,0)
return period, periodLength
output:
seq = [2, 5, 26, 37, 45, 12, 23, 37, 45, 12, 23, 37, 45, 12, 23, 37]
period, periodLength = getPeriod(seq)
print(period,periodLength) # 4 9
print(seq[:-periodLength]) # [2, 5, 26, 37, 45, 12, 23]

Related

Python function that generates random arrays of integers not working

I need to create a function that generates random arrays of integers between a and b, inclusive, where a and b define the range and M and N define the size of the output array. I've done something but it seems that it's not properly working and I don't know exactly how can I define the size of the output array, where exactly to put M and N.....Here it's my code:
import random
def Rand(start, end, num):
res = []
for j in range(num):
res.append(random.randint(start, end))
return res
# Driver Code
num = 10
start = 20
end = 40
print(Rand(start, end, num))
You just need two nested loops (or a nested list comprehension)
For example:
import random
def random_array(start, end, a, b):
return [[random.randint(start, end) for _ in range(a)] for _ in range(b)]
# Driver Code
a = 10
b = 5
start = 20
end = 40
print(random_array(start, end, a, b))
Which, in my case, output:
[[35, 27, 30, 27, 26, 37, 38, 27, 36, 34], [24, 24, 29, 35, 27, 38, 38, 37, 24, 24], [35, 20, 38, 25, 26, 20, 31, 29, 27, 33], [37, 36, 34, 20, 27, 30, 33, 26, 24, 26], [28, 35, 20, 31, 33, 36, 29, 25, 36, 36]]
If you don't want to use list comprehensions (although you probably should), it would be the equivalent of:
def random_array(start, end, a, b):
res = []
for _ in range(b):
inner = []
for _ in range(a):
inner.append(random.randint(start, end))
res.append(inner)
return res
Final note: According to PEP-8 you shouldn't start a function name with a capital letter.

How to loop through an entire list randomly before looping again?

import random
list1 = [11, 22, 33, 44, 55]
for i in range(5):
random_number = random.randint(0,4)
print(list1[random_number])
I am trying to find a way to print an entire list randomly without printing duplicates of the list in the first loop. Then if I increase the range to 10, 15, 20, and so on, every 5 prints displays all the elements randomly and without duplicates(by duplicates i mean no duplicates for every group of 5 prints displayed) i.e. 22, 33, 11, 55, 44, 44, 11, 33, 22, 55, 33, 22, 55, 44, 11 ...
you could make a copy of the list, then pop elements out of the copy until it's empty, then 'reload' it by copying the original list again
import random
list1 = [11, 22, 33, 44, 55]
clonedList = list1.copy()
for i in range(5):
if len(clonedList == 0):
clonedList = list1.copy()
random_number = random.randint(0,len(clonedList)-1)
print(clonedList.pop(random_number))

Do you know why my bubblesort isn't working? [Python] [duplicate]

This question already has answers here:
Python: How can I make my implementation of bubble sort more time efficient?
(3 answers)
Why is Bubble Sort implementation looping forever?
(28 answers)
Closed 5 years ago.
I am trying to make a bubblesort in python from scratch, do you know why it is not working? I am getting the error list index out of range.
data = [1, 32, 50, 12, 14, 7, 45, 27, 18, 9, 19, 22, 51, 42, 4, 25, 13, 6, 21, 49, 41, 37]
def bubbleSort(alist):
length = len(alist)
for i in range(length):
first = alist[i]
second = alist[i + 1]
if first > second:
a, b = alist.index(first), alist.index(second)
alist[b], alist[a] = alist[a], alist[b]
return data
print(bubbleSort(data))
Thanks,
Scott
change your loop to:
for i in range(length-1):
since you grab alist[i + 1] max i should be 2 less than length of list
Check if you've handled the case for last element.
first = alist[i]
second = alist[i + 1]
The second line uses i+1. So, when i points to the last index of the list, the second element alist[i+1] seems to be out of list index.
Found the fix:
data = [1, 32, 50, 12, 14, 7, 45, 27, 18, 9, 19, 22, 51, 42, 4, 25, 13, 6, 21, 49, 41, 37]
def bubbleSort(alist):
length = len(alist) - 1
while sorted(alist) != alist:
for i in range(length):
first = alist[i]
second = alist[i + 1]
if first > second:
a, b = alist.index(first), alist.index(second)
alist[b], alist[a] = alist[a], alist[b]
return data
print(bubbleSort(data))

how to check if an element exists in a list of lists python

I have a list of lists that correspond to lines in file, with multiple columns.
[ [col1, col2, col3], [elem1, elem2, elem3], [elem4, elem5, elem6] ]
I want to check if (for example) elem3 is in any of the lists, and if it is, go into that list. (really I have a list of things I need to check, so it's a list that probably contains elem3, elem5, elem7.... etc)
the shortest way is to use list comprehensions and list comprehensions sometimes are more faster than simple for loop
your list:
list1 = [ ["col1", "col2", "col3"], ["elem1", "elem2", "elem3"], ["elem4", "elem5", "elem6"] ]
your element to find:
to_find = "col1"
your function to "go into that list":
def do_something(sub_list):
print (sub_list)
and the list comprehension that will find your element and call function with list that have it:
[do_something(sub_list) for sub_list in list1 if to_find in sub_list]
You can do something like this:
def in_list(list_of_lists, item):
for list_ in list_of_lists:
if item in list_:
return list_
EDIT:
Here is a recursive version for the heck of it:
def in_list(list_of_lists, item):
if not list_of_lists:
return None
if item in list_of_lists[0]:
return list_of_lists[0]
return in_list(list_of_lists[1:], item)
I came across a similar problem. I had a list of tuples, with tile numbers:
data = [(0, 0, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 0),
(0, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 0),
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)]
I needed to find out where in the list of tuples a particular tile number is located, so:
to_find = 42
for i in range(len(data)):
if to_find in data[i]:
print (i, data[i].index(to_find))
break

function not returning list

I have a simple script to generate UK lottery numbers (7 numbers, 1 to 49 inclusive).
My code has a function that generates 7 random numbers into a list, runs set on the list removing duplicate numbers, checks if there are still 7 members in the list, and if not the function calls itself to generate 7 new numbers.
However, when the function calls itself it does not return the list.
I'd appreciate knowing what I'm doing wrong here.
from random import randint
def lotto():
l = []
for r in range(1,8):
l.append(randint(1,49))
print "DEBUG: l=", l
print "DEBUG: set(l)=", set(l), len(set(l))
if(len(set(l)) !=7):
lotto()
else:
print "Before return l, l = ", l
return l
def main():
numbers = lotto()
print numbers
Here is a sample run that does not work correctly:
DEBUG: l= [44, 32, 12, 12, 33, 16, 31]
DEBUG: set(l)= set([32, 33, 44, 12, 16, 31]) 6
DEBUG: l= [46, 20, 10, 24, 16, 35, 44]
DEBUG: set(l)= set([35, 10, 44, 46, 16, 20, 24]) 7
Before return l, l = [46, 20, 10, 24, 16, 35, 44]
None
And a sample run that does work correctly:
DEBUG: l= [20, 5, 21, 37, 10, 44, 38]
DEBUG: set(l)= set([37, 38, 10, 44, 20, 21, 5]) 7
Before return l, l = [20, 5, 21, 37, 10, 44, 38]
[20, 5, 21, 37, 10, 44, 38]
You're not returning the result of the recursive call.
if(len(set(l)) !=7):
return lotto()
The recursive call
lotto()
does not actually return the value returned by lotto(). You'd need to use
return lotto()
instead. (Note that instead of the tail-recursive call, a loop would be preferable.)
That said, there is a much easier solution to your actual problem, namely random.sample(). Python2.x version:
import random
print random.sample(xrange(1, 50), 7)
Python 3.x version:
import random
print(random.sample(range(1, 50), 7))

Categories