Counting elements in a matrix - python

I have this matrix:
matrix = [[a,r],[b,r],[c,r],[c,t,n],[b,t,n],[b,a]]
I want to count how many times did "n" appear in the matrix, but there is a condition. If the first letter is next to an "a" or an "r", it doesn't count as "n" appeared.
For example, in this list "n" appeared one time, because we have to discount the second time it appeared, due to the fact that the letter "b" later appeared next to an "a".
I've tried this:
c = 0
for i in range(len(matrix)):
if n in matrix[i]:
c+=1
But I have failed in all the conditions that I've tried if the letter that is next to "n" appears again next to an "a"

You will need to loop over the matrix twice (as suggested in the comments) to first make an ignore_list to skip unwanted lists and then to count the number of 'n's. You can do this as follows -
matrix = [['a','r'],['b','r'],['c','r'],['c','t','n'],['b','t','n'],['b','a']]
c = 0
ignore_list = []
for i in range(len(matrix)):
if matrix[i][1] == 'a':
if matrix[i][0] not in ignore_list:
ignore_list.append(matrix[i][0])
for i in range(len(matrix)):
if matrix[i][0] not in ignore_list:
if 'n' in matrix[i]:
c+=1
print(c)

Here's a way to do that using sets:
matrix = [["a","r"],["b","r"],["c","r"],["c","t","n"],["b","t","n"],["b","a"]]
# get the indices of the items containing 'n'
n_inx = [inx for inx in range(len(matrix)) if 'n' in matrix[inx]]
# get the indices of the items containing 'n'
a_inx = [inx for inx in range(len(matrix)) if 'a' in matrix[inx]]
# create a list of these items +1 position and -1 position.
a_inx = [[a-1, a+1] for a in a_inx]
a_inx = [inx for s in a_inx for inx in s]
# drop the 'n's that have 'a' next to them.
len(set(n_inx).difference(a_inx))
The result is 1.

Related

Finding the highest sum of a string in a list

In this task, we creating a function called highsum. It looks at a list of strings and sums up all the numerical characters. We then return the location of the element of the list with the highest value.
For example given list highestSum([“jx72i9r”, “9ch37#r2”, “8rgku3op8”]).
We then must find [17, 21,19] which is all the numerical values added up. Because 21 is the highest value we need the function to return 1 because that is the location of 9ch37#r2 in the list.
This is what I have so far:-
def highestSum(stringList):
number= 0
for xinlist in stringList:
print(xinlist)
for yoflist in xinlist:
print (yoflist)
if yoflist in "1234567890":
number+=int(yoflist)
print(number)
The first for loop cycles through each element while the second for loop cycles through each character in the elements. My accumulator variable work but the problem is I don't know how to let it know when it moves on to a new element.
Another example highestSum([“90gw1xy3”, “12432”, “hfkvbd2”, “*&hdj!4”])
this would return 0 as it as the highest sum of digit characters.
Homemade version
Basically, we gather turn each element in the given list to there digits sum. So like [18,21,19]. Then pair this with original list using zip(). Then use .index() in order to get the corresponding index.
hilarious one-liner
def highestSum(stringList):
return stringList.index({k:v for k,v in zip([sum(list(map(int,[character for character in stringEx if character.isdigit()]))) for stringEx in stringList],stringList)}[max(summed)])
List comprehension & dict comprehension
def highestSum(stringList):
summed = [sum(list(map(int,[character for character in stringEx if character.isdigit()]))) for stringEx in stringList]
highest = max(summed)
pair = {k:v for k,v in zip(summed,stringList)}
return stringList.index(pair[highest])
print(highestSum(["jx72i9r", "9ch37#r2", "8rgku3op8"]))
Easier to understand for the human eye.
def highestSum(stringList):
summed = []
for stringEx in stringList:
gathered = []
for character in stringEx:
if character.isdigit():
gathered.append(character)
gathered = sum(list(map(int,gathered)))
summed.append(gathered)
highest = max(summed)
pair = {}
for k,v in zip(summed,stringList):
pair[k] = v
return stringList.index(pair[highest])
print(highestSum(["jx72i9r", "9ch37#r2", "8rgku3op8"]))
output
1
I have modified your code. Look at this solution. You need a condition to for the highest number in the list and a variable to keep track of its index. See solution below:
def highestSum(stringList):
index = 0
highestValue = 0
for xinlist in stringList:
number= 0
for yoflist in xinlist:
if yoflist in "1234567890":
number+=int(yoflist)
if number > highestValue:
index = stringList.index(xinlist)
highestValue = number
print(index)
stringList = ['jx72i9r', '9ch37#r2', '8rgku3op8']
highestSum(stringList)
def highestSum(stringList):
res = list()
for xinlist in stringList:
number = 0
for yoflist in xinlist:
if yoflist in "1234567890":
number += int(yoflist)
res.append(number)
# find the max position form the accumulator
maxNumPos = 0
for i in range(len(res)):
if res[i] > res[maxNumPos]:
maxNumPos = i
print(maxNumPos)
highestSum(['90gw1xy3', '12432', 'hfkvbd2', '*&hdj!4'])
I'll use list comprehension, maybe it's difficult to read.
code:
x = ["jx72i9r", "9ch37#r2", "8rgku3op8"]
x_to_int = [sum([int(char) for char in s if char.isdigit()]) for s in x]
print(x_to_int.index(max(x_to_int)))
result:
1

Trying to understand the length of the list [PYTHON]

I'm studying python and at the moment I'm focusing on Lists.
The book that I'm reading for it, uses this code as example for creating a third list it doesn't repeat elements that exists in both lists:
first = []
second = []
while True:
e = int(input("Enter a value for the first list (0 to end):"))
if e==0:
break
first.append(e)
while True:
e = int(input("Enter a value for the second list (0 to finish):"))
if e==0:
break
second.append(e)
third = []
two_lists = first[:]
two_lists.extend(second)
x=0
while x < len(two_lists):
y = 0
while y < len(third): #**THIS LINE IS MY QUESTION**
if two_lists[x] == third[y]:
break;
y=y+1
if y == len(third):
third.append(two_lists[x])
x=x+1
x=0
while x < len(third):
print(third[x])
x=x+1
So, when he says while y < len(third) I don't understand why the len(third) is 1 and not 0, since third is set empty before the while part. Is there's something I'm missing?
Thanks.
On the first iteration of the loop at line 18, len(third) is indeed 0 and not 1.
So we don't get into the while loop of line 20, but instead, get into the if clause at line 24, only from that part on len(third) would be positive.
That is true the first time it comes to that while loop.
However, the outer loop populates the third list.
the length of third for the initial iteration should be 0 so that whole while loop will be jumped.
Then the following if statement will test true as 0 is equal to 0 and an element would then be added to your third array.

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.

How to change values in nested list python

The matrix represents cell points. If we imagine these cell points being a grid, we need to make the values within the matrix equal to the input T1 in quadrants 2 and 4 and the values input T2 for quadrants 1 and 3. As in, from row 0 to 2 and column 0 to 3 it should be the value T1. Also, I need to make this appear as cells, with lines in between all rows/columns.
#input values needed
A = input("Enter a value for the first heater/cooler temp: ")
B = input("Enter a value for the second heater/cooler temp: ")
T1 = input("Enter a value for the first initial plate temp: ")
T2 = input("Enter a value for the second initial plate temp: ")
#the stabilizing criterion value
matrix = []
for row in range(0,6):
matrix.append([])
for column in range(0,9):
matrix[row].append(column)
for row in matrix:
print(row)
In this code, row in range(0,6) refers to all positions of the matrix that are in the first row, then second, and so on. It loops over all the rows.
So matrix[0][x] refers to all the positions in the 0th row (and you can access each position by setting x = 1, 2, ...).
What you want to do, is set values to T1 for a specific set of rows and columns, right?
Since you are anyway looping through all the rows and columns, you can check if at any point, the combination of row and column falls in the desired range:
if row < 3 and column < 4:
matrix[row][column] = T1
What this does is, whenever the combination of row and column numbers falls in the range that is, row = 0 to 2 and column = 0 to 3, it sets the value at those positions in the matrix, to T1.
Does this answer your question?
Now about the printing part, you can try a function like this:
def printy(P):
for i in range(len(P[0])):
print '---',
print
for i in range(len(P)):
for j in range(len(P[0])):
print P[i][j], '|',
print
for i in range(len(P[0])):
print '---',
print

Python sudoku checker

I'm working on an assignment for my CIS class in python. We have to code a Sudoku checker. In a 9x9 board we obviously have to check each row, col and 3x3 square for duplicates. I'm a little stuck on the idea of how to check the numbers by a 3x3 square. Below is my code for checking each row and col, if someone could help me a little with an outline or an approach just something for checking each 3x3 square that would be amazing!
self.columns = [ ]
for col in range(9):
col_tiles = [ ]
self.columns.append(col_tiles)
for row in range(9):
col_tiles.append(self.tiles[row][col])
self.squares = [ ]
for col in range(1, 10, 3):
for row in range(1, 10, 3):
square_tiles = [ ]
self.squares.append(square_tiles)
for x in range(3):
for y in range(3):
square_tiles.append(self.tiles[x][y])
This assumes you have the freedom to read the data and structure how you want. We want a set of unique values 1-9 for each row/column/3x3 grid, so one way is to either use a set or a list comparison (we'll use set here to make it cleaner). If we create a set equal to the numbers from 1 to 9, we have a point against which we can compare all of our other groups. Assume a structure like this (from here):
In [1]: r1 = [9,3,2,5,4,8,1,7,6]
In [2]: r2 = [1,8,7,9,2,6,5,4,3]
In [3]: r3 = [5,4,6,3,7,1,2,8,9]
# Continues....
Where each row represents a full row of data. Now lets create a section of that data that represents the first three rows, pull out one grid and compare the contents to our set:
In [4]: sec1 = [r1, r2, r3]
In [5]: nums = set(range(1, 10))
In [6]: nums == set(n for row in sec1 for n in row[:3])
Out[6]: True
This iterates over the first three rows and returns the first three elements in each of those rows. To get a better visual, here is the equivalent for-loop code to make it a bit easier to decipher:
result = set()
for row in sec1:
for n in row[:3]:
result.add(n)
Since our set of numbers includes everything from 1-9, we know it is valid. To move to the second, we range the row[:3] to row[3:6] (and row[6:9] after that). You'll then need to handle this for the next two sections as well. I'll leave it to you as to how to wrap this in a more dynamic structure (note the multiples of three), but hopefully this will get you started :)
Whenever you're having trouble coming up with an algorithm, just ask yourself: "How would I solve this manually, if the only way I could be given the problem was by a computer".
In other words, if I asked you to check the top left 3x3 grid, your eyes would just go to the top left corner and add up numbers. But if I said, check the top left 3x3 grid, and didn't actually give you the board, you'd say, "OK, give me the top left 3x3 grid".
And I'd say "How?"
And you'd say, "Imagine the tiles are numbered by rows and columns. I want the tiles in spots (0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), and (2,2)"
Does that help?
Here's what I would do: create 3 dictionaries, one for the rows, one for the columns, and one for the 3x3 squares.
while you loop through each element in the sudoku puzzle, keep track of your row and column (trivial), and use if statements to keep track of which 3x3 square you're in (a bit more involved)
then just send each element to the corresponding row, column, and 3x3 square dictionary, and compare at the end.
This way you only need to inspect each element once.
EDIT: also, set will probably be useful
This function will do. "sample" gives the randomness, so every time you run this you will get a different one.
from random import sample
def generate_sudoku_checker():
random_list = sample([1,2,3,4,5,6,7,8,9],9)
random_list = random_list + random_list[:9]
for i in range(3):
for j in range(3):
print(random_list[i+j*3:i+j*3+9])
Here is my solution to this :
Funtion:
def check_sudoku(lis):
n = len(lis)
digit = 1 #start from one
while (digit<=n):
i=0
while i<n: # go through each row and column
row_count=0
column_count=0
j=0
while j < n: # for each entry in the row / column
if lis[i][j] == digit: # check row count
row_count = row_count+1
if lis[j][i]== digit :
column_count = column_count+1
j=j+1
if row_count !=1 or column_count!=1:
return False
i=i+1 # next row/column
digit = digit+1 #next digit
return True
Late to the party but this worked for me:
def insert_sudoku():
puzzle = []
for i in range(9):
print("You've entered", len(puzzle), "rows so far")
row = input("Enter a row")
if len(row) < 9:
print("Not enough numbers on this row")
return insert_sudoku()
elif len(row) > 9:
print("Too many numbers. Try again!")
return insert_sudoku()
try:
row = [int(dig) for dig in row]
puzzle.append(row)
except:
print("Whoops, looks like you didn't enter only numbers somewhere. Try again!")
return insert_sudoku()
validate_entries(puzzle)
def validate_entries(puzzle):
check = [1, 2, 3, 4, 5, 6, 7, 8, 9]
b1, b2, b3, b4, b5, b6, b7, b8, b9 = [], [], [], [], [], [], [], [], []
for i in range(9):
z = []
for x in range(9):
z.append(puzzle[i][x])
puzzle.append(z)
for i in range(3):
b1 += (puzzle[i][:3])
b4 += (puzzle[i][3:6])
b7 += (puzzle[i][6:])
for i in range(3,6):
b2 += (puzzle[i][:3])
b5 += (puzzle[i][3:6])
b8 += (puzzle[i][6:])
for i in range(6,9):
b3 += (puzzle[i][:3])
b6 += (puzzle[i][3:6])
b9 += (puzzle[i][6:])
puzzle.append(b1)
puzzle.append(b2)
puzzle.append(b3)
puzzle.append(b4)
puzzle.append(b5)
puzzle.append(b6)
puzzle.append(b7)
puzzle.append(b8)
puzzle.append(b9)
for iter in puzzle:
if sorted(iter) != check:
print("No")
return
print("Yes")
insert_sudoku()
Inspired by this article
EDIT: Indentation might be off from copy + pasting the code.
What my answer adds is the use of a list comprehension to extract the tiles from the board.
"""
# good
board=[
[2,9,5,7,4,3,8,6,1],
[4,3,1,8,6,5,9,2,7],
[8,7,6,1,9,2,5,4,3],
[3,8,7,4,5,9,2,1,6],
[6,1,2,3,8,7,4,9,5],
[5,4,9,2,1,6,7,3,8],
[7,6,3,5,2,4,1,8,9],
[9,2,8,6,7,1,3,5,4],
[1,5,4,9,3,8,6,7,2]
]
"""
# bad
board = [
[1,9,5,7,4,3,8,6,2],
[4,3,1,8,6,5,9,2,7],
[8,7,6,1,9,2,5,4,3],
[3,8,7,4,5,9,2,1,6],
[6,1,2,3,8,7,4,9,5],
[5,4,9,2,1,6,7,3,8],
[7,6,3,5,2,4,1,8,9],
[9,2,8,6,7,1,3,5,4],
[2,5,4,9,3,8,6,7,1]
]
def check(l):
# each digit 1-9 should occur once
for n in range(1,10):
try:
l.index(n)
except ValueError:
return False
return True
# check the rows
for row in board:
print(check(row))
# check the columns
for column in [ [ board[r][c] for r in range(9) ] for c in range(9) ]:
print(check(column))
# check the tiles
for tile in [[board[r][c] for r in range(row, row + 3) for c in range(col, col + 3)] for row in range(0, 9, 3) for col in range(0, 9, 3)]:
print(check(tile))
This is my solution. I also want to confirm the time and space complexity of this code:
"""
Sample input 1:
295743861
431865927
876192543
387459216
612387495
549216738
763524189
928671354
154938672
Output: YES!
Sample input 2
195743862
431865927
876192543
387459216
612387495
549216738
763524189
928671354
254938671
Output: NOPE!!
"""
##################Solution############################################
def get_input():
#Get the input in form of strings and convert into list
print("Enter the board here: ")
lines = []
while True:
line = input()
if line:
lines.append(line)
else:
break
final = [(list(i)) for i in lines]
return final
def row_check(board):
# row check function which will be used in other two functions as well
text = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
x = True
for row in board:
if sorted(row) == text:
x = True
else:
x = False
return x
def col_check(board):
# Getting the list of 9 lists containing column elements
i = 0
j = 0
cols = [[], [], [], [], [], [], [], [], []]
for j in range(0, 9):
for i in range(0, 9):
cols[j].append(board[i][j])
return (row_check(cols))
def tile_check(board):
#Getting the list of 9 lists converting each tile of 3x3 into 9 element list
lst =[[],[],[],[],[],[],[],[],[]]
i = 0
j = 0
k = 0
while k<9:
for r in range(i,i+3):
for c in range(j, j+3):
lst[k].append(board[r][c])
j = j +3
k = k +1
if j == 9:
j = 0
i = i+3
return (row_check(lst))
#main program
c = get_input()
if row_check(c) and col_check(c) and tile_check(c):
print("YES!")
else:
print("NOPE!!")

Categories

Resources