How to count the number of separate regions in python array - python

I need to count the number of separate regions in an array.
An example array is below. I can count the number of unique strings but if there are two distinct islands like in the grid below where 64733 is in the upper left and bottom right my function won't properly count the number of regions.
Can anyone help me to find a way to count the number of regions if two of the regions are comprised of the same numbers? Im writing in python 2.x.
|64733|20996|92360|92360|04478|04478|04478|04478|04478|98101
|64733|92360|92360|92360|04478|04478|04478|04478|04478|04478
|64733|92360|29136|92360|04478|04478|04478|04478|04478|04478
|64733|92360|29136|92360|04478|04478|04478|04478|04478|04478
|92360|92360|92360|92360|04478|04478|04478|04478|04478|04478
|04478|04478|04478|04478|04478|04478|04478|04478|04478|04478
|04478|04478|04478|04478|04478|04478|04478|04478|04478|04478
|04478|04478|04478|04478|04478|04478|04478|04478|04478|04478
|04478|04478|04478|04478|04478|04478|04478|04478|04478|64773
|04478|04478|04478|04478|04478|04478|04478|04478|64773|64773
The input is a 3d array and looks like
[[['6', '4', '7', '3', '3'],
['2', '0', '9', '9', '6'],
['9', '2', '3', '6', '0'],
['9', '2', '3', '6', '0'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['9', '8', '1', '0', '1']],
[['6', '4', '7', '3', '3'],
['9', '2', '3', '6', '0'],
['9', '2', '3', '6', '0'],
['9', '2', '3', '6', '0'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8'],
['0', '4', '4', '7', '8']],
[['6', '4', '7', '3', '3'],
['9', '2', '3', '6', '0'],
This is not the complete input (because it was huge) but it gets the point across i think
So would be where any unique symbol string of numbers lies and the total number of adjacent strings that are identical (adjacent being up down left right, not diagonal).
enter code here

You didn't post your full array, so I made some assumptions about the original pip separated value you gave us. I've written this in Python 3, but I think it should work in Python 2 only modifying the print function calls to statements.
arr = [["64733","20996","92360","92360","04478","04478","04478","04478","04478","98101"],
["64733","92360","92360","92360","04478","04478","04478","04478","04478","04478"],
["64733","92360","29136","92360","04478","04478","04478","04478","04478","04478"],
["64733","92360","29136","92360","04478","04478","04478","04478","04478","04478"],
["92360","92360","92360","92360","04478","04478","04478","04478","04478","04478"],
["04478","04478","04478","04478","04478","04478","04478","04478","04478","04478"],
["04478","04478","04478","04478","04478","04478","04478","04478","04478","04478"],
["04478","04478","04478","04478","04478","04478","04478","04478","04478","04478"],
["04478","04478","04478","04478","04478","04478","04478","04478","04478","64773"],
["04478","04478","04478","04478","04478","04478","04478","04478","64773","64773"]]
x = len(arr)
y = len(arr[0])
#create a new array the same size as the original
regions = [[None for _ in range(y)] for _ in range(x)]
print(regions)
label = 0
queue = []
def check_neighbor(i, j, v):
if not regions[i][j] and arr[i][j] == v:
regions[i][j] = label
queue.insert(0, (i, j))
for i in range(x):
for j in range(y):
#don't check an already labelled region
if regions[i][j]: continue
label += 1 #new label
regions[i][j] = label
queue = [(i, j)]
v = arr[i][j]
#keep checking neighbours until we run out
while queue:
(X, Y) = queue.pop()
if X > 0:
check_neighbor(X-1, Y, v)
if X < x-1:
check_neighbor(X+1, Y, v)
if Y > 0:
check_neighbor(X, Y-1, v)
if Y < y-1:
check_neighbor(X, Y+1, v)
print(regions)
print(label) # this is the number of regions

Related

How to retrieve the position of a list in a list of lists in python

A = [['0', '6', '4', '3'], ['0', '2', '8', '3'], ['0', '4', '1', '5'], ['0', '3', '2', '5']]
B = ['0', '4', '1', '5']
Say I want to find out at which line does B equal to the list. How do I write a solution for this?
The answer would be the third line.
I tried doing a for loop.
You can try list.index(element) to get the index of the element in the original list (A). In your terminology, to get the line just add one to the index.
line = A.index(B) + 1
you dont need use loops.you can get the element index by indexing.
A = [['0', '6', '4', '3'], ['0', '2', '8', '3'], ['0', '4', '1', '5'], ['0', '3', '2', '5']]
B = ['0', '4', '1', '5']
print(A.index(B))
>>> 2

Sample from list of lists until condition is met

I have a list of lists that I am randomly choosing a value from. The issue I am having now is that since the loop I wrote is using random.choice() there is the possibility that a given value won't be present, which will cause an error in downstream code. So I basically want to sample from this list of lists until the final list has at least one occurrence of each value (so at least one occurrence of 1-8).
Below is my current code and the output list for probe which doesn't include a single occurrence of 3 in this iteration, which will cause the subsequent code to fail.
Some restrictions I have:
The final list probe needs to be only 16 items.
One of the two values needs to be picked at each index because it codes for a later stimulus. So for example, probe[0] in this case needs to be either 7 or 6 and probe[15] needs to be either 3 or 2. But still with the condition that across all indexes, 1-8 appears at least once.
probe_list = [['7', '6'], ['5', '8'], ['3', '2'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['7', '6'], ['1', '4'], ['3', '2'], ['7', '6'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['3', '2']]
probe=[]
for i in range(len(probe_list)):
choose = random.choice(probe_list[i])
probe.append(choose)
probe = ['7', '8', '2', '1', '6', '1', '5', '6', '4', '2', '7', '4', '6', '4', '8', '2']
You could create a set, which contains all values which are already in the probe in the current "run". Then you could always check, whether the size of the set is 8. If you begin a new "run", then you have to clear() the set and the probe.
import random
probe_list = [['7', '6'], ['5', '8'], ['3', '2'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['7', '6'], ['1', '4'], ['3', '2'], ['7', '6'], ['1', '4'], ['7', '6'], ['1', '4'], ['5', '8'], ['3', '2']]
probe=[]
while True:
contained=set()
probe = []
for i in range(len(probe_list)):
choose = random.choice(probe_list[i])
contained.add(choose)
probe.append(choose)
if len(contained) == 8:
break
print(probe, len(probe), len(set(probe)))
It would alway ensure, that the length of the probe is 16 and the number of unique items in the probe is 8.
For example the output:
['7', '5', '2', '4', '6', '1', '8', '7', '1', '3', '6', '4', '6', '1', '5', '3'] 16 8

How to add a list to another list

I have a function called "organizer" which takes 2 values a list and an index(number), to reorganize this list, after that it return a new list.
I want to execute this function 10 times to create 10 lists and add this lists to a single list of lists for later use, the program acomplish this, however it repeat the last list 10 times, it does not add the other lists.
I put the function "organizer" in here,because Im unable to find where the problem relies so more information may be needed.
I have been using the print function along the function to see where it fails, and it creates the lists as I desire, the problem is that after creating them it just copy the last created list as many times as the loop goes on. It takes the final list produced and copy it several times
Here is the code:
number_list = ["12","11","10","9","8","7","6","5","4","3","2","1"]
indexes = [0,5,6,8,10,4,5,2,1,9]
def organizer(list,index): # Takes a list and reorganize it by a number which is an index.
number1 = index - 1
count_to_add = -1
list_to_add = []
for item in range(number1):
count_to_add += 1
a = list[count_to_add]
list_to_add.append(a)
number2 = index - 1
for item1 in range(number2):
del list[0]
list.extend(list_to_add)
return list
def lists_creator(list_indexes): # Create a list of 10 lists ,with 12 elements each.
final_list = []
count = -1
for item in list_indexes:
count += 1
result = organizer(number_list, list_indexes[count])
final_list.append(result)
return final_list
final_output = lists_creator(indexes)
print(final_output)
Here is the result:(the same list 10 times)
[['7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8'], ['7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8'], ['7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8'], ['7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8'], ['7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8'], ['7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8'], ['7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8'], ['7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8'], ['7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8'], ['7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8']]
Note: If I change the line 28 in list_creator function
final_list.append(result)
for
final_list.extend(result)
the result is:
['12', '11', '10', '9', '8', '7', '6', '5', '4', '3', '2', '1', '8', '7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '3', '2', '1', '12', '11', '10', '9', '8', '7', '6', '5', '4', '8', '7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '11', '10', '9', '8', '7', '6', '5', '4', '3', '2', '1', '12', '8', '7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '4', '3', '2', '1', '12', '11', '10', '9', '8', '7', '6', '5', '3', '2', '1', '12', '11', '10', '9', '8', '7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8', '7', '6', '5', '4', '7', '6', '5', '4', '3', '2', '1', '12', '11', '10', '9', '8']
Which is the result that I desire but is not a group of lists.
you are using the same list every time, so the result consists of actually one list,
in your list_creator method, you have to give to organizer method a copy of your original list number_list, otherwise you just mutate over and over again the same one list:
def lists_creator(list_indexes): # Create a list of 10 lists ,with 12 elements each.
final_list = []
count = -1
for item in list_indexes:
count += 1
result = organizer(list(number_list), list_indexes[count])
final_list.append(result)
return final_list
def lists_creator(list_indexes): # Create a list of 10 lists ,with 12 elements each.
final_list = []
list = []
for i in range(len(list_indexes)):
result = organizer(number_list, list_indexes[i])
list.extend(result)
n = 0
m = 12
for n_times in range(len(list_indexes)):
final_list.append(list[n:m])
n = m
m += 12
return final_list

Python - TypeError: unorderable types: str() < int()

I get this error when I try to run my code. Please help, and explain what it's trying to say!
This program is meant to find a persons ballot paper vote preferences (1st, 2nd, 3rd etc) for each candidate, and remove their first preference. That first preference is replaced by 99999, to make it easier for me.
Error:
ERROR CODE: minIndex = int(vote.index(min(vote)))
TypeError: unorderable types: str() < int()
Code:
def countVotes(voteList):
candidatePreferences = []
for vote in voteList:
minIndex = int(vote.index(min(vote)))
candidatePreferences.append(minIndex)
vote[minIndex] = 99999
return candidatePreferences
Value of vList (after calling countVotes function first time):
[[99999, '3', '4', '5', '2'], ['4', '2', '5', '3', 99999], [99999, '3', '2', '5', '4'], [99999, '2', '4', '3', '5'], [99999, '3', '4', '5', '2'], ['2', 99999, '3', '5', '4'], [99999, '3', '4', '5', '2'], ['3', '5', '2', '4', 99999], [99999, '4', '5', '2', '3'], ['5', 99999, '4', '3', '2'], ['3', '2', '5', '4', 99999], ['3', 99999, '2', '5', '4'], ['2', '5', 99999, '4', '3'], ['3', '2', 99999, '4', '5'], ['4', '5', '3', 99999, '2'], [99999, '5', '4', '3', '2'], [99999, '5', '3', '4', '2'], ['2', 99999, '4', '3', '5'], ['4', 99999, '2', '5', '3']]
Calling the function (second time):
cp = countVotes(vList)
minIndex = int(vote.index(min(vote)))
TypeError: unorderable types: str() < int()
Python cannot order str values and int values together.
In your example 99999 is an int value while all the other values are str values.
I think is this line minIndex = int(vote.index(min(vote)))
You are trying to find min on a string list. so what you can
def countVotes(voteList):
candidatePreferences = []
for vote in voteList:
vote = map(int, vote)
minIndex = int(vote.index(min(vote)))
candidatePreferences.append(minIndex)
vote[minIndex] = 99999
return candidatePreferences
After converting string list to Int list you can perform min operation.
Please check and let me know.
Try this code. it fixed the error:
def countVotes(voteList):
candidatePreferences = []
for vote in voteList:
minIndex = int(vote.index(min(vote)))
candidatePreferences.append(minIndex)
vote[minIndex] = '99999'
return candidatePreferences
vList = [['1', '3', '4', '5', '2'], ['4', '2', '5', '3', '1'], ['1', '3', '2', '5', '4'], ['1', '2', '4', '3', '5'], ['1', '3', '4', '5', '2'], ['2', '1', '3', '5', '4'], ['1', '3', '4', '5', '2'], ['3', '5', '2', '4', '1'], ['1', '4', '5', '2', '3'], ['5', '1', '4', '3', '2'], ['3', '2', '5', '4', '1'], ['3', '1', '2', '5', '4'], ['2', '5', '1', '4', '3'], ['3', '2', '1', '4', '5'], ['4', '5', '3', '1', '2'], ['1', '5', '4', '3', '2'], ['1', '5', '3', '4', '2'], ['2', '1', '4', '3', '5'], ['4', '1', '2', '5', '3']]
cp = countVotes(vList)
print(str(cp))
output:
[0, 4, 0, 0, 0, 1, 0, 4, 0, 1, 4, 1, 2, 2, 3, 0, 0, 1, 1]
Convert string elements to integer.You can use python map function to convert all the list elements to integer
def countVotes(voteList):
candidatePreferences = []
for vote in voteList:
vote = list(map(int, vote)) # add this line to the code to convert string elements to integer
minIndex = int(vote.index(min(vote)))
candidatePreferences.append(minIndex)
vote[minIndex] = 99999
return candidatePreferences

Printing a variable and appending it with a line from a file in a loop

I've researched this already but I can't find an exact answer. I've found answers for appending when there's 2 lists involved but this is different so here goes.
I'm creating a really basic fuzzer but I'm having issues appending the directory names to the end of the address. Here's what I have so far.
The expected output is as follows;
www.website.com/1
www.website.com/2
www.website.com/3
www.website.com/4
etc. But I'm getting something completely different. Here's the first piece of code I tested.
>>> host = "www.website.com/"
>>> path = [line.strip() for line in open("C:/Users/Public/Documents/tester.txt", 'r')]
>>> print str(host) + str(path)
which returns the following
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
The second attempt was this;
>>> host = "www.website.com/"
>>> path = [line.strip() for line in open("C:/Users/Public/Documents/tester.txt", 'r')]
>>> for line in path:
print str(host) + str(path)
Which returned this;
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
www.website.com/['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
I can see exactly what's happening and why it's happening but I can't figure out how to arrive at the expected output. I'll also need to filter out the special characters which I didn't think 'print' would pick up. Maybe there's different rules for print when it's reading something as a list.
I've thought of stupid complex methods such as counting the lines in the file and then throwing it into a while loop using that count but I'm sure there's something I can use or something I've done wrong. My Python knowledge isn't fantastic.
Can anybody help with this?
You were nearly there , when using the for loop , concatenate the elements from the list (which in your case is in variable 'line') , not the complete list again .
Code -
for line in path:
print str(host) + str(line)

Categories