Summarize data in a list in python - python

In python i need to summarize data in count_list this way (like a histogram):
"""
number | occurence
0 | *
1 | **
2 | ***
3 | **
4 | **
5 | *
6 | *
7 | **
8 | ***
9 | *
10 | **
"""
But instead I get this wrong output:
"""
number | occurence
0 |
1 | **
2 |
3 |
4 |
5 |
6 | **
7 |
8 |
9 |
10 | **
"""
Here is my code:
import random
random_list = []
list_length = 20
while len(random_list) < list_length:
random_list.append(random.randint(0,10))
count_list = [0] * 11
index = 0
while index < len(random_list):
number = random_list[index]
count_list[number] = count_list[number] + 1
index = index + 1
def summerizer():
index = 0
print count_list
print '"'*3
print 'number | occurrence'
while index < len(count_list):
print '%s' %' '*(7),
print index,#the problem is here
print ' | ',#and here
print '%s' %'*'*(count_list[index])
index += 1
print '%s'%'"'*3
summerizer()

This method uses collections.Counter:
from collections import Counter
import random
random_list = []
list_length = 20
while len(random_list) < list_length:
random_list.append(random.randint(0,10))
c = Counter(random_list)
print('number | occurrence')
def summerizer(dic):
for v,d in dic.items():
print(v, '|', '%s'%'*'*c[v])
summerizer(dic)

Yes i have found the problem
It is from the ide itself !!!
This was a quiz in a course on UDACITY android application and the embedded compiler inside it make this wrong answer..
Same code i tried now from pydroid application on Android also made the answer that i need without any change
Thanks for trying to help all of you
`import random
random_list = []
list_length = 20
while len(random_list) < list_length:
random_list.append(random.randint(0,10))
count_list = [0] * 11
index = 0
while index < len(random_list):
number = random_list[index]
count_list[number] = count_list[number] + 1
index = index + 1
def summerizer():
index = 0
print count_list
print '"'*3
print 'number | occurrence'
while index < len(count_list):
print '%s' %' '*(7),
print index,
print ' | ',
print '%s' %'*'*(count_list[index])
index += 1
print '%s'%'"'*3
summerizer()`

Try this
import random
random_list = []
list_length = 20
while len(random_list) < list_length:
random_list.append(random.randint(0,10))
dic={}
for i in random_list:
dic[i]=dic.get(i,0)+1
print 'number | occurrence'
for i in range(0,11):
if(i not in dic):
print i,"|",'%s' %'*'*(0)
else:
print i,"|",'%s' %'*'*(dic[i])
Out put
[9, 8, 4, 2, 5, 4, 8, 3, 5, 6, 9, 5, 3, 8, 6, 2, 10, 10, 8, 9]
number | occurrence
0 |
1 |
2 | **
3 | **
4 | **
5 | ***
6 | **
7 |
8 | ****
9 | ***
10 | **

Related

How should I solve logic error in timestamp using Python?

I have written a code to calculate a, b, and c. They were initialized at 0.
This is my input file
-------------------------------------------------------------
| Line | Time | Command | Data |
-------------------------------------------------------------
| 1 | 0015 | ACTIVE | |
| 2 | 0030 | WRITING | |
| 3 | 0100 | WRITING_A | |
| 4 | 0115 | PRECHARGE | |
| 5 | 0120 | REFRESH | |
| 6 | 0150 | ACTIVE | |
| 7 | 0200 | WRITING | |
| 8 | 0314 | PRECHARGE | |
| 9 | 0318 | ACTIVE | |
| 10 | 0345 | WRITING_A | |
| 11 | 0430 | WRITING_A | |
| 12 | 0447 | WRITING | |
| 13 | 0503 | WRITING | |
and the timestamps and commands are used to process the calculation for a, b, and c.
import re
count = {}
timestamps = {}
with open ("page_stats.txt", "r") as f:
for line in f:
m = re.split(r"\s*\|\s*", line)
if len(m) > 3 and re.match(r"\d+", m[1]):
count[m[3]] = count[m[3]] + 1 if m[3] in count else 1
#print(m[2])
if m[3] in timestamps:
timestamps[m[3]].append(m[2])
#print(m[3], m[2])
else:
timestamps[m[3]] = [m[2]]
#print(m[3], m[2])
a = b = c = 0
for key in count:
print("%-10s: %2d, %s" % (key, count[key], timestamps[key]))
if timestamps["ACTIVE"] > timestamps["PRECHARGE"]: #line causing logic error
a = a + 1
print(a)
Before getting into the calculation, I assign the timestamps with respect to the commands. This is the output for this section.
ACTIVE : 3, ['0015', '0150', '0318']
WRITING : 4, ['0030', '0200', '0447', '0503']
WRITING_A : 3, ['0100', '0345', '0430']
PRECHARGE : 2, ['0115', '0314']
REFRESH : 1, ['0120']
To get a, the timestamps of ACTIVE must be greater than PRECHARGE and WRITING must be greater than ACTIVE. (Line 4, 6, 7 will contribute to the first a and Line 8, 9, and 12 contributes to the second a)
To get b, the timestamps of WRITING must be greater than ACTIVE. For the lines that contribute to a such as Line 4, 6, 7, 8, 9, and 12, they cannot be used to calculate b. So, Line 1 and 2 contribute to b.
To get c, the rest of the unused lines containing WRITING will contribute to c.
The expected output:
a = 2
b = 1
c = 1
However, in my code, when I print a, it displays 0, which shows the logic has some error. Any suggestion to amend my code to achieve the goal? I have tried for a few days and the problem is not solved yet.
I made a function that will return the commands in order that match a pattern with gaps allowed.
I also made a more compact version of your file reading.
There is probably a better version to divide the list into two parts, the problem was to only allow elements in that match the whole pattern. In this one I iterate over the elements twice.
import re
commands = list()
with open ("page_stats.txt", "r") as f:
for line in f:
m = re.split(r"\s*\|\s*", line)
if len(m) > 3 and re.match(r"\d+", m[1]):
_, line, time, command, data, _ = m
commands.append((line,time,command))
def search_pattern(pattern, iterable, key=None):
iter = 0
count = 0
length = len(pattern)
results = []
sentinel = object()
for elem in iterable:
original_elem = elem
if key is not None:
elem = key(elem)
if elem == pattern[iter]:
iter += 1
results.append((original_elem,sentinel))
if iter >= length:
iter = iter % length
count += length
else:
results.append((sentinel,original_elem))
matching = []
nonmatching = []
for res in results:
first,second = res
if count > 0:
if second is sentinel:
matching.append(first)
count -= 1
elif first is sentinel:
nonmatching.append(second)
else:
value = first if second is sentinel else second
nonmatching.append(value)
return matching, nonmatching
pattern_a = ['PRECHARGE','ACTIVE','WRITING']
pattern_b = ['ACTIVE','WRITING']
pattern_c = ['WRITING']
matching, nonmatching = search_pattern(pattern_a, commands, key=lambda t: t[2])
a = len(matching)//len(pattern_a)
matching, nonmatching = search_pattern(pattern_b, nonmatching, key=lambda t: t[2])
b = len(matching)//len(pattern_b)
matching, nonmatching = search_pattern(pattern_c, nonmatching, key=lambda t: t[2])
c = len(matching)//len(pattern_c)
print(f'{a=}')
print(f'{b=}')
print(f'{c=}')
Output:
a=2
b=1
c=1

Pandas: how to incrementally add one to column while sum is less than corresponding column?

I am trying to increment a column by 1 while the sum of that column is less than or equal to a total supply figure. I also need that column to be less than the corresponding value in the 'allocation' column. The supply variable will be dynamic from 1-400 based on user input. Below is the desired output (Allocation Final column).
supply = 14
| rank | allocation | Allocation Final |
| ---- | ---------- | ---------------- |
| 1 | 12 | 9 |
| 2 | 3 | 3 |
| 3 | 1 | 1 |
| 4 | 1 | 1 |
Below is the code I have so far:
data = [[1.05493,12],[.94248,3],[.82317,1],[.75317,1]]
df = pd.DataFrame(data,columns=['score','allocation'])
df['rank'] = df['score'].rank()
df['allocation_new'] = 0
#static for testing
supply = 14
for index in df.index:
while df.loc[index, 'allocation_new'] < df.loc[index, 'allocation'] and df.loc[index, 'allocation_new'].sum() < supply:
df.loc[index, 'allocation_new'] += 1
print(df)
This should do:
def allocate(df, supply):
if supply > df['allocation'].sum():
raise ValueError(f'Unacheivable supply {supply}, maximal {df["allocation"].sum()}')
under_alloc = pd.Series(True, index=df.index)
df['allocation final'] = 0
while (missing := supply - df['allocation final'].sum()) >= 0:
assert under_alloc.any()
if missing <= under_alloc.sum():
df.loc[df.index[under_alloc][:missing], 'allocation final'] += 1
return df
df.loc[under_alloc, 'allocation final'] = (
df.loc[under_alloc, 'allocation final'] + missing // under_alloc.sum()
).clip(upper=df.loc[under_alloc, 'allocation'])
under_alloc = df['allocation final'] < df['allocation']
return df
At every iteration, we add the missing quotas to any rows that did not reach the allocation yet (rounded down, that’s missing // under_alloc.sum()), then using pd.Series.clip() to ensure we stay below the allocation.
If there’s less missing quotas than available ranks to which to allocate (e.g. run the same dataframe with supply=5 or 6), we allocate to the first missing ranks.
>>> df = pd.DataFrame( {'allocation': {0: 12, 1: 3, 2: 1, 3: 1}, 'rank': {0: 1, 1: 2, 2: 3, 3: 4}})
>>> print(allocate(df, 14))
allocation rank allocation final
0 12 1 9
1 3 2 3
2 1 3 1
3 1 4 1
>>> print(allocate(df, 5))
allocation rank allocation final
0 12 1 2
1 3 2 1
2 1 3 1
3 1 4 1
Here is a simpler version:
def allocate(series, supply):
allocated = 0
values = [0]*len(series)
while True:
for i in range(len(series)):
if allocated >= supply:
return values
if values[i] < series.iloc[i]:
values[i]+=1
allocated+=1
pass
allocate(df['allocation'], 14)
output:
[9,3,1,1]

How to print Sudoku grid more efficiently

I'm Programming Sudoku game in terminal, I want to Print the grid to console with a square around it as in the picture below.
There is no problem with my code except it is inefficient.
I would like to get it more efficient and short (with list comprehensions, string multiplying, etc).
the board is defined like that,
board = [[_ for _ in range(9)] for _ in range(9)]
That is the function i'm using:
def Print_Board(board):
print("\n-------------------------")
for i in range(9):
for j in range(9):
if board[i][j] is not None:
if j == 0:
print("|", end=" ")
print(f"{board[i][j]} ", end="")
if (j + 1) % 3 == 0:
print("|", end=" ")
if (i + 1) % 3 == 0:
print("\n-------------------------", end=" ")
print()
You can build a board format and throw all the data at it:
bar = '-------------------------\n'
lnf = '|' +(' {:}'*3 + ' |')*3 + '\n'
bft = bar + (lnf*3+bar)*3
print(bft.format(*(el for rw in board for el in rw)))
You only need to build the format once, of course. After that it's just a print.
Suggestion from JonSG in comments to encapsulate this in a closure:
def make_board_printer():
bar = '-------------------------\n'
lnf = '|' +(' {:}'*3 + ' |')*3 + '\n'
bft = bar + (lnf*3+bar)*3
return (lambda bd:print(bft.format(*(el for rw in bd for el in rw))))
is a function which returns a board printer function:
# make a printer:
b_print = make_board_printer()
# then as needed
b_print(board)
You could do this:
def print_board(board):
print("\n-------------------------")
for row_num, row in enumerate(board):
print("|", end=" ")
for col_num, item in enumerate(row):
print(item, end=" ")
if (col_num + 1) % 3 == 0:
print("|", end=" ")
if (row_num + 1) % 3 == 0:
print("\n-------------------------", end=" ")
print()
if __name__ == '__main__':
print_board(board=[range(9) for _ in range(9)])
Here is a (not more readable) solution for your problem:
board = [range(1,10) for i in range(9)]
print("-"*25)
for idx, row in enumerate(board):
rowStr = " | ".join([" ".join(map(str, row[i:i+3])) for i in range(0, len(row), 3)])
print(f'| {rowStr} |')
if (idx+1) % 3 == 0:
print("-"*25)
Output:
-------------------------
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
-------------------------
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
-------------------------
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
-------------------------

Does anyone know how to return a grid into the shell based on a txt file?

Iam trying to make a small interior designing app, I type a txt file and make my program return the grid on shell.
I just need to know how to make a grid where the height and width are both 20.
These are the codes I have so far.. I only know how to make the width but not the height. I also don't know how to get the numbers and letters from my txt file but i made my txt file into a list line by line.
f = open('Apt_3_4554_Hastings_Coq.txt','r')
bigListA = [ line.strip().split(',') for line in f ]
offset = " "
width = 20
string1 = offset
for number in range(width):
if len(str(number)) == 1:
string1 += " " + str(number) + " "
else:
string1 += str(number) + " "
print (string1)
A bit of an overkill, but it was fun to make a class around it:
def decimal_string(number, before=True):
"""
Convert a number between 0 and 99 to a space padded string.
Parameters
----------
number: int
The number to convert to string.
before: bool
Whether to place the spaces before or after the nmuber.
Examples
--------
>>> decimal_string(1)
' 1'
>>> decimal_string(1, False)
'1 '
>>> decimal_string(10)
'10'
>>> decimal_string(10, False)
'10'
"""
number = int(number)%100
if number < 10:
if before:
return ' ' + str(number)
else:
return str(number) + ' '
else:
return str(number)
class Grid(object):
def __init__(self, doc=None, shape=(10,10)):
"""
Create new grid object from a given file or with a given shape.
Parameters
----------
doc: file, None
The name of the file from where to read the data.
shape: (int, int), (10, 10)
The shape to use if no `doc` is provided.
"""
if doc is not None:
self.readfile(doc)
else:
self.empty_grid(shape)
def __repr__(self):
"""
Representation method.
"""
# first lines
# 0 1 2 3 4 5 6 7 ...
# - - - - - - - - ...
number_line = ' '
traces_line = ' '
for i in range(len(self.grid)):
number_line += decimal_string(i) + ' '
traces_line += ' - '
lines = ''
for j in range(len(self.grid[0])):
line = decimal_string(j, False) + '|'
for i in range(len(self.grid)):
line += ' ' + self.grid[i][j] + ' '
lines += line + '|\n'
return '\n'.join((number_line, traces_line, lines[:-1], traces_line))
def readfile(self, doc):
"""
Read instructions from a file, overwriting current grid.
"""
with open(doc, 'r') as open_doc:
lines = open_doc.readlines()
shape = lines[0].split(' ')[-2:]
# grabs the first line (line[0]),
# splits the line into pieces by the ' ' symbol
# grabs the last two of them ([-2:])
shape = (int(shape[0]), int(shape[1]))
# and turns them into numbers (np.array(..., dtype=int))
self.empty_grid(shape=shape)
for instruction in lines[1:]:
self.add_pieces(*self._parse(instruction))
def empty_grid(self, shape=None):
"""
Empty grid, changing the shape to the new one, if provided.
"""
if shape is None:
# retain current shape
shape = (len(self.grid), len(self.grid[0]))
self.grid = [[' ' for i in range(shape[0])]
for j in range(shape[1])]
def _parse(self, instruction):
"""
Parse string instructions in the shape:
"C 5 6 13 13"
where the first element is the charachter,
the second and third elements are the vertical indexes
and the fourth and fifth are the horizontal indexes
"""
pieces = instruction.split(' ')
char = pieces[0]
y_start = int(pieces[1])
y_stop = int(pieces[2])
x_start = int(pieces[3])
x_stop = int(pieces[4])
return char, y_start, y_stop, x_start, x_stop
def add_pieces(self, char, y_start, y_stop, x_start, x_stop):
"""
Add a piece to the current grid.
Parameters
----------
char: str
The char to place in the grid.
y_start: int
Vertical start index.
y_stop: int
Vertical stop index.
x_start: int
Horizontal start index.
x_stop: int
Horizontal stop index.
Examples
--------
>>> b = Grid(shape=(4, 4))
>>> b
0 1 2 3
- - - -
0 | |
1 | |
2 | |
3 | |
- - - -
>>> b.add_pieces('a', 0, 1, 0, 0)
>>> b
0 1 2 3
- - - -
0 | a |
1 | a |
2 | |
3 | |
- - - -
>>> b.add_pieces('b', 3, 3, 2, 3)
>>> b
0 1 2 3
- - - -
0 | a |
1 | a |
2 | |
3 | b b |
- - - -
"""
assert y_start <= y_stop < len(self.grid[0]),\
"Vertical index out of bounds."
assert x_start <= x_stop < len(self.grid),\
"Horizontal index out of bounds."
for i in range(x_start, x_stop+1):
for j in range(y_start, y_stop+1):
self.grid[i][j] = char
You can then have file.txt with:
20 20
C 5 6 13 13
C 8 9 13 13
C 5 6 18 18
C 8 9 18 18
C 3 3 15 16
C 11 11 15 16
E 2 3 3 6
S 17 18 2 7
t 14 15 3 6
T 4 10 14 17
and make:
>>> a = Grid('file.txt')
>>> a
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
- - - - - - - - - - - - - - - - - - - -
0 | |
1 | |
2 | E E E E |
3 | E E E E C C |
4 | T T T T |
5 | C T T T T C |
6 | C T T T T C |
7 | T T T T |
8 | C T T T T C |
9 | C T T T T C |
10| T T T T |
11| C C |
12| |
13| |
14| t t t t |
15| t t t t |
16| |
17| S S S S S S |
18| S S S S S S |
19| |
- - - - - - - - - - - - - - - - - - - -
You can represent the room as a 20x20 grid. One idea is a list of lists; personally I prefer a dict.
Read through the file and assign each point. (I assume you've handled parsing the file, since that wasn't the issue you posted.) For instance:
room[5, 13] = 'C'
Then you can iterate over the coordinates to provide your output.
for i in range(N_ROWS):
for j in range(N_COLS):
# Print the character if it exists, or a blank space.
print(room.get((i, j), default=' '), end='')
print() # Start a new line.

Weird Sudoku validation bug

I'm currently trying to program a recursive sudoku solving algorithm in Python. I made a class for Sudokus which contains some methods to help me manipulate the sudoku grid.
Here is my code :
class Sudoku:
def __init__(self, input, tokens = None):
self.data = {}
if tokens is None:
self.tokens = list(range(1, 10))
else:
self.tokens = tokens
assert len(self.tokens) == 9
if type(input) == dict:
self.data = input
else:
for i, cell in enumerate(input):
if cell in self.tokens:
self.data[i % 9, i // 9] = cell
def __repr__(self):
string = ''
canvas = [['.'] * 9 for line in range(9)]
for (col, row), cell in self.data.items():
canvas[row][col] = str(cell)
for y, row in enumerate(canvas):
if not y % 3:
string += "+-------+-------+-------+\n"
string += '| {} | {} | {} |\n'.format(' '.join(row[:3]), ' '.join(row[3:6]), ' '.join(row[6:]))
string += "+-------+-------+-------+"
return string
#classmethod
def sq_coords(cls, cell_x, cell_y):
#returns all coordinates of cells in the same square as the one in (cell_x, cell_y)
start_x, start_y = cell_x // 3 * 3, cell_y // 3 * 3
for dx in range(3):
for dy in range(3):
yield (start_x +dx, start_y + dy)
def copy(self):
return Sudoku(self.data)
def clues(self, cell_x, cell_y):
assert not self.data.get((cell_x, cell_y))
allowed = set(self.tokens)
#Remove all numbers on the same row, column and square as the cell
for row in range(9):
allowed.discard(self.data.get((cell_x, row)))
for col in range(9):
allowed.discard(self.data.get((col, cell_y)))
for coords in self.sq_coords(cell_x, cell_y):
allowed.discard(self.data.get(coords))
return allowed
def get_all_clues(self):
clues = {}
for row in range(9):
for col in range(9):
if not self.data.get((col, row)):
clues[col, row] = self.clues(col, row)
return clues
def fill_singles(self):
still_going = True
did_something = False
while still_going:
still_going = False
for (col, row), clues in self.get_all_clues().items():
if len(clues) == 1:
still_going = True
did_something = True
self.data[col, row] = clues.pop()
return did_something
def place_finding(self):
still_going = True
did_something = False
while still_going:
still_going = False
for token in self.tokens:
for group in self.get_groups():
available_spots = [coords for coords, cell in group.items() if cell == None and token in self.clues(*coords)]
if len(available_spots) == 1:
self.data[available_spots.pop()] = token
still_going = True
did_something = True
return did_something
def fill_obvious(self):
still_going = True
while still_going:
a = self.fill_singles()
b = self.place_finding()
still_going = a or b
def get_groups(self):
for y in range(9):
yield {(x, y) : self.data.get((x, y)) for x in range(9)}
for x in range(9):
yield {(x, y) : self.data.get((x, y)) for y in range(9)}
for n in range(9):
start_x, start_y = n % 3 * 3, n // 3 * 3
yield {(x, y) : self.data.get((x, y)) for x, y in self.sq_coords(start_x, start_y)}
def is_valid(self):
for group in self.get_groups():
if any([list(group.values()).count(token) > 1 for token in self.tokens]):
return False
return True
def is_solved(self):
return self.is_valid() and len(self.data) == 9 * 9
def solve(sudoku):
def loop(su):
if su.is_solved():
print(su)
elif su.is_valid():
su.fill_obvious()
print(su)
for coords, available_tokens in sorted(su.get_all_clues().items(), key=lambda kv: len(kv[1])):
for token in available_tokens:
new_su = su.copy()
new_su.data[coords] = token
loop(new_su)
loop(sudoku)
with open('input.txt') as f:
numbers = ''
for i, line in enumerate(f):
if i >= 9:
break
numbers += line.rstrip().ljust(9)
s = Sudoku(numbers, tokens='123456789')
print(s)
solve(s)
print(s)
Sorry if this seems messy but I'd rather give you everything I have than only some data that may or may not contain the problem.
As you can see, the first thing it does is filling the Sudoku with only 100% sure numbers using the methods fill_singles (fills every cell that can only be filled with number x, eg the 8 other possibilities are in its row, column or block) and place_finding (checks all tokens and see if there's only one space in a group - row, column or block - where they can fit). It loops through both of those until nothing can be done.
Afterwards, it tries every possibility in spaces that have least and tries to solves the newly made grid with the same method. That's where my problem is. Currently, for debug purposes, the program prints grids it comes across whenever they're valid (no same number twice in a group). Actually that's what I'd like it to do. However it doesn't work like this; with this input :
+-------+-------+-------+
| . . . | . 2 6 | . . 4 |
| . . . | 7 9 . | 5 . . |
| . . . | . . . | 9 1 . |
+-------+-------+-------+
| . 8 . | 1 . . | . . . |
| 2 3 6 | . . . | 1 8 5 |
| . . . | . . 3 | . 7 . |
+-------+-------+-------+
| . 4 7 | . . . | . . . |
| . . 3 | . 7 8 | . . . |
| 5 . . | 6 3 . | . . . |
+-------+-------+-------+
It outputs grids such as this one, which is obviously not valid:
+-------+-------+-------+
| 1 4 9 | 3 2 6 | 7 3 4 |
| 3 2 4 | 7 9 1 | 5 1 8 |
| 3 7 5 | 3 2 4 | 9 1 2 |
+-------+-------+-------+
| 7 8 6 | 1 1 4 | 3 2 5 |
| 2 3 6 | 9 4 7 | 1 8 5 |
| 4 1 7 | 2 3 3 | 6 7 4 |
+-------+-------+-------+
| 2 4 7 | 1 1 3 | 5 4 6 |
| 1 3 3 | 4 7 8 | 2 5 1 |
| 5 5 4 | 6 3 2 | 1 3 7 |
+-------+-------+-------+
I really cannot understand why it allows such grids to pass the is_valid test, especially considering that when I manually input the grid above, it doesn't pass the test :
>>> s
+-------+-------+-------+
| 1 4 9 | 3 2 6 | 7 3 4 |
| 3 2 4 | 7 9 1 | 5 1 8 |
| 3 7 5 | 3 2 4 | 9 1 2 |
+-------+-------+-------+
| 7 8 6 | 1 1 4 | 3 2 5 |
| 2 3 6 | 9 4 7 | 1 8 5 |
| 4 1 7 | 2 3 3 | 6 7 4 |
+-------+-------+-------+
| 2 4 7 | 1 1 3 | 5 4 6 |
| 1 3 3 | 4 7 8 | 2 5 1 |
| 5 5 4 | 6 3 2 | 1 3 7 |
+-------+-------+-------+
>>> s.is_valid()
False
Can anyone see an error in my code that I haven't noticed? I'm sorry I'm not really being specific but I tried looking through every piece of my code and can't seem to find anything.
For #AnandSKatum :
26 4
79 5
91
8 1
236 185
3 7
47
3 78
5 63
here is a better implementation that I wrote for you
from numpy.lib.stride_tricks import as_strided
from itertools import chain
import numpy
def block_view(A, block= (3, 3)):
"""Provide a 2D block view to 2D array. No error checking made.
Therefore meaningful (as implemented) only for blocks strictly
compatible with the shape of A."""
# simple shape and strides computations may seem at first strange
# unless one is able to recognize the 'tuple additions' involved ;-)
shape= (A.shape[0]/ block[0], A.shape[1]/ block[1])+ block
strides= (block[0]* A.strides[0], block[1]* A.strides[1])+ A.strides
return chain.from_iterable(as_strided(A, shape= shape, strides= strides))
def check_board(a):
"""
a is a 2d 9x9 numpy array, 0 represents None
"""
for row,col,section in zip(a,a.T,block_view(a,(3,3))):
s = list(chain.from_iterable(section))
if any(sum(set(x)) != sum(x) for x in [row,col,s]):
return False
return True
a = numpy.array(
[
[9,8,7,6,5,4,3,2,1],
[2,1,5,0,0,0,0,0,0],
[3,6,4,0,0,0,0,0,0],
[4,2,0,0,0,0,0,0,0],
[5,3,0,0,0,0,0,0,0],
[6,7,0,0,0,0,0,0,0],
[7,0,0,0,0,0,0,0,0],
[8,0,0,0,0,0,0,0,0],
[1,0,0,0,0,0,0,0,0],
]
)
print check_board(a)

Categories