I have a list of lists.
Each element of the list is made in this way [id1, id2, timex, value].
Given two external numbers ex and lx (ex < lx), I want to:
1. Check each element of the list, and see if timex < ex. If I find an element in which timex < ex, then I can end everything.
2. If I don't find it, then I want to make another check, starting for the first element of the list, and see if I can find an element in which ex < timex < lx.
3. If I don't find what said in point 2, I want to make another control and check whether there is an element with timex > lx.
What I did is this. But I want to know if there is a better way to do it.
f1 = 0
f2 = 0
found = False
# 1
count = 0
while (found == False) and (count < len(Listx)):
if Listx[count][2] <= ex:
print "Found - 1"
f1 = Listx[count][0]
f2 = Listx[count][1]
Listx[count][2] = Listx[count][2] + dx
found = True
count = count + 1
# 2
count = 0
while (found == False) and (count < len(Listx)):
if (Listx[count][2] > ex) and (Listx[count][2] <= lx):
print "Found - 2"
Listx[count][2] = Listx[count][2] + ex
f1 = Listx[count][0]
f2 = Listx[count][1]
found = True
count = count + 1
#3
count = 0
while (found == False) and (count < len(Listx)):
if (Listx[count][1] < lx):
f1 = Listx[count][0]
f2 = Listx[count][1]
found = True
count = count + 1
You don't necessarily need to index your list with 'count' every time, you can use for loops to iterate through. If you need that index for something else, you can use a for loop in the style of
for index, value in enumerate(lst):
# code
There are also some other modules that could help, depending on the nature of your data. See test if list contains a number in some range for examples of a few.
That said, here's my solution.
f1 = 0
f2 = 0
found = False
for element in Listx :
if element[2] <= ex:
print "Found - 1"
f1 = element[0]
f2 = element[1]
element[2] = element[2] + dx
found = True
break
if found = False:
for element in Listx :
if (element[2] > ex) and (element[2] <= lx):
print "Found - 2"
element[2] = element[2] + ex
f1 = element[0]
f2 = element[1]
found = True
break
if found = False:
for element in Listx :
if (element[1] < lx):
print "Found - 3"
f1 = element[0]
f2 = element[1]
found = True
break
You can write things a lot more compactly using for loops and for...else statements.
# 1
for item in Listx:
if item[2] <= ex:
print ("Found - 1")
f1, f2 = item[:2]
item[2] += dx
break
else:
# begin # 2 here...
The other loops can be similarly condensed. To describe the syntax going on here:
for x in y:
// ...
is essentially
i = 0
while i < len(y):
x = y[i]
// ...
i = i + 1
except that you don't get the i variable.
item[:1] uses list slicing to give us item[0], item[1].
Now something like a, b = x, y sets the variables respectively. It's shorthand for
a = x
b = y
Finally, break will break you out of the current loop immediately. The else is another fancy Python thing. The else code triggers when the previous loop was not broken out of.
I'll admit I used some "Pythonic" shortcuts above that use some of the features that I think makes Python great. :)
Related
I’d like to get the string having repetitive substrings consecutively more than x times. The substrings has more than y characters.
For example, when x=4, y=3,
BGGEFGEFGEFGEFFD satisfies the condition (= GEF * 4 consecutively).
On the other hand, when x=2, y=4,
GDCCCGDCCFDCC does not satisfies the condition since there is one C between GDCC.
Any suggestions to check if the given string satisfies the condition without importing packages? Thanks in advance.
This is what I’ve tried
counter = 0
for s in range(0, len(string),y):
if string[s : s+y] == string[s+y :s+y*2]:
counter +=1
if counter >= x:
print(‘TRUE’)
def is_expected_str(str_val, x, y):
match_found = False
split_strs = {}
index = 0
for i in str_val:
subs = str_val[index:(index + y)]
index = index + 1
if len(subs) < y:
continue
sub_count = split_strs.get(subs)
if sub_count is None:
match_count = 1
else:
match_count = split_strs[subs] + 1
split_strs[subs] = match_count
if match_count >= x:
match_found = True
print(split_strs)
return match_found
# print(subs)
rr = "BGGEFGEFGEFGEFFD"
res = is_expected_str(rr, x=4, y=3)
print(res)
Use dictionary to store the count information of sub strings
Let's say you have a list which only has two types of values and goes something like ['t','r','r','r','t','t','r','r','t'] and you want to find the length of the smallest sequence number of 'r's which have 't's at both ends.
In this case the smallest sequence of 'r' has a length of 2, because there is first t,r,r,r,t and then t,r,r,t, and the latter has the smallest number of 'r's in a row surrounded by 't' and the number of 'r's is 2.
How would I code for finding that number?
This is from a problem of trying of going to a play with your friend, and you want to sit as close as possible with your friend, so you are trying to find the smallest amount of taken seats in between two free seats at a play. "#" is a taken seat and a "." is a free seat. you are given the amount of seats, and the seating arrangement (free seats and taken seats), and they are all in one line.
An example of an input is:
5
#.##.
where there are two taken seats(##) in between two free seats.
Here is my code which is not working for inputs that I don't know, but working for inputs I throw at it.
import sys
seats = int(input())
configuration = input()
seatsArray = []
betweenSeats = 1
betweenSeatsMin = 1
checked = 0
theArray = []
dotCount = 0
for i in configuration:
seatsArray.append(i)
for i in range(len(seatsArray)):
if i == len(seatsArray) - 1:
break
if seatsArray[i] == "." and seatsArray[i+1] == ".":
print(0)
sys.exit()
for i in range(0,len(seatsArray)):
if i > 0:
if checked == seats:
break
checked += 1
if seatsArray[i] == "#":
if i > 0:
if seatsArray[i-1] == "#":
betweenSeats += 1
if seatsArray[i] == ".":
dotCount += 1
if dotCount > 1:
theArray.append(betweenSeats)
betweenSeats = 1
theArray = sorted(theArray)
if theArray.count(1) > 0:
theArray.remove(1)
theArray = list(dict.fromkeys(theArray))
print(theArray[0])
This is a noob and a !optimal approach to your problem using a counter for the minimum and maximum sequence where ew compare both and return the minimum.
''' create a funciton that
will find min sequence
of target char
in a list'''
def finder(a, target):
max_counter = 0
min_counter = 0
''' iterate through our list
and if the element is the target
increase our max counter by 1
'''
for i in x:
if i == target:
max_counter += 1
'''min here is 0
so it will always be less
so we overwrite it's value
with the value of max_counter'''
if min_counter < max_counter:
min_counter = max_counter
'''at last iteration max counter will be less than min counter
so we overwrite it'''
if max_counter < min_counter:
min_counter = max_counter
else:
max_counter = 0
return min_counter
x = ['t','r','r','r','t','t','r','r','t','t','t','r','t']
y = 'r'
print(finder(x,y))
Create a string from list and then search for pattern required and then count r in the found matches and then take min of it
Code:
import re
lst = ['t','r','r','r','t','t','r','r','t']
text = ''.join(lst)
pattern = '(?<=t)r+(?=t)'
smallest_r_seq = min(match.group().count('r') for match in re.finditer(pattern, text))
print(smallest_r_seq)
Output:
2
Here is the function i defined:
def count_longest(field, data):
l = len(field)
count = 0
final = 0
n = len(data)
for i in range(n):
count = 0
if data[i:i + l] is field:
while data[i - l: i] == data[i:i + l]:
count = count + 1
i = i + 1
else:
print("OK")
if final == 0 or count >= final:
final = count
return final
a = input("Enter the field - ")
b = input("Enter the data - ")
print(count_longest(a, b))
It works in some cases and gives incorrect output in most cases. I checked by printing the strings being compared, and even after matching the requirement, the loop results in "OK" which is to be printed when the condition is not true! I don't get it! Taking the simplest example, if i enter 'as', when prompted for field, and 'asdf', when prompted for data, i should get count = 1, as the longest iteration of the substring 'as' is once in the string 'asdf'. But i still get final as 0 at the end of the program. I added the else statement just to check the if the condition was being satisfied, but the program printed 'OK', therefore informing that the if condition has not been satisfied. While in the beginning itself, data[0 : 0 + 2] is equal to 'as', 2 being length of the "field".
There are a few things I notice when looking at your code.
First, use == rather than is to test for equality. The is operator checks if the left and right are referring to the very same object, whereas you want to properly compare them.
The following code shows that even numerical results that are equal might not be one and the same Python object:
print(2 ** 31 is 2 ** 30 + 2 ** 30) # <- False
print(2 ** 31 == 2 ** 30 + 2 ** 30) # <- True
(note: the first expression could either be False or True—depending on your Python interpreter).
Second, the while-loop looks rather suspicious. If you know you have found your sequence "as" at position i, you are repeating the while-loop as long as it is the same as in position i-1—which is probably something else, though. So, a better way to do the while-loop might be like so:
while data[i: i + l] == field:
count = count + 1
i = i + l # <- increase by l (length of field) !
Finally, something that might be surprising: changing the variable i inside the while-loop has no effect on the for-loop. That is, in the following example, the output will still be 0, 1, 2, 3, ..., 9, although it looks like it should skip every other element.
for i in range(10):
print(i)
i += 1
It does not effect the outcome of the function, but when debugging you might observe that the function seems to go backward after having found a run and go through parts of it again, resulting in additional "OK"s printed out.
UPDATE: Here is the complete function according to my remarks above:
def count_longest(field, data):
l = len(field)
count = 0
final = 0
n = len(data)
for i in range(n):
count = 0
while data[i: i + l] == field:
count = count + 1
i = i + l
if count >= final:
final = count
return final
Note that I made two additional simplifications. With my changes, you end up with an if and while that share the same condition, i.e:
if data[i:i+1] == field:
while data[i:i+1] == field:
...
In that case, the if is superfluous since it is already included in the condition of while.
Secondly, the condition if final == 0 or count >= final: can be simplified to just if count >= final:.
I am trying to write code that is an insertion sort. I am trying to get the code to take 2 values and put them into a new list while sorting it. So far it just puts the values into the list without them being sorted, i'm not quite sure why
pos = 0
pos2 = 1
go = True
while go == True:
for i in range(len(ex)-1):
stack.append(ex[pos])
print(stack)
stack.append(ex[pos2])
print(stack)
if stack[pos] > stack[pos2]:
stack[pos], stack[pos2] = stack[pos2], stack[pos]
print(stack)
pos = pos + 2
pos2 = pos2 + 2
I know it's not efficient, but it is based off code i made for a bubble sort which does
go = True
add = 0
while go == True:
for i in range(len(ex)-1):
if ex[i] > ex[i+1]:
go = True
ex[i], ex[i+1] = ex[i+1], ex[i] #flips the numbers in the list
print(ex)
add = add + 1
if add >= len(ex):
go = False
EDIT
I have changed it drastically, but there is still a problem. It only swaps the values once, even if it needs to be swapped multiple times to be in the right place. Here is the code
pos = 0
while pos < len(ex)-1:
for i in range(len(ex)-1):
stack.append(ex[i])
print(stack)
if stack[i-1] > stack[i]:
stack[i-1], stack[i] = stack[i], stack[i-1]
pos = pos + 1
else:
pos = pos + 1
You have to compare ex[pos] with ex[pos2] then you append the right element first :
if ex[pos] > ex[pos2]:
stack[pos].append(ex[pos2])
else stack[pos].append(ex[pos])
print(stack)
Here is the pseudo code for a classic insertion sort from https://visualgo.net/sorting a great resource for learning sorting algorithms:
mark first element as sorted
for each unsorted element
'extract' the element
for i = lastSortedIndex to 0
if currentSortedElement > extractedElement
move sorted element to the right by 1
else: insert extracted element
And here is how you could implement insertion sort in python:
def insertion_sort(l):
for i in range(1, len(l)):
j = i-1
key = l[i]
while (l[j] > key) and (j >= 0):
l[j+1] = l[j]
j -= 1
l[j+1] = key
return l
Once you understand the basic insertion sort you should be able to understand where you went wrong in your implementation in that you are not properly storing stack[pos] in your implementation.
I need to find the first missing number in a list. If there is no number missing, the next number should be the last +1.
It should first check to see if the first number is > 1, and if so then the new number should be 1.
Here is what I tried. The problem is here: if next_value - items > 1:
results in an error because at the end and in the beginning I have a None.
list = [1,2,5]
vlans3=list
for items in vlans3:
if items in vlans3:
index = vlans3.index(items)
previous_value = vlans3[index-1] if index -1 > -1 else None
next_value = vlans3[index+1] if index + 1 < len(vlans3) else None
first = vlans3[0]
last = vlans3[-1]
#print ("index: ", index)
print ("prev item:", previous_value)
print ("-cur item:", items)
print ("nxt item:", next_value)
#print ("_free: ", _free)
#print ("...")
if next_value - items > 1:
_free = previous_value + 1
print ("free: ",_free)
break
print ("**************")
print ("first item:", first)
print ("last item:", last)
print ("**************")
Another method:
L = vlans3
free = ([x + 1 for x, y in zip(L[:-1], L[1:]) if y - x > 1][0])
results in a correct number if there is a gap between the numbers, but if no space left error occurs: IndexError: list index out of range. However I need to specify somehow that if there is no free space it should give a new number (last +1). But with the below code it gives an error and I do not know why.
if free = []:
print ("no free")
else:
print ("free: ", free)
To get the smallest integer that is not a member of vlans3:
ints_list = range(min(vlans3), max(vlans3) + 1)
missing_list = [x for x in ints_list if x not in vlans3]
first_missing = min(missing_list)
However you want to return 1 if the smallest value in your list is greater than 1, and the last value + 1 if there are no missing values, so this becomes:
ints_list = [1] + list(range(min(vlan3), max(vlan3) + 2))
missing_list = [x for x in ints_list if x not in vlan3]
first_missing = min(missing_list)
First avoid using reserved word list for variable.
Second use try:except to quickly and neatly avoid this kind of issues.
def free(l):
if l == []: return 0
if l[0] > 1: return 1
if l[-1] - l[0] + 1 == len(l): return l[-1] + 1
for i in range(len(l)):
try:
if l[i+1] - l[i] > 1: break
except IndexError:
break
return l[i] + 1
How about a numpy solution? Below code works if your input is a sorted integer list with non-duplicating positive values (or is empty).
nekomatic's solution is a bit faster for small inputs, but it's just a fraction of a second, doesn't really matter. However, it does not work for large inputs - e.g. list(range(1,100000)) completely freezes on list comprehension with inclusion check. Below code does not have this issue.
import numpy as np
def first_free_id(array):
array = np.concatenate((np.array([-1, 0], dtype=np.int), np.array(array, dtype=np.int)))
where_sequence_breaks = np.where(np.diff(array) > 1)[0]
return where_sequence_breaks[0] if len(where_sequence_breaks)>0 else array[-1]+1
Prepend the array with -1 and 0 so np.diff works for empty and 1-element lists without breaking existing sequence's continuity.
Compute differences between consecutive values. Seeked discontinuity ("hole") is where the difference is bigger than 1.
If there ary any "holes" return the id of the first one, otherwise return the integer succeeding the last element.