This is a part of a game TicTacToe. Both of them print a table of Tic Tac Toe, same output, but which one is better in algorithm and code quality? Is there anything can be modify to make it better?
#self.board is a list contains value of this table.
# e.g. an empty board should look like this:
# 0 1 2
# 0 | |
# -----------
# 1 | |
# -----------
# 2 | |
# code 1
printFormat = "\n 0 1 2 \n0 {} | {} | {} \n -----------\n1 {} | {} | {} \n -----------\n2 {} | {} | {} "
print(printFormat.format(*self.board[0],*self.board[1],*self.board[2]))
# code 2
printList = []
txtFormat ="{:} {:^3}"+"|{:^3}"*(self.size-1)
titleFormat = "{:^3} " * self.size
numbers = range(self.size)
line1 = "\n "+titleFormat.format(*numbers)
printList.append(line1)
for i in range(self.size):
contentLine = txtFormat.format(numbers[i],*self.board[i])
printList.append(contentLine)
cutOffLine = " "+"-"*(4*self.size-1)
printList.append(cutOffLine)
printList.pop()
for item in printList:
print(item)
The error I am getting:
invalid string interpolation: `$$', `$'ident or `$'BlockExpr expected
Spark SQL:
val sql =
s"""
|SELECT
| ,CAC.engine
| ,CAC.user_email
| ,CAC.submit_time
| ,CAC.end_time
| ,CAC.duration
| ,CAC.counter_name
| ,CAC.counter_value
| ,CAC.usage_hour
| ,CAC.event_date
|FROM
| xyz.command AS CAC
| INNER JOIN
| (
| SELECT DISTINCT replace(split(get_json_object(metadata_payload, '$.configuration.name'), '_')[1], 'acc', '') AS account_id
| FROM xyz.metadata
| ) AS QCM
| ON QCM.account_id = CAC.account_id
|WHERE
| CAC.event_date BETWEEN '2019-10-01' AND '2019-10-05'
|""".stripMargin
val df = spark.sql(sql)
df.show(10, false)
You added s prefix which means you want the string be interpolated. It means all tokens prefixed with $ will be replaced with the local variable with the same name. From you code it looks like you do not use this feature, so you could just remove s prefix from the string:
val sql =
"""
|SELECT
| ,CAC.engine
| ,CAC.user_email
| ,CAC.submit_time
| ,CAC.end_time
| ,CAC.duration
| ,CAC.counter_name
| ,CAC.counter_value
| ,CAC.usage_hour
| ,CAC.event_date
|FROM
| xyz.command AS CAC
| INNER JOIN
| (
| SELECT DISTINCT replace(split(get_json_object(metadata_payload, '$.configuration.name'), '_')[1], 'acc', '') AS account_id
| FROM xyz.metadata
| ) AS QCM
| ON QCM.account_id = CAC.account_id
|WHERE
| CAC.event_date BETWEEN '2019-10-01' AND '2019-10-05'
|""".stripMargin
Otherwise if you really need the interpolation you have to quote $ sign like this:
val sql =
s"""
|SELECT
| ,CAC.engine
| ,CAC.user_email
| ,CAC.submit_time
| ,CAC.end_time
| ,CAC.duration
| ,CAC.counter_name
| ,CAC.counter_value
| ,CAC.usage_hour
| ,CAC.event_date
|FROM
| xyz.command AS CAC
| INNER JOIN
| (
| SELECT DISTINCT replace(split(get_json_object(metadata_payload, '$$.configuration.name'), '_')[1], 'acc', '') AS account_id
| FROM xyz.metadata
| ) AS QCM
| ON QCM.account_id = CAC.account_id
|WHERE
| CAC.event_date BETWEEN '2019-10-01' AND '2019-10-05'
|""".stripMargin
I have a .txt file as in the example reported below. I would like to convert it into a .csv table, but I'm not having much success.
Mack3 Line Item Journal Time 14:22:33 Date 03.10.2015
Panteni Ledger 1L TGEPIO00/CANTINAOAS Page 20.001
--------------------------------------------------------------------------------------------------------------------------------------------
| Pstng Date|Entry Date|DocumentNo|Itm|Doc..Date |BusA|PK|SG|Sl|Account |User Name |LCurr| Amount in LC|Tx|Assignment |S|
|------------------------------------------------------------------------------------------------------------------------------------------|
| 07.01.2014|07.02.2014|4919005298| 36|07.01.2019| |81| | |60532640 |tARFooWMOND |EUR | 0,85 | |20140107 | |
| 07.01.2014|07.02.2014|4919065298| 29|07.01.2019| |81| | |60532640 |tARFooWMOND |EUR | 2,53 | |20140107 | |
| 07.01.2014|07.02.2014|4919235298| 30|07.01.2019| |81| | |60532640 |tARFooWMOND |EUR | 30,00 | |20140107 | |
| 07.01.2014|07.02.2014|4119005298| 32|07.01.2019| |81| | |60532640 |tARFooWMOND |EUR | 1,00 | |20140107 | |
| 07.01.2014|07.02.2014|9019005298| 34|07.01.2019| |81| | |60532640 |tARFooWMOND |EUR | 11,10 | |20140107 | |
|------------------------------------------------------------------------------------------------------------------------------------------|
The file in question is structure as a report from SAP. Practicing with python and looking in other posts I found this code:
with open('file.txt', 'rb') as f_input:
for line in filter(lambda x: len(x) > 2 and x[0] == '|' and x[1].isalpha(), f_input):
header = [cols.strip() for cols in next(csv.reader(StringIO(line), delimiter='|', skipinitialspace=True))][1:-1]
break
with open('file.txt', 'rb') as f_input, open(str(ii + 1) + 'output.csv', 'wb') as f_output:
csv_output = csv.writer(f_output)
csv_output.writerow(header)
for line in filter(lambda x: len(x) > 2 and x[0] == '|' and x[1] != '-' and not x[1].isalpha(), f_input):
csv_input = csv.reader(StringIO(line), delimiter='|', skipinitialspace=True)
csv_output.writerow(csv_input)
Unfortunately it does not work for my case. In fact it creates empty .csv files and it seems to not read properly the csv_input.
Any possible solution?
Your input file can be treated as CSV once we filter out a few lines, namely the ones that do not start with a pipe symbol '|' followed by a space ' ', which would leave us with this:
| Pstng Date|Entry Date|DocumentNo|Itm|Doc..Date |BusA|PK|SG|Sl|Account |User Name |LCurr| Amount in LC|Tx|Assignment |S|
| 07.01.2014|07.02.2014|4919005298| 36|07.01.2019| |81| | |60532640 |tARFooWMOND |EUR | 0,85 | |20140107 | |
| 07.01.2014|07.02.2014|4919065298| 29|07.01.2019| |81| | |60532640 |tARFooWMOND |EUR | 2,53 | |20140107 | |
| 07.01.2014|07.02.2014|4919235298| 30|07.01.2019| |81| | |60532640 |tARFooWMOND |EUR | 30,00 | |20140107 | |
| 07.01.2014|07.02.2014|4119005298| 32|07.01.2019| |81| | |60532640 |tARFooWMOND |EUR | 1,00 | |20140107 | |
| 07.01.2014|07.02.2014|9019005298| 34|07.01.2019| |81| | |60532640 |tARFooWMOND |EUR | 11,10 | |20140107 | |
Your output is mainly empty because that x[1].isalpha() check is never true on this data. The character in position 1 on each line is always a space, never alphabetic.
It's not necessary to open the input file multiple times, we can read, filter and write to the output in one go:
import csv
ii = 0
with open('file.txt', 'r', encoding='utf8', newline='') as f_input, \
open(str(ii + 1) + 'output.csv', 'w', encoding='utf8', newline='') as f_output:
input_lines = filter(lambda x: len(x) > 2 and x[0] == '|' and x[1] == ' ', f_input)
csv_input = csv.reader(input_lines, delimiter='|')
csv_output = csv.writer(f_output)
for row in csv_input:
csv_output.writerow(col.strip() for col in row[1:-1])
Notes:
You should not use binary mode when reading text files. Use r and w modes, respectively, and explicitly declare the file encoding. Choose the encoding that is the right one for your files.
For work with the csv module, open files with newline='' (which lets the csv module pick the correct line endings)
You can wrap multiple files in the with statements using the \ at the end of the line.
StringIO is completely unnecesary.
I'm not using skipinitialspace=True because some of the columns also have spaces at the end. Therefore I'm calling .strip() manually on each value when writing the row.
The [1:-1] is necessary to get rid of the superfluous empty columns (before the first and after the last | in the input)
Output is as follows
Pstng Date,Entry Date,DocumentNo,Itm,Doc..Date,BusA,PK,SG,Sl,Account,User Name,LCurr,Amount in LC,Tx,Assignment,S
07.01.2014,07.02.2014,4919005298,36,07.01.2019,,81,,,60532640,tARFooWMOND,EUR,"0,85",,20140107,
07.01.2014,07.02.2014,4919065298,29,07.01.2019,,81,,,60532640,tARFooWMOND,EUR,"2,53",,20140107,
07.01.2014,07.02.2014,4919235298,30,07.01.2019,,81,,,60532640,tARFooWMOND,EUR,"30,00",,20140107,
07.01.2014,07.02.2014,4119005298,32,07.01.2019,,81,,,60532640,tARFooWMOND,EUR,"1,00",,20140107,
07.01.2014,07.02.2014,9019005298,34,07.01.2019,,81,,,60532640,tARFooWMOND,EUR,"11,10",,20140107,
Here's a shortened version of my code. Basically, I have a dictionary that stores a list that contains my ascii letter. I am prompting the user for a choice of letters to then be printed out with the special design. The second user input is used to decide how to print the letters. 'h' = horizontal and 'v' = vertical. The vertical section works perfectly. The horizontal does not.
def print_banner(input_string, direction):
'''
Function declares a list of ascii characters, and arranges the characters in order to be printed.
'''
ascii_letter = {'a': [" _______ ",
"( ___ )",
"| ( ) |",
"| (___) |",
"| ___ |",
"| ( ) |",
"| ) ( |",
"|/ \|"]}
# Branch that encompasses the horizontal banner
if direction == "h":
# Letters are 8 lines tall
for i in range(8):
for letter in range(len(input_string)):
# Dict[LetterIndex[ListIndex]][Line]
print(ascii_letter[input_string[letter]][i], end=" ")
print(" ")
# Branch that encompasses the vertical banner
elif direction == "v":
for letter in input_string:
for item in ascii_letter[letter]:
print(item)
def main():
user_input = input("Enter a word to convert it to ascii: ").lower()
user_direction = input("Enter a direction to display: ").lower()
print_banner(user_input, user_direction)
# This is my desired output if input is aa
_______ _______
( ___ ) ( ___ )
| ( ) | | ( ) |
| (___) | | (___) |
| ___ | | ___ |
| ( ) | | ( ) |
| ) ( | | ) ( |
|/ \| |/ \|
#What i get instead is:
_______
_______
( ___ )
( ___ )
| ( ) |
| ( ) |
| (___) |
| (___) |
| ___ |
| ___ |
| ( ) |
| ( ) |
| ) ( |
| ) ( |
|/ \|
|/ \|
You could zip the lines together and then join them:
if direction == "h":
zipped = zip(*(ascii_letter[char] for char in input_string))
for line in zipped:
print(' '.join(line))
Or just with the index:
if direction == "h":
for i in range(8):
for char in input_string:
print(ascii_letter[char][i], end=' ')
print()
Just getting into python, and so I decided to make a hangman game. Works good, but I was wondering if there was any kind of optimizations I could make or ways to clean up the code. Also, if anyone could recommend a project that I could do next that'd be cool.
import sys
import codecs
import random
def printInterface(lst, attempts):
""" Prints user interface which includes:
- hangman drawing
- word updater """
for update in lst:
print (update, end = '')
if attempts == 1:
print ("\n\n\n\n\n\n\n\n\n\n\n\t\t _____________")
elif attempts == 2:
print ("""
|
|
|
|
|
|
|
|
|
______|______""")
elif attempts == 3:
print ("""
______
|
|
|
|
|
|
|
|
|
______|______""")
elif attempts == 4:
print ("""
______
| |
| |
(x_X) |
|
|
|
|
|
|
______|______""")
elif attempts == 5:
print ("""
______
| |
| |
(x_X) |
| |
| |
| |
|
|
|
______|______""")
elif attempts == 6:
print ("""
______
| |
| |
(x_X) |
| |
/| |
| |
|
|
|
______|______""")
elif attempts == 7:
print ("""
______
| |
| |
(x_X) |
| |
/|\ |
| |
|
|
|
______|______""")
elif attempts == 8:
print ("""
______
| |
| |
(x_X) |
| |
/|\ |
| |
/ |
|
|
______|______""")
elif attempts == 9:
print ("""
______
| |
| |
(x_X) |
| |
/|\ |
| |
/ \ |
|
|
______|______""")
def main():
try:
wordlist = codecs.open("words.txt", "r")
except Exception as ex:
print (ex)
print ("\n**Could not open file!**\n")
sys.exit(0)
rand = random.randint(1,5)
i = 0
for word in wordlist:
i+=1
if i == rand:
break
word = word.strip()
wordlist.close()
lst = []
for h in word:
lst.append('_ ')
attempts = 0
printInterface(lst,attempts)
while True:
guess = input("Guess a letter: ").strip()
i = 0
for letters in lst:
if guess not in word:
print ("No '{0}' in the word, try again!".format(guess))
attempts += 1
break
if guess in word[i] and lst[i] == "_ ":
lst[i] = (guess + ' ')
i+=1
printInterface(lst,attempts)
x = lst.count('_ ')
if x == 0:
print ("You win!")
break
elif attempts == 9:
print ("You suck! You iz ded!")
break
if __name__ == '__main__':
while True:
main()
again = input("Would you like to play again? (y/n): ").strip()
if again.lower() == "n":
sys.exit(1)
print ('\n')
I didn't try the code, but here's some random tips:
Try to format your code accordingly to PEP 8 (use i += 1 instead of i+=1). PEP 8 is the standard style guide for Python.
Use
lst = ['_ '] * len(word)
instead of the for-loop.
Use enumerate as in:
for i, word in enumerate(wordlist)
instead of manually keeping track of i in the loop.
The default mode for opening files is 'r', there's no need to specify it. Are you using codecs.open instead of the built-in open in order to get Unicode strings back? Also, try to catch a more specific exception that Exception -- probably IOError.
First idea: ASCII art
The things special to Python are regular expression syntax and range() function, as well as [xxx for yyy in zzz] array filler.
import re
def ascii_art(attempt):
return re.sub(r'\d', '', re.sub('[0{0}].' \
.format(''.join([str(e) for e in range(attempt + 1, 10)])), ' ', """
3_3_3_3_3_3_
4| 2|
4| 2|
4(4x4_4X4) 2|
5| 2|
6/5|7\ 2|
5| 2|
8/ 9\ 2|
2|
2|
1_1_1_1_1_1_1|1_1_1_1_1_1_
"""))
for i in range(1, 10):
print(ascii_art(i))
Second idea: loops
Use enumerate for word reading loop. Use
for attempt in range(1, 10):
# inside main loop
...
print ('you suck!')
as the main loop. Operator break should be used with care and not as replacement for for!
Unless I miss something, the structure of
for letters in lst:
if guess not in word:
...
break
if guess in word[i]:
...
will be more transparent as
if guess not in word:
...
else:
index = word.find (guess)
...
I would use list instead of if .. else statement in printInterface.