Prim's algorithm output empty - python

I have this piece of code above:
N = 8
inf = 99
graph = [[0,0,6,7,0,8,0,0], #1
[0,0,0,3,4,2,0,0], #2
[6,0,0,0,0,3,0,7], #3
[7,3,0,0,9,0,0,0], #4
[0,4,0,9,0,0,5,0], #5
[8,2,3,0,0,0,9,3], #6
[0,0,0,0,5,9,0,0], #7
[0,0,7,0,0,3,0,0]] #8
# Матрица инцидентности для остовного дерева (задаётся пустой)
spanning_tree_graph = [[0,0,0,0,0,0,0,0] for node in range(N)]
selected_nodes = [False for node in range(N)] # какие вершины включены, какие нет
while(False in selected_nodes): # Пока есть невключенные вершины:
minimum = inf
start = 0
end = 0
for i in range(0, N):
if selected_nodes[i]:
for j in range(0+i, N):
if(not selected_nodes[j] and graph[i][j] > 0):
if graph[i][j] < minimum:
minimum = graph[i][j]
start, end = i, j
selected_nodes[end] = True
spanning_tree_graph[start][end] = minimum
if minimum == inf:
spanning_tree_graph[start][end] = 0
spanning_tree_graph[end][start] = spanning_tree_graph[start][end]
print(spanning_tree_graph)
But output is empty, and I don't know why.
I'm trying to render the sorted graph. Like this
[[0, 8, 2, 4, 0, 0, 0, 0], [8, 0, 0, 0, 0, 0, 0, 0], [2, 0, 0, 0, 0, 5, 0, 4], [4, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 4, 0], [0, 0, 5, 0, 0, 0, 0, 0], [0, 0, 0, 0, 4, 0, 0, 0], [0, 0, 4, 0, 0, 0, 0, 0]]

Here is what I believe to be a fixed implementation.
N = 8
inf = 99
graph = [[0,0,6,7,0,8,0,0], #1
[0,0,0,3,4,2,0,0], #2
[6,0,0,0,0,3,0,7], #3
[7,3,0,0,9,0,0,0], #4
[0,4,0,9,0,0,5,0], #5
[8,2,3,0,0,0,9,3], #6
[0,0,0,0,5,9,0,0], #7
[0,0,7,0,0,3,0,0]] #8
# Матрица инцидентности для остовного дерева (задаётся пустой)
spanning_tree_graph = [[0,0,0,0,0,0,0,0] for node in range(N)]
selected_nodes = [False for node in range(N)] # какие вершины включены, какие нет
selected_nodes[0] = True
while(False in selected_nodes): # Пока есть невключенные вершины:
minimum = inf
start = 0
end = 0
for i in range(0, N):
if selected_nodes[i]:
for j in range(0, N):
if(not selected_nodes[j] and graph[i][j] > 0):
if graph[i][j] < minimum:
minimum = graph[i][j]
start, end = i, j
selected_nodes[end] = True
spanning_tree_graph[start][end] = minimum
if minimum == inf:
spanning_tree_graph[start][end] = 0
break
spanning_tree_graph[end][start] = spanning_tree_graph[start][end]
for g in spanning_tree_graph:
print(g)
Here were the bugs that I fixed.
You have to start with a node (any node) in the spanning tree graph for it to get going.
You're looping through pairs to find i a selected node and j not. You were not willing to consider j < i but it might be.
If minimum == inf then the next loop iteration will find the same, and you have an infinite loop. So break with the partial tree.
I modified the print at the end to display in a more convenient format.

Related

simple version of Game Of Life game doesnt behave correctly [duplicate]

This question already has answers here:
Does Python make a copy of objects on assignment?
(5 answers)
Closed 2 years ago.
Here's the full code. I've left out few unnecessary things
import random
import pygame
FPS = 1
WIDTH, HEIGHT = 400, 400
RESOLUTION = 40
GRAY = (200, 200, 200)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Game of Life")
def draw_grid(win, cols, rows):
for i in range(cols):
for j in range(rows):
x = i * RESOLUTION
y = j * RESOLUTION
pygame.draw.rect(win, GRAY, (x, y, RESOLUTION, RESOLUTION), 1)
def make_2d_array(cols, rows):
arr = []
for i in range(cols):
arr.append([])
for j in range(rows):
arr[i].append(0)
return arr
def count_neighbours(grid, x, y):
neighbourCount = 0
for i in range(-1, 2):
for j in range(-1, 2):
neighbourCount += grid[x + i][y + j]
return neighbourCount
def draw_squares(win, grid, cols, rows):
#nextA = make_2d_array(cols, rows)
nextA = grid
for i in range(len(grid)):
for j in range(len(grid[i])):
x = i * RESOLUTION
y = j * RESOLUTION
if grid[i][j] == 1:
pygame.draw.rect(win, WHITE, (x, y, RESOLUTION, RESOLUTION))
elif grid[i][j] == 0:
pygame.draw.rect(win, BLACK, (x, y, RESOLUTION, RESOLUTION))
for i in range(cols):
for j in range(rows):
if i == 0 or i == cols-1 or j == 0 or j == rows-1:
nextA[i][j] = grid[i][j]
else:
state = grid[i][j]
neighbours = count_neighbours(grid, i, j)
if state == 0 and neighbours == 3:
nextA[i][j] = 1
elif state == 1 and (neighbours < 2 or neighbours > 3):
nextA[i][j] = 0
else:
nextA[i][j] = state
grid = nextA
def main():
run = True
clock = pygame.time.Clock()
cols = int(WIDTH / RESOLUTION)
rows = int(HEIGHT / RESOLUTION)
grid = make_2d_array(cols, rows)
"""for i in range(cols):
for j in range(rows):
grid[i][j] = random.randint(0, 1)"""
#glider test
grid = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
draw_squares(WIN, grid, cols, rows)
draw_grid(WIN, cols, rows)
pygame.display.update()
pygame.quit()
main()
I was following along with a tutorial that was written in Java or JavaScript but the rules are the same and should work but they don't.
The rules simplified should be this:
if state == 0 and neighbours == 3:
nextA[i][j] = 1
elif state == 1 and (neighbours < 2 or neighbours > 3):
nextA[i][j] = 0
else:
nextA[i][j] = state
but when I run the code the first if-statement works I'm pretty sure (it's kinda hard to understand the program behaves weirdly).
The implementation of the rules is correct, but in Conway's Game of Life you have to create a new and empty grid every turn. The fields in the new grid must be determined depending on the fields in the current grid and the evolution rules.
Create a new and empty grid in draw_squares, but return the new grid form the function:
def draw_squares(win, grid, cols, rows):
# nextA = grid # <--- DELETE
nextA = make_2d_array(cols, rows) # <--- ADD
# [...]
return nextA # <-- return the new grid
Make the new grid the current grid by assigning the new grid returned by draw_squares to grid:
grid = draw_squares(WIN, grid, cols, rows)
Additionally the computation of the neighbors is wrong. A field is not a neighbor of itself:
def count_neighbours(grid, x, y):
neighbourCount = 0
for i in range(-1, 2):
for j in range(-1, 2):
if i != 0 or j != 0:
neighbourCount += grid[x + i][y + j]
return neighbourCount

Replace in array of zeros with other values in certain cells_updated question

I need to solve a problem in which I have spent hours, with the data from my excel sheet I have created a 6x36 '' zeros '' matrix of zeros and a 6x6 '' matrix_tran '' coordinate transformation matrix [image 1].
My problem is that I can't find a way to replace the zeros of the '' zeros '' matrix with the values that the matrix '' matrix_tran '' dictates, and whose location must be in the columns (4,5,6, 7,8,9) that are given by the connection vector (4,5,6,7,8,9) of element 15 of the Excel sheet, that is, the last row of the for loop iteration [image 2].
In summary: Below I show how it fits and how it should look [image 3 and 4 respectively].
I would very much appreciate your help, and excuse my English, but it is not my native language, a big greeting.
import pandas as pd
import numpy as np
ex = pd.ExcelFile('matrix_tr.xlsx')
hoja = ex.parse('Hoja1')
cols = 36
for n in range(0,len(hoja)):
A = hoja['ELEMENT #'][n]
B = hoja['1(i)'][n]
C = hoja['2(i)'][n]
D = hoja['3(i)'][n]
E = hoja['1(j)'][n]
F = hoja['2(j)'][n]
G = hoja['3(j)'][n]
H = hoja['X(i)'][n]
I = hoja['Y(i)'][n]
J = hoja['X(j)'][n]
K = hoja['Y(j)'][n]
L = np.sqrt((J-H)**2+(K-I)**2)
lx = (J-H)/L
ly = (K-I)/L
zeros = np.zeros((6, cols))
counters = hoja.loc[:, ["1(i)", "2(i)", "3(i)", "1(j)", "2(j)", "3(j)"]]
for _, i1, i2, i3, j1, j2, j3 in counters.itertuples():
matrix_tran = np.array([[lx, ly, 0, 0, 0, 0],
[-ly, lx, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, lx, ly, 0],
[0, 0, 0, -ly, lx, 0],
[0, 0, 0, 0, 0, 1]])
zeros[:, [i1 - 1, i2 - 1, i3 - 1, j1 - 1, j2 - 1 , j3 - 1]] = matrix_tran
Try with a transposed zeros matrix
import pandas as pd
import numpy as np
ex = pd.ExcelFile('c:/tmp/SO/matrix_tr.xlsx')
hoja = ex.parse('Hoja1')
counters = hoja.loc[:, ["1(i)", "2(i)", "3(i)", "1(j)", "2(j)", "3(j)"]]
# zeros matrix transposed
cols = 36
zeros_trans = np.zeros((cols,6))
# last row only
for n in range(14,len(hoja)):
Xi = hoja['X(i)'][n]
Yi = hoja['Y(i)'][n]
Xj = hoja['X(j)'][n]
Yj = hoja['Y(j)'][n]
X = Xj-Xi
Y = Yj-Yi
L = np.sqrt(X**2+Y**2)
lx = X/L
ly = Y/L
matrix_tran = np.array([[lx, ly, 0, 0, 0, 0],
[-ly, lx, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, lx, ly, 0],
[0, 0, 0, -ly, lx, 0],
[0, 0, 0, 0, 0, 1]])
i = 0
for r in counters.iloc[n]:
zeros_trans[r-1] = matrix_tran[i]
i += 1
print(np.transpose(zeros_trans))

Get first number each block of duplicates numbers in a list of 0 and 1

I have a list that looks like this:
a = [0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0...]
How do I get the index of the first 1 in each block of zero - one so the resulting index is:
[8 23 ..] and so on
I've been using this code:
def find_one (a):
for i in range(len(a)):
if (a[i] > 0):
return i
print(find_one(a))
but it gives me only the first occurrence of 1. How can implement it to iterate trough the entire list?
Thank you!!
You can do it using zip and al list comprehension:
a = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
r = [i for n,(i,v) in zip([1]+a,enumerate(a)) if v > n]
print(r) # [8,23]
Since you tagged pandas, can use groupby. If s = pd.Series(a) then
>>> x = s.groupby(s.diff().ne(0).cumsum()).head(1).astype(bool)
>>> x[x].index
Int64Index([8, 23], dtype='int64')
Without pandas:
b = a[1:]
[(num+1) for num,i in enumerate(zip(a,b)) if i == (0,1)]
# `state` is (prev_char, cur_char)
# where `prev_char` is the previous character seen
# and `cur_char` is the current character
#
#
# (0, 1) .... previous was "0"
# current is "1"
# RECORD THE INDEX.
# STRING OF ONES JUST BEGAN
#
# (0, 0) .... previous was "0"
# current is "0"
# do **NOT** reccord the index
#
# (1, 1) .... previous was "1"
# current is "1"
# we are in a string of ones, but
# not the begining of it.
# do **NOT** reccord the index.
#
# (1, 0).... previous was "1"
# current is "0"
# string of ones, just ended
# not the start of a string of ones.
# do **NOT** reccord the index.
state_to_print_decision = dict()
state_to_print_decision[(0, 1)] = True
def find_one (a, state_to_print_decision):
#
# pretend we just saw a bunch of zeros
# initilize state to (0, 0)
state = (0, 0)
for i in range(len(a)):
#
# a[i] is current character
#
# state[0] is the left element of state
#
# state[1] is the right elemet of state
#
# state[1] was current character,
# is now previous character
#
state = (state[1], a[i])
it_is_time_to_print = state_to_print_decision.get(state, False)
if(it_is_time_to_print):
indicies.append()
return indicies
a = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]
print(find_one(a, state_to_print_decision))

How to modify Numpy array in for loop

I have a Pandas Dataframe of 1's and 0's converted to an array :
[0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]
I'm using the following function to amend the array:
def regressor(x, param):
new_array = x
for i in range(len(new_array)):
length = len(new_array)
current = new_array[(length-i)-1]
previous = new_array[(length-i)-2]
if current != 0:
if previous == 0:
new_array[(length-i)-2] = current*param
return new_array
However, my array is still unchanged. new_array[(length-i)-2] does not seem to actually amend that element of the array.
Could someone tell me what I'm missing?
Thanks
UPDATE: My problem was solved by converting the DataFrame to a pandas.Series and then converting this to a list within the function.
If I run your code I get this (for param=2):
x = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
def regressor(x, param):
new_array = x
for i in range(len(new_array)):
length = len(new_array)
current = new_array[(length-i)-1]
previous = new_array[(length-i)-2]
if current != 0:
if previous == 0:
new_array[(length-i)-2] = current * param
return new_array
new_array = regressor(x, 2)
print(new_array)
# Output:
# [8, 4, 2, 1, 2097152, 1048576, 524288, 262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
Why do you not see changes in your new_array? Do you actually call the regressor function to update your array?
Also, copying x to new_array at the beginning of the function is redundant.
Just re-posting your function with some edits for better readability:
def regressor(arr, param):
for i in range(len(arr)):
length = len(arr)
current = arr[(length-i)-1]
previous = arr[(length-i)-2]
if (current != 0) and (previous == 0):
arr[(length-i)-2] = current * param
return arr

Why cycle behaves differently in just one iteration?

I have this code:
gs = open("graph.txt", "r")
gp = gs.readline()
gp_splitIndex = gp.find(" ")
gp_nodeCount = int(gp[0:gp_splitIndex])
gp_edgeCount = int(gp[gp_splitIndex+1:-1])
matrix = [] # predecare the array
for i in range(0, gp_nodeCount):
matrix.append([])
for y in range(0, gp_nodeCount):
matrix[i].append(0)
for i in range(0, gp_edgeCount-1):
gp = gs.readline()
gp_splitIndex = gp.find(" ") # get the index of space, dividing the 2 numbers on a row
gp_from = int(gp[0:gp_splitIndex])
gp_to = int(gp[gp_splitIndex+1:-1])
matrix[gp_from][gp_to] = 1
print matrix
The file graph.txt contains this:
5 10
0 1
1 2
2 3
3 4
4 0
0 3
3 1
1 4
4 2
2 0
The first two number are telling me, that GRAPH has 5 nodes and 10 edges. The Following number pairs demonstrate the edges between nodes. For example "1 4" means an edge between node 1 and 4.
Problem is, the output should be this:
[[0, 1, 0, 1, 0], [0, 0, 1, 0, 1], [1, 0, 0, 1, 0], [0, 1, 0, 0, 1], [1, 0, 1, 0, 0]]
But instead of that, I get this:
[[0, 1, 0, 1, 0], [0, 0, 1, 0, 1], [0, 0, 0, 1, 0], [0, 1, 0, 0, 1], [1, 0, 1, 0, 0]]
Only one number is different and I can't understand why is this happening. The edge "3 1" is not present. Can someone explain, where is the problem?
Change for i in range(0, gp_edgeCount-1): to
for i in range(0, gp_edgeCount):
The range() function already does the "-1" operation. range(0,3) "==" [0,1,2]
And it is not the "3 1" edge that is missing, it is the "2 0" edge that is missing, and that is the last edge. The matrices start counting at 0.
Matthias has it; you don't need edgeCount - 1 since the range function doesn't include the end value in the iteration.
There are several other things you can do to clean up your code:
The with operator is preferred for opening files, since it closes them automatically for you
You don't need to call find and manually slice, split already does what you want.
You can convert and assign directly to a pair of numbers using a generator expression and iterable unpacking
You can call range with just an end value, the 0 start is implicit.
The multiplication operator is handy for initializing lists
With all of those changes:
with open('graph.txt', 'r') as graph:
node_count, edge_count = (int(n) for n in graph.readline().split())
matrix = [[0]*node_count for _ in range(node_count)]
for i in range(edge_count):
src, dst = (int(n) for n in graph.readline().split())
matrix[src][dst] = 1
print matrix
# [[0, 1, 0, 1, 0], [0, 0, 1, 0, 1], [1, 0, 0, 1, 0], [0, 1, 0, 0, 1], [1, 0, 1, 0, 0]]
Just to keep your code and style, of course it could be much more readable:
gs = open("graph.txt", "r")
gp = gs.readline()
gp_splitIndex = gp.split(" ")
gp_nodeCount = int(gp_splitIndex[0])
gp_edgeCount = int(gp_splitIndex[1])
matrix = [] # predecare the array
for i in range(0, gp_nodeCount):
matrix.append([])
for y in range(0, gp_nodeCount):
matrix[i].append(0)
for i in range(0, gp_edgeCount):
gp = gs.readline()
gp_Index = gp.split(" ") # get the index of space, dividing the 2 numbers on a row
gp_from = int(gp_Index[0])
gp_to = int(gp_Index[1])
matrix[gp_from][gp_to] = 1
print matrix
Exactly is the last instance not used..the 2 0 from your file. Thus the missed 1. Have a nice day!
The other answers are correct, another version similar to the one of tzaman:
with open('graph.txt', mode='r') as txt_file:
lines = [l.strip() for l in txt_file.readlines()]
number_pairs = [[int(n) for n in line.split(' ')] for line in lines]
header = number_pairs[0]
edge_pairs = number_pairs[1:]
num_nodes, num_edges = header
edges = [[0] * num_nodes for _ in xrange(num_nodes)]
for edge_start, edge_end in edge_pairs:
edges[edge_start][edge_end] = 1
print edges

Categories

Resources