Display 2D sudoku board in python - python

i am trying to display a 2D sudoku board in python like this:
0 0 3 |0 2 0 |6 0 0
9 0 0 |3 0 5 |0 0 1
0 0 1 |8 0 6 |4 0 0
------+------+------
0 0 8 |1 0 2 |9 0 0
7 0 0 |0 0 0 |0 0 8
0 0 6 |7 0 8 |2 0 0
------+------+------
0 0 2 |6 0 9 |5 0 0
8 0 0 |2 0 3 |0 0 9
0 0 5 |0 1 0 |3 0 0
I managed to display the board without the seperation lines using this code:
rows = 'ABCDEFGHI'
cols = '123456789'
def display(values):
for r in rows :
for c in cols :
print values[r+c],
print
values is a dictionary {'A1':'0', 'A2':'0', 'A3':'3', 'A4':'0', 'A5':'2'...etc} I get this output:
0 0 3 0 2 0 6 0 0
9 0 0 3 0 5 0 0 1
0 0 1 8 0 6 4 0 0
0 0 8 1 0 2 9 0 0
7 0 0 0 0 0 0 0 8
0 0 6 7 0 8 2 0 0
0 0 2 6 0 9 5 0 0
8 0 0 2 0 3 0 0 9
0 0 5 0 1 0 3 0 0
Any help?

The following may work. But I think that a function that render a string as a result may be more useful (for writing the result to a text file for example, without too much monkey-patching).
rows = 'ABCDEFGHI'
cols = '123456789'
def display(values):
for i, r in enumerate(rows):
if i in [3, 6]:
print '------+-------+------'
for j, c in enumerate(cols):
if j in [3, 6]:
print '|',
print values[r + c],
print
Result:
9 6 0 | 5 0 7 | 9 5 2
1 9 3 | 9 3 4 | 5 4 2
4 9 7 | 2 3 0 | 1 3 1
------+-------+------
3 0 1 | 6 7 3 | 9 8 3
2 4 5 | 7 8 7 | 8 0 8
0 1 4 | 9 3 9 | 3 9 6
------+-------+------
6 1 2 | 8 7 6 | 5 0 1
4 3 9 | 3 0 8 | 5 6 6
4 1 7 | 5 9 9 | 3 1 7

Here's an approach that's a bit messy. If you add some other identifier to your row and column strings, you actually get the in between columns in a recognizable form:
# Use "x" as an identifier for a row or column where there should be a separator
rows = 'ABCxDEFxGHI'
cols = '123x456x789'
values = {'A1': '0', 'A2': '0', 'A3': '3'}
def display(values):
for r in rows:
for c in cols:
if r == "x":
if c == "x":
# Both row and column are the separator, show a plus
print "+",
else:
# Only the row is the separator, show a dash
print "-"
elif c == "x":
# Only the column is the separator, show a pipe
print "|",
else:
# Not a separator, print the given cell (or ? if not found)
print values.get(r+c, "?"),
# Make sure there's a newline so we start a new row
print ""
display(values)
Another possibility is to be more clever and insert the separator modified cells into the dictionary (ie "xx": "+", "Ax": "|"), but that's more work. You can use the get() method of the dictionary to automatically fill in one set of those however (ie default to returning a pipe or hyphen).

sudoku="
0 0 3 0 2 0 6 0 0
9 0 0 3 0 5 0 0 1
0 0 1 8 0 6 4 0 0
0 0 8 1 0 2 9 0 0
7 0 0 0 0 0 0 0 8
0 0 6 7 0 8 2 0 0
0 0 2 6 0 9 5 0 0
8 0 0 2 0 3 0 0 9
0 0 5 0 1 0 3 0 0"
wherever spaces are present in the string , you can replace it with a '-'
import re
re.sub(r'\s+', '-', sudoku)
Not what u are looking for? Let me know

This should do the trick:
rows = 'ABCDEFGHIJK'
cols = '123456789'
def display(values):
for r in rows :
if r == "D" or r == "H":
print '------+-------+------'
else:
for c in cols :
if c%3 == 0 and c != 9:
print values[r+c] + "|"
else:
print values[r+c]

Solution for python3:
values = {'A9': '1' , 'D8' : '9', 'A1': '7', ...}
sortedKeys = sorted(values)
for i in range(0, 9):
if i != 0 and i % 3 == 0:
print("- - - + - - - + - - -")
for j in range(0, 9):
if j != 0 and j % 3 == 0:
print("|", end=' ')
key = sortedKeys[i*9 + j]
print(values[key], end=' ')
print()

Related

Replace values in df col - pandas

I'm aiming to replace values in a df column Num. Specifically:
where 1 is located in Num, I want to replace preceding 0's with 1 until the nearest Item is 1 working backwards or backfilling.
where Num == 1, the corresponding row in Item will always be 0.
Also, Num == 0 will always follow Num == 1.
Input and code:
df = pd.DataFrame({
'Item' : [0,1,2,3,4,4,0,1,2,3,1,1,2,3,4,0],
'Num' : [0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0]
})
df['Num'] = np.where((df['Num'] == 1) & (df['Item'].shift() > 1), 1, 0)
Item Num
0 0 0
1 1 0
2 2 0
3 3 0
4 4 0
5 4 1
6 0 0
7 1 0
8 2 0
9 3 0
10 1 0
11 1 0
12 2 0
13 3 0
14 4 1
15 0 0
intended output:
Item Num
0 0 0
1 1 1
2 2 1
3 3 1
4 4 1
5 4 1
6 0 0
7 1 0
8 2 0
9 3 0
10 1 0
11 1 1
12 2 1
13 3 1
14 4 1
15 0 0
First, create groups of the rows according to the two start and end conditions using cumsum. Then we can group by this new column and sum over the Num column. In this way, all groups that contain a 1 in the Num column will get the value 1 while all other groups will get 0.
groups = ((df['Num'].shift() == 1) | (df['Item'] == 1)).cumsum()
df['Num'] = df.groupby(groups)['Num'].transform('sum')
Result:
Item Num
0 0 0
1 1 1
2 2 1
3 3 1
4 4 1
5 4 1
6 0 0
7 1 0
8 2 0
9 3 0
10 1 0
11 1 1
12 2 1
13 3 1
14 4 1
15 0 0
You could try:
for a, b in zip(df[df['Item'] == 0].index, df[df['Num'] == 1].index):
df.loc[(df.loc[a+1:b-1, 'Item'] == 1)[::-1].idxmax():b-1, 'Num'] = 1

Hour Glass in Python

I'm trying to code an hour glass in python with the following format:
Sample Input = 3
Sample Output:
1 0 2 0 3
0 2 0 3 0
0 0 3 0 0
0 2 0 3 0
1 0 2 0 3
My code:
#for input use:
inputString = int(input())
# For uper half
for i in range(1,inputString):
# printing i zeroes at the
# beginning of each row
for j in range(1,i):
print("0",end=" ")
for k in range(i,inputString+1):
print(k,"0",end=" ")
print()
# For lower half
for i in range(inputString , 0, -1):
# printing i spaces at the
# beginning of each row
for j in range(1, i):
print("0", end = " ")
# printing i to rows value
# at the end of each row
for k in range(i, inputString + 1):
print(k,"0",end = " ")
print()
My Output:
1 0 2 0 3 0
0 2 0 3 0
0 0 3 0
0 2 0 3 0
1 0 2 0 3 0
I experimented with the looping parameters but I'm not able to figure it out. But unfortunately i couldn't.
Please provide some inputs.
Here's my take to your problem:
def hourglass(n, pretty_print=True):
all_lines = []
for ii in range(n):
line = np.zeros((n*2-1))
line[[idx for idx in np.arange(ii, n*2-1-ii, 2)]] = np.arange(ii+1, n+1, 1)
all_lines.append(line)
all_lines = all_lines + all_lines[-2::-1]
if pretty_print:
str_lines = [[str(int(val)) for val in line] for line in all_lines]
[print(" ".join(line)) for line in str_lines]
return np.vstack(all_lines)
In the case of n=3:
hourglass(3, pretty_print=True)
which prints:
1 0 2 0 3
0 2 0 3 0
0 0 3 0 0
0 2 0 3 0
1 0 2 0 3
One solution with recursion:
def hourglass(n, n2=1, filler_char='0'):
if n == n2:
print(*'{:{filler}^{width}}'.format(filler_char.join('{}'.format(n)), width=n*2-1, filler=filler_char), sep=' ')
return
print(*'{:{filler}^{width}}'.format(filler_char.join(str(i) for i in range(n2, n+1)), width=n*2-1, filler=filler_char), sep=' ')
hourglass(n, n2+1, filler_char)
print(*'{:{filler}^{width}}'.format(filler_char.join(str(i) for i in range(n2, n+1)), width=n*2-1, filler=filler_char), sep=' ')
hourglass(7)
Prints:
1 0 2 0 3 0 4 0 5 0 6 0 7
0 2 0 3 0 4 0 5 0 6 0 7 0
0 0 3 0 4 0 5 0 6 0 7 0 0
0 0 0 4 0 5 0 6 0 7 0 0 0
0 0 0 0 5 0 6 0 7 0 0 0 0
0 0 0 0 0 6 0 7 0 0 0 0 0
0 0 0 0 0 0 7 0 0 0 0 0 0
0 0 0 0 0 6 0 7 0 0 0 0 0
0 0 0 0 5 0 6 0 7 0 0 0 0
0 0 0 4 0 5 0 6 0 7 0 0 0
0 0 3 0 4 0 5 0 6 0 7 0 0
0 2 0 3 0 4 0 5 0 6 0 7 0
1 0 2 0 3 0 4 0 5 0 6 0 7
With hourglass(7, filler_char=' ') it prints:
1 2 3 4 5 6 7
2 3 4 5 6 7
3 4 5 6 7
4 5 6 7
5 6 7
6 7
7
6 7
5 6 7
4 5 6 7
3 4 5 6 7
2 3 4 5 6 7
1 2 3 4 5 6 7
for k in range(i,inputString+1):
print(k,"0",end=" ")
print()
This section is your problem. Once it prints the final character (the 3 in your case), the loop tacks on another '0' and a whitespace and calls it a day. If you want whitespace instead of zeros this isn't a problem since they are visually indistinguishable, but an absence of any character obviously doesn't look the same as a '0' character. You can verify this by highlighting the sample output from the geeksforgeeks article in your browser; the leading whitespaces are there but the trailing whitespaces don't exist - after the 8 in each row is simply a whitespace then a newline character.

How to Align keys with columns python?

I want to align the keys in pandas to the columns they belong to. I have the code, and the output below, with an example of what I am trying to do.
Code:
df = pd.read_csv('Filename.txt')
df.columns = ['Date','b1','b2','b3']
df = df.set_index('Date')
reversed_df = df.iloc[::-1]
n=5
print('Game')
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
print(reversed_df.drop(df.index[n:-n]),("\n"))
BallOne = pd.get_dummies(reversed_df.b1)
BallTwo = pd.get_dummies(reversed_df.b2)
BallThree = pd.get_dummies(reversed_df.b3)
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
pd.set_option('display.width', None)
print(pd.concat([BallOne, BallTwo, BallThree], keys = ['D3E-B1', 'D3E-B2', 'D3E-B3'], axis=1),("\n"))
Output:
D3E-B1 D3E-B2 D3E-B3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
Date
1984-09-01 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
1984-09-03 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0
I would like the keys to be centered on their column like this:
D3E-B1 D3E-B2 D3E-B3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
Date
1984-09-01 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
1984-09-03 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0
from tabulate import tabulate
import pandas as pd
df = pd.DataFrame({'col_two' : [0.0001, 1e-005 , 1e-006, 1e-007],
'column_3' : ['ABCD', 'ABCD', 'long string', 'ABCD']})
print(tabulate(df, headers='keys', tablefmt='psql'))
+----+-----------+-------------+
| | col_two | column_3 |
|----+-----------+-------------|
| 0 | 0.0001 | ABCD |
| 1 | 1e-05 | ABCD |
| 2 | 1e-06 | long string |
| 3 | 1e-07 | ABCD |
+----+-----------+-------------+
from: Pretty Printing a pandas dataframe

Splitting pandas dataframe based on value

I would like to split pandas dataframe to groups in order to process each group separately. My 'value.csv' file contains the following numbers
num tID y x height width
2 0 0 0 1 16
2 1 1 0 1 16
5 0 1 0 1 16
5 1 0 0 1 8
5 2 0 8 1 8
6 0 0 0 1 16
6 1 1 0 1 8
6 2 1 8 1 8
2 0 0 0 1 16
2 1 1 0 1 16
5 0 1 0 1 16
5 1 0 0 1 8
5 2 0 8 1 8
6 0 0 0 1 16
6 1 1 0 1 8
6 2 1 8 1 8
I would like to split the data based on the starting value of 0 at the tID column like that for the first 4 seperation.
First:
2 0 0 0 1 16
2 1 1 0 1 16
Second:
5 0 1 0 1 16
5 1 0 0 1 8
5 2 0 8 1 8
Third:
6 0 0 0 1 16
6 1 1 0 1 8
6 2 1 8 1 8
Fourth:
2 0 0 0 1 16
2 1 1 0 1 16
For this, I tried to split it using if but no success, any efficient ideas?
import pandas as pd
statQuality = 'value.csv'
df = pd.read_csv(statQuality, names=['num','tID','y','x','height','width'])
df2 = df.copy()
df2.drop(['num'], axis=1, inplace=True)
x = []
for index, row in df2.iterrows():
if row['tID'] == 0:
x = []
x.append(row)
print(x)
else:
x.append(row)
Use:
#create groups by consecutive values
s = df['num'].ne(df['num'].shift()).cumsum()
#create helper count Series for duplicated groups like `2_0`, `2_1`...
g = s.groupby(df['num']).transform(lambda x: x.factorize()[0])
#dictionary of DataFrames
d = {'{}_{}'.format(i,j): v.drop('num', axis=1) for (i, j), v in df.groupby(['num', g])}
print (d)
{'2_0': tID y x height width
0 0 0 0 1 16
1 1 1 0 1 16, '2_1': tID y x height width
8 0 0 0 1 16
9 1 1 0 1 16, '5_0': tID y x height width
2 0 1 0 1 16
3 1 0 0 1 8
4 2 0 8 1 8, '5_1': tID y x height width
10 0 1 0 1 16
11 1 0 0 1 8
12 2 0 8 1 8, '6_0': tID y x height width
5 0 0 0 1 16
6 1 1 0 1 8
7 2 1 8 1 8, '6_1': tID y x height width
13 0 0 0 1 16
14 1 1 0 1 8
15 2 1 8 1 8}

Python - Pandas - create "first fail" column from other column data

I have a data frame that represents fail-data for a series of parts, showing which of 3 tests (A, B, C) pass (0) or fail (1).
A B C
1 0 1 1
2 0 0 0
3 1 0 0
4 0 0 1
5 0 0 0
6 0 1 0
7 1 1 0
8 1 1 1
I'd like to add a final column to the dataframe showing the First Fail (FF) of each part, or a default (P) if no fails.
A B C | FF
1 0 1 1 | B
2 0 0 0 | P
3 1 0 0 | A
4 0 0 1 | C
5 0 0 0 | P
6 0 1 0 | B
7 1 1 0 | A
8 1 1 1 | A
Any easy way to do this pandas? Does it require iterating over each row?
maybe:
>>> df['FF'] = df.dot(df.columns).str.slice(0, 1).replace('', 'P')
>>> df
A B C FF
1 0 1 1 B
2 0 0 0 P
3 1 0 0 A
4 0 0 1 C
5 0 0 0 P
6 0 1 0 B
7 1 1 0 A
8 1 1 1 A
alternatively:
>>> df['FF'] = np.where(df.any(axis=1), df.idxmax(axis=1), 'P')
>>> df
A B C FF
1 0 1 1 B
2 0 0 0 P
3 1 0 0 A
4 0 0 1 C
5 0 0 0 P
6 0 1 0 B
7 1 1 0 A
8 1 1 1 A

Categories

Resources