I have a file called "magic.txt" which contains the following numbers:
3
8 1 6
3 5 7
4 9 2
The "3" stands for the NxN size of the square, and the rest of the numbers is the potential magic square. I wrote code that can sum up all the rows and the columns and the first diagonal (namely, the numbers 8, 5, 2). However I have no clue how to solve for the other diagonal (namely, 6, 5, 4). Below is my code for the first diagonal.
def sum_diagonal():
with open("magic.txt") as file:
text = file.readlines() # Read magic.txt file
square_size = int(text.pop(0)) # Pop off the square size from the list and converting it to an integer
terminator = int(text.pop(square_size)) # Pop off the -1 terminator
sumdia1 = 0
for x in range(square_size): # This for loop is to loop through all the rows and add up the diagonal.
text_list = text[x].split() # Splits the y-th index into its own list (multi-dimensional list)
sumdia1 = sumdia1 + int(text_list[x]) # Sum up the diagonal 1
print("Sum of diagonal 1:", sumdia1)
Any suggestions would be appreciated.
You may notice the index of the other diagonal is (i, 2-i), or (i, square_size-1-i) in your case.
So you can do something similar to before
def sum_diagonal():
with open("magic.txt") as file:
text = file.readlines() # Read magic.txt file
square_size = int(text.pop(0)) # Pop off the square size from the list and converting it to an integer
terminator = int(text.pop(square_size)) # Pop off the -1 terminator
sumdia1 = 0
for x in range(square_size): # This for loop is to loop through all the rows and add up the diagonal.
text_list = text[x].split() # Splits the y-th index into its own list (multi-dimensional list)
sumdia1 = sumdia1 + int(text_list[x]) # Sum up the diagonal 1
print("Sum of diagonal 1:", sumdia1)
sumdia2 = 0
for x in range(square_size): # This for loop is to loop through all the rows and add up the diagonal.
text_list = text[x].split() # Splits the y-th index into its own list (multi-dimensional list)
sumdia2 = sumdia2 + int(text_list[square_size-1-x]) # Sum up the diagonal 1
print("Sum of diagonal 2:", sumdia2)
Related
Title. Essentially I want to replace the characters that would be randomly generated in a 2d List I made. Here's an example, I'd like to replace 0 with 9
0 0 0 0
1 1 1 1
2 2 2 2
3 3 3 3
9 9 9 9
1 1 1 1
2 2 2 2
3 3 3 3
But I am not entirley familiar with how I am supposed to do this because I am rather new at programming.
My first attempt was to make a function with a parameter that wiuld Identify and characters that had 0 and then make a seperate funtinon that would return it and replace it with 9, but it wouldn't even start it, and I have no idea where to go from there. Any help would be
appreciated.
code:
import random
SIZE = 4
EMPTY = " "
PERSON = "P"
PET = "T"
POOP = "O"
ERROR = "!"
CLEANED = "."
MAX_RANDOM = 10
def clean(world,endRow,endColumn):
if world == POOP, POOP == CLEAN:
print("Scooping the poop")
# #args(reference to a alist of characters,integer,integer)
# Function will count the number of occurences of the character specified by the user up the specified
# end point (row/column specified by the user).
# #return(character,integer)
def count(world,endRow,endColumn):
print("Counting number of occurances of a character")
number = 0
element = input("Enter character: ")
return(element,number)
# Randomly generates an 'occupant' for a location in the world
# #args(none)
# Randomly generates and returns a character according to the specified probabilities.
# *50% probability empty space
# *20% probability of a person
# *10% probability of a pet
# *20% probability of fecal matter
# #return(character)
def createElement():
tempNum = random.randrange(MAX_RANDOM)+1
# 50% chance empty
if ((tempNum >= 1) and (tempNum <= 5)):
tempElement = EMPTY
# 20% of a person
elif ((tempNum >= 6) and (tempNum <= 7)):
tempElement = PERSON
# 10% chance of pet
elif (tempNum == 8):
tempElement = PET
# 20% chance of poop in that location (lots in this world)
elif ((tempNum >= 9) and (tempNum <= 10)):
tempElement = POOP
# In case there's a bug in the random number generator
else:
tempElement = ERROR
return(tempElement)
# Creates the SIZExSIZE world. Randomly populates it with the
# return values from function createElement
# #args(none)
# Randomly populates the 2D list which is returned to the caller.
# #return(reference to a list of characters)
def createWorld():
world = [] # Create a variable that refers to a 1D list.
r = 0
# Outer 'r' loop traverses the rows.
# Each iteration of the outer loop creates a new 1D list.
while (r < SIZE):
tempRow = []
world.append(tempRow) # Create new empty row
c = 0
# The inner 'c' loop traverses the columns of the newly
# created 1D list creating and initializing each element
# to the value returned by createElement()
while (c < SIZE):
element = createElement()
tempRow.append(element)
c = c + 1
r = r + 1
return(world)
# Shows the elements of the world. All the elements in a row will
# appear on the same line.
# #args(reference to a list of characters)
# Displays the 2D list with each row on a separate line.
# #return(nothing)
def display(world):
print("OUR WORLD")
print("========")
r = 0
while (r < SIZE): # Each iteration accesses a single row
c = 0
while (c < SIZE): # Each iteration accesses an element in a row
print(world[r][c], end="")
c = c + 1
print() # Done displaying row, move output to the next line
r = r + 1
# #args(none)
# #return(integer,integer)
def getEndPoint():
#Declaring local variables
endRow = -1
endColumn = -1
return(endRow,endColumn)
# Starting execution point for the program.
def start():
world = createWorld()
display(world)
endRow,endColumn = getEndPoint()
element,number = count(world,endRow,endColumn)
print("# occurances of %s=%d" %(element,number))
clean(world,endRow,endColumn)
display(world)
start()
As a newbie to python, I've come across a task that I'm having trouble completing. I am supposed to create a new matrix, taking into consideration the original one, inputted by the user, where each element corresponds to the number of adjacent elements greater or equal to the corresponding one in the original matrix. Since English is not my native language, I might not have presented it properly so here is an example:
input:
3x3 matrix
9 14 13
3 0 7
8 15 15
output:
3x3 matrix
2 5 2
1 0 1
2 5 3
So, if it isn't clear, the new matrix determines how many adjacent elements are greater or equal to an element in the original one. 9 is greater than 3 & 0, so that results in "2", 14 is greater than all the adjacent ones so it prints out "5", etc... It also takes diagonals into consideration, of course.
So far, I've got down the input of the original matrix but I'm unsure how to proceed further. I am not someone who's got access to university materials, professors or peer help and my experimentation and search online has been futile so far. I do not need a complete solution, rather than pointers and concept explanation.
This is the code so far:
# matrix input
rOne = int(input("Number of rows:"))
cOne = int(input("Number of columns:"))
# initialize matrix
matrixOne = []
print("Enter elements rowwise:")
# user input
for i in range(rOne): # for loop za redove
a =[]
for j in range(cOne): # for loop za kolone
a.append(int(input()))
matrixOne.append(a)
# print matrix one
for i in range(rOne):
for j in range(cOne):
print(matrixOne[i][j], end = " ")
print()
Here is a function that can do the exact thing:
def adj_matrix(matrixOne, rOne, cOne):
new_lst = []
for i in range(rOne):
a = []
for j in range(cOne):
count = 0
x, y = (i, j) # matrix values here
cells = list(starmap(lambda a,b: (x+a, y+b), product((0,-1,+1), (0,-1,+1)))) # this will find all the adjacent index
filtered_cell = [p for p in cells if (sum(p)>=0 and prod(p)>=0)] # this filters out all the negative indexs
filtered_cell = [p for p in filtered_cell if p[0]<rOne and p[1]<cOne] # this filters out index that are greater than matrix
for z in filtered_cell:
if matrixOne[i][j] >= matrixOne[z[0]][z[1]]:
count += 1
a.append(count-1)
new_lst.append(a)
return new_lst
also import:
from itertools import product, starmap
from math import prod
Actually managed to solve the thing, feels amazing :D
def get_neighbor_elements(current_row, current_col, total_rows, total_cols):
neighbors = []
for i in [-1, 0, 1]: # red pre, isti red, red posle
for j in [-1, 0, 1]: # kolona pre, ista kolona, kolona posle
row = current_row + i
col = current_col + j
if row < 0 or col < 0 or row >= total_rows or col >= total_cols: # preskace se ako se izaslo iz granica matrice
continue
if row == current_row and col == current_col:# ako su red i kolona isti, preskace se(to je taj isti element)
continue
neighbor = [row, col]
neighbors.append(neighbor)
return neighbors
def make_new_matrix(old_matrix):
new_matrix = []
for i in range(len(old_matrix)):
new_matrix.append([])
for i in range(len(old_matrix)): # iteriramo kroz redove stare matrice
for j in range(len(old_matrix[i])): # iteriramo kroz kolone stare matrice
neighbors = get_neighbor_elements(i, j, len(old_matrix), len(old_matrix[i])) # dobavljamo komsije
count = 0
for neighbor in neighbors: # sad gledamo da li je trenutni element veci ili jednak susednim
if old_matrix[i][j] >= old_matrix[neighbor[0]][neighbor[1]]:
count += 1
new_matrix[i].append(count)
return new_matrix
def print_matrix(matrix):
for i in range(len(matrix)):
for j in range(len(matrix[i])):
print(str(matrix[i][j]) + " ", end='')
print()
if __name__ == '__main__':
matrix = [[12, 10], [2, 10]]
print("Old matrix: ")
print_matrix(matrix)
new_matrix = make_new_matrix(matrix)
print("New matrix")
print_matrix(new_matrix)
I have a coding assignment to input row and column length, and create a power table. THe example below is for 5 rows, 5 columns.
The code I have so far prints the correct number of rows and columns, but I haven't been able to get the calculations to work. It just shows a table of 1's, five by five.
rows = int(input("Enter a number of rows: "))
cols = int(input("Enter a number of columns: "))
x = 1
y = 1
z = 1
line = ""
while x <= cols :
line = line + format(y**cols, "4d")
x = x + 1
while z <= rows :
print(line)
z = z + 1
The basic problem is that you need to nest your loops. Your second problem is that you never change y. What you do at the moment is to compute the power sequence for 1 into five different lines -- and then you print that last line only five times. Try two changes:
Compute a line, then print it immediately. Then you go to the next line.
Use the correct variable.
After changes:
while z <= rows:
while x <= cols:
line = line + format(x**cols, "4d") # Note the variable change
x = x + 1
print(line)
z = z + 1
Also, look up the for statement, as this will simplify things. After that, look up list comprehension for even more compression.
Here is a way to do it that preserves padding no matter what:
def grid(rows, cols, padding):
max_num_len = len(str(rows**cols))
return '\n'.join([
''.join(['{{:>{}}}'.format(max_num_len+padding).format((row+1)**(col+1))
for col in range(cols)])
for row in range(rows)
])
print(grid(5, 5, 3))
Instead, try creating a 2D array in Python such as a 2D list.
Matrix = [[0 for x in range(5)] for y in range(5)]
for i in range(5):
for j in range(5):
Matrix[i][j]=j^i
Then, print the data you need using nested for loops.
for i in range (5):
for j in range(5):
print(Matrix[j][i])
My code first takes in user input where:
n = the number of vertices in a graph
file = the file to compute
In this case, my file is a .txt file containing:
0 1
2 1
0 2
1 3
My code successfully converts this into an adjacency list with the output [[1, 2], [0, 2, 3], [1, 0], [1]]. The problem however, is to convert it into a adjacency matrix. I am aware that the main problem with my code is at this line:
for x in range(len(vertices)):
matrix[z-1][vertices[x]] = 1
Here is my full code:
n = int(input("Enter the number of vertices: ")) ## E.g. 4
file = input("Enter the filename: ") ## E.g. graph.txt
vertices = []
matrix = [] ## define list
for x in range(n):
matrix.append([0]*n]) ## append a list for n, e.g. if n = 4 then [[][][][]]
vertices.append([])
f =open(file)
z = 0
for line in f: ##loop statement until no more line in file
line = line.split() ## turn every line into a list
z+=1
for y in range(len(line)):
line[y] = line[y].strip() ## remove spaces
line[y] = int(line[y]) ## converts line list into integer
## add value of line into main list
vertices[line[0]].append(line[1])
vertices[line[1]].append(line[0])
for z in range(len(matrix)):
for x in range(len(vertices)):
matrix[z-1][vertices[x]] = 1
print(vertices)
print(matrix)
First of all you are using z-1 as an index which could be -1, so that should just be z.
Secondly, you're accessing vertices[x] in the inner loop as if it has a node number, but it is a nested list. Instead, you need vertices[z][x]. For performance it is in principle better to create a name for vertices[z]:
for z in range(len(matrix)):
neighbors = vertices[z]
for x in range(len(neighbors)):
matrix[z][neighbors[x]] = 1
Or:
for z, neighbors in enumerate(vertices):
for x in neighbors:
matrix[z][x] = 1
I'm very sorry I'm asking this question, but my coding skills are not so great, so I can not solve this problem: there is a grid 5*5, and a task is to find minimal number of "lights", or "1" settled in a special way: in every 3*3 square of the big square, there must be exactly 4 "lights". Counting with a pen, I've got this minimal number equals 7 (the answer is right). So my solution looks like this:
#creates a list
grid = []
#creates lines
for row in range(5):
grid.append([])
#creates columns
for column in range(5):
grid[row].append(0)
#one "light" must be in a center
grid[2][2] = 1
#this array counts all "lights" and will notice when there are 4 of them
light_number = []
def counter():
for row in range(0, 3):
for column in range(0, 3):
if grid[row][column] == 1:
light_number.append(1)
print(len(light_number))
As expected, counter() works only for the first little 3*3 square. Wanting to have only one function for searching "lights" and not 9, I`ve tried to write something like this:
def counter():
#initial range of the counter
row_min = 0
row_max = 3
column_min = 0
column_max = 3
for i in range(9):
for row in range(row_min, row_max):
for column in range(column_min, column_max):
if grid[row][column] == 1:
#write it in a list
light_number.append(1)
column_min += 1
column_max += 1
row_min += 1
row_max += 1
#print a number of total lights
print(len(light_number))
But it doesn't work, saying that grid[row][column] == 1 is out of range.
So, the problem is:
I can't write working counter, which should automatically see all little squares 3*3
I don't know, how to write all combinations of "lights".
Please, if you have ANY idea, tell me. If you think there can be another solution, please, say also. Thanks in advance.
Until someone comes up with a smarter algorithm, I can offer you a brute-force solution to enumerate all grids.
Represent each row of a grid as a "binary" number from 0 (all lights in a row are off) to 31 (all lights are on). Then, a grid will be a 5-tuple of such numbers. There are 32^5 = 33554432 grids - something that is possible to brute-force within minutes, if done efficiently.
To check a number of lights (bits) in a 3x3 square that starts at row r and column c (where r and c are between 0 and 2), use bit shifts and masks:
s = (nbits[7 & (g[r + 0] >> (2 - c))]
+nbits[7 & (g[r + 1] >> (2 - c))]
+nbits[7 & (g[r + 2] >> (2 - c))])
where g is a grid and nbits holds the number of bits for each number from 0 to 7. If some s != 4, the grid is not valid, go on to the next one.
Putting it all together:
import itertools
# 0 1 2 3 4 5 6 7
nbits = [ 0,1,1,2,1,2,2,3 ]
def check(g):
for r in range(3):
for c in range(3):
s = (nbits[7 & (g[r + 0] >> (2 - c))]
+nbits[7 & (g[r + 1] >> (2 - c))]
+nbits[7 & (g[r + 2] >> (2 - c))])
if s != 4:
return False
return True
for g in itertools.product(range(32), repeat=5):
if check(g):
print g
for row in g:
print '{:05b}'.format(row)
print
The question was about learning something about programming. As far as I can see, a simple backtrack-mechanism should be used:
import numpy as np
#initialize the grid with the middle set to one
grid = np.zeros((5,5))
grid[2,2] = 1
First, we need a simple check function, that returns True if the global grid is
gracefully filled with ones:
# a method to check all sub squares starting at row and column 0 through 2
def checkgrid():
# row 0 through 2
for r in xrange(3):
# column 0 through 2
for c in xrange(3):
# sum up all entries of grid matrix
if grid[r:r+3, c:c+3].sum() != 4:
return False
return True
And here we go with the main method. The idea is the following: Every grid entry has a
unique identifier between zero and 24, its "idx". The aim is to find a valid configuration
where the six ones are spread correctly over the 24 grid entries (25 - middle entry).
All possible binom(24, 6)=134596 solutions are enumerated through a simple loop and a recursive call to place the remaining entries, until the check-method returns True the first time, i.e. when a valid configuration is found.
# method that is recursively applied to set the next one
def recursive_trial(first, depth, maxdepth):
# all ones are placed: check the grid
if depth == maxdepth:
return checkgrid()
# enumerate possible grid positions as idx == 5 * r + c
for idx in xrange(first, 25 - (maxdepth - depth + 1)):
# get row and column idx
r = idx / 5
c = idx % 5
# skip the middle
if grid[r,c] == 1:
continue
# set entry to one
grid[r,c] = 1
# call method recursively to place missing ones until 7 in the remainder of the array
if recursive_trial(idx + 1, depth + 1, maxdepth):
return True
# set entry back to zero
grid[r,c] = 0
# at this point, we failed with the current configuration.
return False
A call to
recursive_trial(0, 0, 6)
print grid
yields (in a matter of milliseconds)
[[ 0. 0. 1. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 1. 1. 1. 1. 1.]
[ 0. 0. 1. 0. 0.]
[ 0. 0. 0. 0. 0.]]
This is how I will solve it:
grid = [[0,0,0,0,0],[0,0,0,0,0],[0,0,1,0,0],[0,0,0,0,0],[0,0,0,0,0]]
grid33total = [[0,0,0],[0,0,0],[0,0,0]]
for i in range(3):
for j in range(3):
grid33total[i][j] = sum(sum(x[0+i:3+i]) for x in grid[0+j:3+j])
total = sum(sum(x) for x in grid33total)
The array grid33total contains the number of "lights" for each of the 3x3 squares.
So, thankfully to efforts and help, I've came up with a solution.
import itertools
from pprint import pprint
import sys
def check(grid):
count = 0
for row in range(3):
for column in range(3):
s = 0
for right in range(3):
for down in range(3):
if grid[row+right][column+down] == 1:
s += 1
if s == 4:
count += 1
if count != 9:
return False
else:
return True
for n in range(4, 25):
for comb in itertools.combinations(range(25), n):
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]]
for index in comb:
row = index // 5
column = index % 5
grid[row][column] = 1
if check(grid):
print(n)
pprint(grid)
sys.exit()
I've decided to use itertools.combinations.
row = index // 5
column = index % 5
grid[row][column] = 1
is a very interesting way to determine whether there must be "1" or "0". Program looks at the result of integer division (//), and that will be a row number, and then at the residual (%), that will be a column number. Then it places "1" here.
I know, it's not so beautiful and short, as nbits solution, but it's also a possible variant. On my computer it works just about five minutes.