For in range involving tuple and last tuple - python

im running a for to check a list of tuples. something in the lines of
for i in range of b:
actual=i
temp1=(actual[0]+1,actual[1])
temp2=(actual[0],actual[1]-1)
temp3=(actual[0],actual[1]+1)
temp4=(actual[0]-1,actual[1])
And i want to make sure the temp's NEVER take the value of the tuple verified on the cycle before. Any idea on how to do this?

First, it seems that there's a problem with your code. range accepts integer input, so if b is an integer, for i in range(b) will give you integers [0, 1, 2, .. , b-1 ] in a list. You can't index into i using [], as you do on the next two lines.
If b is not an integer, but a collection, then you should use something like:
# Assuming b is a collection
for i in range(len(b)):
actual=b[i]
temp1=(actual[0]+1,actual[1])
temp2=(actual[0],actual[1]-1)
temp3=(actual[0],actual[1]+1)
temp4=(actual[0]-1,actual[1])
# Check if this is the first one. If it is, previous won't exist.
if i == 0:
continue
previous = b[i-1]
if previous in [ temp1, temp2, temp3, temp4 ]:
# This is what you want not to happen. Deal with it somehow.
pass

Here's my two cents.
Note that this will make temp(1-4) None if any match.
# assuming b is a collection
for i in range(len(b)):
actual=b[i]
if i!=0:
prev = b[i-1]
if i==0:
prev = [[['something']],[['ridiculous']]] #this is so that the rest of the code works even if index is 0
if (actual[0]+1,actual[1]) != prev: #if it is not the previous item
temp1=(actual[0]+1,actual[1]) #assign temp1
else:
temp1 = None #temp1 would otherwise automatically take on the value of (b[i-1][0]+1,b[i-1][1])
if (actual[0],actual[1]-1) != prev:
temp2=(actual[0],actual[1]-1)
else:
temp2 = None
if (actual[0],actual[1]+1) != prev:
temp3=(actual[0],actual[1]+1)
else:
temp3 = None
if (actual[0]-1,actual[1]) != prev:
temp4=(actual[0]-1,actual[1])
else:
temp4 = None

Related

looping over a nested list with multiple rows and columns

I wanted to replace the items from listoflist = [[None, None, None]] with the output from
def _execute():
user_input = input("type in: ")
return user_input
without creating a new list
def insertdata(data): is doing that. its start with the first value and continues till the last value
def insertdata(data):
data_added = False
n = len(listoflist[0])
index = 0
while not data_added and index != n:
if listoflist[0][index] is None:
listoflist[0][index] = data
data_added = True
else:
index += 1
if index == n:
print("\n The list is full, No more elements will be added \n")
while True:
insertdata(_execute())
print(listoflist)
I want to extend the function to loop over a nested list with multiple rows.
what condition should the if statment have so it starts at the first row and execute the inner loop `?
def double_loop(data):
data_added_outer = False
index_outer = 0
n_out = len(listoflist)
# outer loop
while not data_added_outer and index_outer < n_out:
if: # what condition ?
#### inner loop ###############
data_added_inner = False
n_inner = len(listoflist[index_outer])
index_inner = 0
while not data_added_inner and index_inner != n_inner:
if listoflist[index_outer][index_inner] is None:
listoflist[index_outer][index_inner] = data
data_added = True
else:
index_inner += 1
if index_inner == n_inner:
print("\n The list is full, No more elements will be added \n")
####### inner ############################################################
else:
index_outer += 1
if index_outer == n_out:
print("\n The list is full, No more elements will be added \n")
Instead of replacing the data, the elegant approach in Python is to create new data, using comprehensions:
def with_nones_replaced(grid, replacement):
return [
[
replacement if value is None else value
for value in row
]
for row in grid
]
As far as I have understood, the job of your function is simply to replace the None objects in a 2D-List with the data parameter passed to the function. I find a for-loop approach much more cleaner, and pythonic in this case.
def changedata(arr, data):
for item in arr:
for x in range(len(item)):
if item[x] is None:
item[x] = data
You can also use the map function to simplify the code:
def changedata(arr, data):
for i in range(len(arr)):
arr[i] = list(map(lambda x: data if x is None else x, arr[i]))
If the data is coming from a function, you can still use this paradigm by calling
_execute() once, storing it in a variable, and then passing it to changedata()
data = _execute()
changedata(listoflist, data)
print(listoflist)

indexError: list indexing error and wrongful tracking of counters

The goal of the program is to define a procedure that takes in a string of numbers from 1-9 and outputs a list with the following parameters:
Every number in the string should be inserted into the list.
If a number x in the string is less than or equal to the preceding number y, the number x should be inserted into a sublist. Continue adding the following numbers to the sublist until reaching a number z that is greater than the number y.
Then add this number z to the normal list and continue.
#testcases
string = '543987'
numbers_in_lists(string)
result = [5,[4,3],9,[8,7]]
def numbers_in_lists(string):
# Convert the sequence of strings into an array of numbers
i = 0
conv_str_e = []
while i < len(string):
conv_str_e.append(int(string[i]))
i += 1
#official code starts here
normal_list = []
list_of_small_nums = [[]]
# This will help me keep track of elements of the normal_list.
previous_e_pos = -1
e_pos = 0
# this one will be used to decide if the element should go into the
#normal_list or list_of_small_nums
check_point = 0
for e in conv_str_e:
#The first element and every elements bigger the element with
#check_point as it's index
#will be put into the normal_list as long as the list inside
#list_of_small_nums is empty
if e_pos == 0 or e > conv_str_e[check_point]:
#If the list inside list_of_small_nums is not empty
if list_of_small_nums[0] != []:
#concatenate the normal_list and list_of_small_nums
normal_list = normal_list + list_of_small_nums[0]
#Clear the list inside list_of_small_nums
list_of_small_nums[0] = []
#Add the element in the normal_list
normal_list.append(e)
# Update my trackers
e_pos += 1
previous_e_pos += 1
# (not sure this might be the error)
check_point = e_pos
#The curent element is not bigger then the element with the
#check_point as index position
#Therefor it goes into the sublist.
list_of_small_nums[0].append(e)
e_pos += 1
previous_e_pos += 1
return list
What you were doing wrong was exactly what you pointed out in your comments. You just kept increasing e_pos and so check_point eventually was greater than the length of the list.
I took the liberty of changing some things to simplify the process. Simple programs make it easier to figure out what is going wrong with them. Make sure you always try to think about the simplest way first to solve your problem! Here, I replaced the need for e_pos and previous_e_pos by using enumerate:
string = '543987'
# Convert the sequence of strings into an array of numbers
conv_str_e = [int(i) for i in string]
#official code starts here
normal_list = []
list_of_small_nums = []
# this one will be used to decide if the element should go into the
#normal_list or list_of_small_nums
check_point = 0
for ind, e in enumerate(conv_str_e):
#The first element and every elements bigger the element with
#check_point as it's index
#will be put into the normal_list as long as the list inside
#list_of_small_nums is empty
if ind == 0 or e > conv_str_e[check_point]:
#If the list inside list_of_small_nums is not empty
if list_of_small_nums != []:
#concatenate the normal_list and list_of_small_nums
normal_list.append(list_of_small_nums)
#Clear the list inside list_of_small_nums
list_of_small_nums = []
#Add the element in the normal_list
normal_list.append(e)
# Update my trackers
check_point = ind
else:
#The curent element is not bigger then the element with the
#check_point as index position
#Therefore it goes into the sublist.
list_of_small_nums.append(e)
# If there is anything left, add it to the list
if list_of_small_nums != []:
normal_list.append(list_of_small_nums)
print(normal_list)
Result:
[5, [4, 3], 9, [8, 7]]
I am sure you can change it appropriately from here to put it back in your function.

having error while jumping in list

You are given a list jumps of positive and negative integers which signify forward or negative jumps.
Starting at index 0, you jump to index 0+jump[0] . In general, if you are at index k, you would jump to index k+jump[k] Let's say jumps[0] was 2 . Index becomes 2. Assuming jumps[2] was -1, index would become 1.
Write the function list_jumps(jumps) where jumps is the aforementioned list. The function should return the string 'cycle' if the index will never leave the boundaries of the input list otherwise it must return 'out-of-bounds'. The starting index is always 0.
dm=[3,0,0,-2]
def list_jump(jumps):
xs=jumps
xy=jumps
max=len(xs)
while(True):
p = int(xs[0])
print p
for i in range (0,max,p):
print i,"iii"
p = xs[i]
if xs[i]=="visited":
return False
else:
xs[i]="visited"
print xs
return True
if list_jump(dm):
print "not cycle"
else:
print "cycle"
I really don't need solution. I just want to know what is the error.
note that I would just make a set seen and add each index to that.
def list_jump(jumps):
i = 0
seen = {0}
while True:
try:
i += jumps[i]
if i < 0:
# negative indices are legal, but we should exit if we have one.
return "out-of-bounds"
except IndexError:
# we've escaped the list: non-cyclic!
return "out-of-bounds"
else:
if i in seen:
return "cycle"
else:
seen.add(i)

Python: find smallest missing positive integer in ordered list

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.

How to find the position of first instance of duplicates in two equal length, sorted lists

I have two random lists of same length, in range of 0 to 99.
lista = [12,34,45,56,66,80,89,90]
listb = [13,30,56,59,72,77,80,85]
I need to find the first instance of a duplicate number, and in what list it is from.
In this example, I need to find the number '56' in listb, and get the index i = 2
Thanks.
Update:
After running it a couple of times, I got this error:
if list_a[i] == list_b[j]:
IndexError: list index out of range
like #Asterisk suggested, my two lists are equal length and sorted, both i and j are set to 0 at the beginning.
that bit is part of a genetic crossover code:
def crossover(r1,r2):
i=random.randint(1,len(domain)-1) # Indices not at edges of domain
if set(r1) & set(r2) == set([]): # If lists are different, splice at random
return r1[0:i]+r2[i:]
else: # Lists have duplicates
# Duplicates At Edges
if r1[0] == r2[0]: # If [0] is double, retain r1
return r1[:1]+r2[1:]
if r1[-1] == r2[-1]: # If [-1] is double, retain r2
return r1[:-1]+r2[-1:]
# Duplicates In Middle
else: # Splice at first duplicate point
i1, i2 = 0, 0
index = ()
while i1 < len(r1):
if r1[i1] == r2[i2]:
if i1 < i2:
index = (i1, r1, r2)
else:
index = (i2, r2, r1)
break
elif r1[i1] < r2[i2]:
i1 += 1
else:
i2 += 1
# Return A Splice In Relation To What List It Appeared First
# Eliminates Further Duplicates In Original Lists
return index[2][:index[0]+1]+index[1][index[0]+1:]
The function takes 2 lists and returns one.
domain is a list of 10 tupples: (0,99).
As I said, the error doesn't happen every time, only once in a while.
I appreciate your help.
I'm not a python guy, but this is an algorithm question...
You maintain an index into each list and you look at the elements at those two list positions.
Whichever list has the smallest element at the current position, you move to the next element in that list.
When you find an element that is the same as the other list's current element, that is your smallest duplicate.
If you reach the end of either list, there are no duplicates.
If you're looking for all the duplicates, you can use something like this:
list_a = [12,34,45,56,66,80,89,90]
list_b = [13,30,56,59,72,77,80,85]
set_a = set(list_a)
set_b = set(list_b)
duplicates = set_a.intersection(set_b)
# or just this:
# duplicates = [n for n in list_a if n in list_b]
for duplicate in duplicates:
print list_a.index(duplicate)
To get the smallest index of a duplicate in either list:
a_min = min(map(list_a.index, duplicates))
b_min = min(map(list_b.index, duplicates))
if a_min < b_min:
print 'a', a_min, list_a[a_min]
else:
print 'b', b_min, list_b[b_min]
If not, this should work a bit better:
duplicate = None
for n in set_a:
if n in set_b:
duplicate = n
break
if duplicate is not None:
print list_a.index(duplicate)
lista = [12,34,45,56,66,80,89,90]
listb = [13,30,56,59,72,77,80,85]
i, j = 0, 0
while i < len(lista):
if lista[i] == listb[j]:
if i < j:
print i, lista
else:
print j, listb
break
elif lista[i] < listb[j]:
i += 1
else:
j += 1
>>>
2 [13, 30, 56, 59, 72, 77, 80, 85]
Assumptions: both lists have the same length, and they are sorted
Just scan all the lists at position 0, then 1, then 2, ... Keep track of what you've seen (you can query a set in O(1) time).
def firstDuplicate(*lists):
seen = {}
for i,tup in enumerate(zip(*lists)):
for listNum,value in enumerate(tup):
position = (listNum,i)
if value in seen:
return value, [seen[value], position]
else:
seen[value] = position
Demo:
>>> value,positions = firstDuplicate(lista,listb)
>>> value
56
>>> positions
[(1, 2), (0, 3)]
(Does not generalize to N lists... yet. Would need a minor tweak to use a defaultdict(set), insert all indices as a tuple together, then check for duplicates.)

Categories

Resources