I am trying to make a simple text editor using python. I am now trying to make a find function. This is what I've got:
def Find():
text = textArea.get('1.0', END+'-1c').lower()
input = simpledialog.askstring("Find", "Enter text to find...").lower()
startindex = []
endindex = []
lines = 0
if input in text:
text = textArea.get('1.0', END+'-1c').lower().splitlines()
for var in text:
character = text[lines].index(input)
start = str(lines + 1) + '.' + str(character)
startindex.append(start)
end = str(lines + 1) + '.' + str(character + int(len(input)))
endindex.append(end)
textArea.tag_add('select', startindex[lines], endindex[lines])
lines += 1
textArea.tag_config('select', background = 'green')
This will succesfully highlight words that match the users input with a green background. But the problem is, that it only highlights the first match every line, as you can see here.
I want it to highlight all matches.
Full code here: https://pastebin.com/BkuXN5pk
Recommend using the text widget's built-in search capability. Shown using python3.
from tkinter import *
root = Tk()
textArea = Text(root)
textArea.grid()
textArea.tag_config('select', background = 'green')
f = open('mouse.py', 'r')
content = f.read()
f.close()
textArea.insert(END, content)
def Find(input):
start = 1.0
length = len(input)
while 1:
pos = textArea.search(input, start, END)
if not pos:
break
end_tag = pos + '+' + str(length) + 'c'
textArea.tag_add('select', pos, end_tag)
start = pos + '+1c'
Find('display')
root.mainloop()
Related
Does anybody know how to create/update a table with the docx library in a word document at a specific location.
So e.g. after a paragraph with text 'test1'?
The idea is to check if paragraph exists in the document, overwrite the existsing table underneath if not create a new paragraph and underneath at a certain location (at certain header level).
I managed to add a paragraph after a specific paragraph but it does not seem to work with tables in the same way.
I can not seem to find a link between the paragraph objects and creating a table object underneath that paragraph object or identifying the existing table object based on the paragraph.
A bit of context on the code, the code is first reading xaml files and writing this data in a word document. The first time the code is run it will create all subheadings and text/tables. With a second run the code will be updating the text/table values as the subheadings already exist.
e.g.
template:
02_BusinessProcess
00_Dispatcher
01_Initialization
after first run:
02_BusinessProcess
1.1 Xamlfilename
Text
Table
00_Dispatcher
2.1 Xamlfilenam
Text
01_Initialization
after second run:
02_BusinessProcess
1.1 Xamlfilename
Updated Text
Updated Table
00_Dispatcher
2.1 Xamlfilenam
Updated Text
01_Initialization
I want to add in the tables between these lines(newly created paragraphs).
paragraph1 = insert_paragraph_after(paragraph, xaml_obt.xamlfilename, style=document.styles['Heading 3'])
paragraph_annseq = insert_paragraph_after(paragraph1, xaml_obt.ann_seq, style=document.styles['No Spacing'])
paragraph_var = insert_paragraph_after(paragraph_annseq, "Variables - " + xaml_obt.xamlfilename,style=document.styles['Heading 4'])
paragraph_in_arg = insert_paragraph_after(paragraph_var, "In_Agruments - " + xaml_obt.xamlfilename, style=document.styles['Heading 4'])
paragraph_io_arg = insert_paragraph_after(paragraph_in_arg, "In_Out_Agruments - " + xaml_obt.xamlfilename, style=document.styles['Heading 4'])
insert_paragraph_after(paragraph_io_arg, "Out_Agruments - " + xaml_obt.xamlfilename, style=document.styles['Heading 4'])
Or update the table in this spot if the paragraph exists in the document:
if paragraph.style.name.startswith('Heading'):
if paragraph.text == xaml_obt.xamlfilename:
new_para = document.paragraphs[i + 1]
new_para.text = xaml_obt.ann_seq + "\n\n"
style = document.styles['No Spacing']
new_para.style = style
new_para.alignment = WD_ALIGN_PARAGRAPH.LEFT
Here is the complete code:
from tkinter import Tk, filedialog
import os
import json
from xml.etree import ElementTree as ET
import docx
from docx.oxml.xmlchemy import OxmlElement
from docx.text.paragraph import Paragraph
from docx.enum.text import WD_ALIGN_PARAGRAPH
import time
import win32com.client
import pandas as pd
class xamlinfo(object):
def __init__(self, name: object) -> object:
self.aut_block = str
self.xamlfilepath = str
self.xamlfilename = str
self.xaml_read = None
self.toplevelnaming = str
self.ann_seq = str
self.in_arguments = pd.DataFrame(columns=['Name', 'Type', 'Annotation'])
self.out_arguments = pd.DataFrame(columns=['Name', 'Type', 'Annotation'])
self.io_agruments = pd.DataFrame(columns=['Name', 'Type', 'Annotation'])
self.variables = pd.DataFrame(columns=['Name', 'Annotation'])
def selectfolder():
root = Tk() # pointing root to Tk() to use it as Tk() in program.
root.withdraw()
root.attributes('-topmost', True)
open_file = filedialog.askdirectory()
open_file = os.path.normpath(open_file)
print("Following filepath selected: ",open_file)
return open_file
def assignxamlobjects(listxamls, path):
if os.path.exists(path):
for root,dirs,files in os.walk(path):
for file in files:
xaml_obt = xamlinfo(os.path.basename(file))
xaml_obt.aut_block = os.path.basename(path)
xaml_obt.xamlfilename = file
xaml_obt.xamlfilepath = os.path.join(root,file)
tree = ET.parse(xaml_obt.xamlfilepath)
treeroot = tree.getroot()
xaml_obt.xaml_read = treeroot
top_sequence = treeroot.find(".//{*}Sequence")
xaml_obt.toplevelnaming = top_sequence.attrib["DisplayName"]
annotation = ""
annotationelements = [x for x in top_sequence.attrib if "annotationtext" in x.lower()]
if (len(annotationelements) > 0):
annotation = top_sequence.attrib[annotationelements[0]]
xaml_obt.ann_seq = annotation
listofelements = treeroot.findall(".//{*}Property")
for element in listofelements:
if "InArgument" in element.attrib["Type"]:
annotation = ""
annotationelements = [x for x in element.attrib if "annotationtext" in x.lower()]
if (len(annotationelements) > 0):
annotation = element.attrib[annotationelements[0]]
xaml_obt.in_arguments = xaml_obt.in_arguments.append({0:str(element.attrib["Name"]), 1:str(element.attrib["Type"]).replace("InArgument",""),2: annotation})
if "InOutArgument" in element.attrib["Type"]:
annotation = ""
annotationelements = [x for x in element.attrib if "annotationtext" in x.lower()]
if (len(annotationelements) > 0):
annotation = element.attrib[annotationelements[0]]
xaml_obt.io_agruments = xaml_obt.io_agruments.append({0:str(element.attrib["Name"]), 1:str(element.attrib["Type"]).replace("InOutArgument",""),2: annotation})
if "OutArgument" in element.attrib["Type"]:
annotation = ""
annotationelements = [x for x in element.attrib if "annotationtext" in x.lower()]
if (len(annotationelements) > 0):
annotation = element.attrib[annotationelements[0]]
xaml_obt.out_arguments = xaml_obt.out_arguments.append({0:str(element.attrib["Name"]), 1:str(element.attrib["Type"]).replace("OutArgument",""),2: annotation})
listofelements = treeroot.findall(".//{*}Variable")
for element in listofelements:
annotation = ""
annotationelements = [x for x in element.attrib if "annotationtext" in x.lower()]
if (len(annotationelements) > 0):
annotation = element.attrib[annotationelements[0]]
xaml_obt.variables = xaml_obt.variables.append({0:str(element.attrib["Name"]),1:annotation})
listxamls.append(xaml_obt)
else:
print("The following path does not exists, please amend your project structure: "+path)
return listxamls
def getworkflowinfo(openfile):
jsonpath = os.path.join(openfile,"project.json")
procestrans_path = os.path.join(openfile,"process","02_BusinessProcess")
dispatcher_path = os.path.join(openfile,"process","00_Dispatcher")
init_path = os.path.join(openfile,"process","01_Initialization")
process_path = os.path.join(openfile,"Process")
listxamls = []
listxamls = assignxamlobjects(listxamls, path=procestrans_path)
listxamls = assignxamlobjects(listxamls, path=dispatcher_path)
listxamls = assignxamlobjects(listxamls, path=init_path)
listxamls = assignxamlobjects(listxamls, path=process_path)
with open(jsonpath) as f:
uipathjson = json.load(f)
return uipathjson, listxamls
def insert_paragraph_after(paragraph, text, style):
new_p = OxmlElement('w:p')
paragraph._p.addnext(new_p)
new_para = Paragraph(new_p, paragraph._parent)
if text:
new_para.add_run(text)
if style is not None:
new_para.style = style
paragraph1 = new_para
return paragraph1
def fillxamldata(document, listofxamls):
print("Starting to update workflow information.")
for xaml_obt in listofxamls:
paraexists = False
for paragraph in document.paragraphs:
if paragraph.text == xaml_obt.xamlfilename:
paraexists = True
if paraexists is True:
for i, paragraph in enumerate(document.paragraphs):
# Check if the paragraph is a heading
if paragraph.style.name.startswith('Heading'):
if paragraph.text == xaml_obt.xamlfilename:
new_para = document.paragraphs[i + 1]
new_para.text = xaml_obt.ann_seq + "\n\n"
style = document.styles['No Spacing']
new_para.style = style
new_para.alignment = WD_ALIGN_PARAGRAPH.LEFT
else:
for paragraph in document.paragraphs:
# Check if the paragraph is a heading
if paragraph.style.name.startswith('Heading'):
if paragraph.text == xaml_obt.aut_block:
paragraph1 = insert_paragraph_after(paragraph, xaml_obt.xamlfilename, style=document.styles['Heading 3'])
paragraph_annseq = insert_paragraph_after(paragraph1, xaml_obt.ann_seq, style=document.styles['No Spacing'])
paragraph_var = insert_paragraph_after(paragraph_annseq, "Variables - " + xaml_obt.xamlfilename,style=document.styles['Heading 4'])
paragraph_in_arg = insert_paragraph_after(paragraph_var, "In_Agruments - " + xaml_obt.xamlfilename, style=document.styles['Heading 4'])
paragraph_io_arg = insert_paragraph_after(paragraph_in_arg, "In_Out_Agruments - " + xaml_obt.xamlfilename, style=document.styles['Heading 4'])
insert_paragraph_after(paragraph_io_arg, "Out_Agruments - " + xaml_obt.xamlfilename, style=document.styles['Heading 4'])
print("Workflow information updated successfully.\n")
return
def filldependencies(document, jsonUI):
print("Starting to fill dependencies.")
dict_depend = jsonUI['dependencies']
text = ""
for i in dict_depend:
text = text + i+": "+ dict_depend[i]+"\n"
for i, paragraph in enumerate(document.paragraphs): # Loop through all the paragraphs in the Word file
if paragraph.style.name.startswith('Heading'): # Check if the paragraph is a heading
if 'dependencies' == paragraph.text.lower():
new_para = document.paragraphs[i+1]
new_para.text = text
style = document.styles['No Spacing']
new_para.style = style
new_para.alignment = WD_ALIGN_PARAGRAPH.LEFT
print("Dependencies updated successfully.\n")
return
def fillgeneralinfo(document, jsonUI):
print("Starting to fill process info.")
text = ("Process name: "+"\t\t\t"+ jsonUI['name'] + "\n" +
"Process description:"+"\t\t" + jsonUI['description'] +"\n" +
"UIpath Studio version:"+"\t\t"+ jsonUI['studioVersion'] + "\n" +
"Project version:"+"\t\t\t" + jsonUI['projectVersion'] + "\n")
for i, paragraph in enumerate(document.paragraphs): # Loop through all the paragraphs in the Word file
if paragraph.style.name.startswith('Heading'): # Check if the paragraph is a heading
if 'general info' == paragraph.text.lower():
new_para = document.paragraphs[i+1]
new_para.text = text
style = document.styles['No Spacing']
new_para.style = style
new_para.alignment = WD_ALIGN_PARAGRAPH.LEFT
print("Process info successfully updated.\n")
return
def fillworddata(path, listofxamls):
print("You seleceted the following SDD file: "+path+"\n")
document = docx.Document(path)
with open(path, "w") as doc:
fillxamldata(document, listofxamls)
filldependencies(document, jsonUI)
fillgeneralinfo(document, jsonUI)
document.save(path)
return
def startmessage():
print("###############################################################\n"+
" SDD_AUT \n"+
"###############################################################\n")
starttimer = time.time()
startmessage()
openfile = selectfolder()
jsonUI, listxamls = getworkflowinfo(openfile)
correct_proc = input("The information for process | " + jsonUI['name'] + " | has been read.\n"+
"Do you want to continue? (y/n)\n")
if correct_proc.lower() == 'y':
sdd_doc = filedialog.askopenfilename(title='Select a file')
fillworddata(path=sdd_doc, listofxamls=listxamls)
print("Process has been executed successfully!")
else:
print("The process has been terminated as the incorrect project was selected.")
endtimer = time.time()
duration = endtimer - starttimer
print("Process took: " + str(duration))
I'm looking to put black backgrounds on text using PIL in Python that automatically adjust to the width and height of the text.
Currently, I have code that constructs the text at equal distances from each other. How would I now put a black background on each line?
font_fname = r'user\arial.ttf'
font_size = 50
font = ImageFont.truetype(font_fname, font_size)
text = 'This is a picture of a dolphin having fun'
text_items = wrap(text, 25)
for i in range(4):
try:
number = str(i)
item = text_items[i]
exec(str("line" + number + ' = ''"""' + item + '"""'))
except:
pass
spacing = spacing + 30
par_spacing = 40
for i in range(len(opening_par_items) + 1):
line_number = str(i)
try:
exec("draw.text((130, " + str(spacing) + "), line_" + line_number + ", font=font , fill='rgb(255, 255, 255)')")
spacing = spacing + par_spacing
except:
pass
I'm writing a program that can parse math papers written in .tex files. Here are what I want:
The program is supposed to detect the beginning, the end, sections, subsections, subsubsections, theorems, lemmas, definitions, conjectures, corollaries, proposition, exercises, notations and examples in a math paper and ignore the rest of the contents to produce a summary.
In the beginning the program is supposed to retain all characters until reaching token MT. In this case the lever should preserve the token and enter ig mode. Then it should ignore all characters unless it detects a theorem/lemma/definition/conjecture/corollary/example/exercise/notation/proposition, in which case it temporarily enters the INITIAL mode and retain it or a (sub/subsub)section in which case it should temporarily enter the sec mode.
\newtheorem{<name>}{<heading>}[<counter>] and \newtheorem{<name>}[<counter>]{<heading>} are detected as TH ptext THCC ptext THC ptext and TH ptext THCS ptext THSC ptext THC respectively where ptext is a bunch of TEXT.
import sys
import logging
from ply.lex import TOKEN
if sys.version_info[0] >= 3:
raw_input = input
tokens = (
'BT', 'BL', 'BD', 'BCONJ', 'BCOR', 'BE', 'ET', 'EL', 'ED', 'ECONJ', 'ECOR', 'EE', 'SEC', 'SSEC', 'SSSEC', 'ES', 'TEXT','ITEXT','BIBS','MT','BN','EN','BEXE','EEXE','BP','EP','TH','THCS','THSC','THCC','THC',
)
states = (('ig', 'exclusive'), ('sec', 'exclusive'), ('th', 'exclusive'), ('tht','exclusive'),('thc','exclusive'))
logging.basicConfig(
level = logging.DEBUG,
filename = "lexlog.txt",
filemode = "w",
format = "%(filename)10s:%(lineno)4d:%(message)s"
)
log = logging.getLogger()
th_temp = ''
thn_temp = ''
term_dic = {'Theorem':'','Lemma':'','Corollary':'','Definition':'','Conjecture':'','Example':'','Exercise':'','Notation':'','Proposition':''}
idb_list = ['','','','','','','','','']
ide_list = ['','','','','','','','','']
bb = r'\\begin\{'
eb = r'\\end\{'
ie = r'\}'
def finalize_terms():
global idb_list
global ide_list
if term_dic['Theorem'] != '':
idb_list[0] = bb + term_dic['Theorem'] + ie
ide_list[0] = eb + term_dic['Theorem'] + ie
if term_dic['Lemma'] != '':
idb_list[1] = bb + term_dic['Lemma'] + ie
ide_list[1] = eb + term_dic['Lemma'] + ie
if term_dic['Corollary'] != '':
idb_list[2] = bb + term_dic['Corollary'] + ie
ide_list[2] = eb + term_dic['Corollary'] + ie
if term_dic['Definition'] != '':
idb_list[3] = bb + term_dic['Definition'] + ie
ide_list[3] = eb + term_dic['Definition'] + ie
if term_dic['Conjecture'] != '':
idb_list[4] = bb + term_dic['Conjecture'] + ie
ide_list[4] = eb + term_dic['Conjecture'] + ie
if term_dic['Example'] != '':
idb_list[5] = bb + term_dic['Example'] + ie
ide_list[5] = eb + term_dic['Example'] + ie
if term_dic['Exercise'] != '':
idb_list[6] = bb + term_dic['Exercise'] + ie
ide_list[6] = eb + term_dic['Exercise'] + ie
if term_dic['Notation'] != '':
idb_list[7] = bb + term_dic['Notation'] + ie
ide_list[7] = eb + term_dic['Notation'] + ie
if term_dic['Proposition'] != '':
idb_list[8] = bb + term_dic['Proposition'] + ie
ide_list[8] = eb + term_dic['Proposition'] + ie
print(idb_list)
print(ide_list)
Here are some of the parsing functions:
def t_TH(t):
r'\\newtheorem\{'
t.lexer.begin('th')
return t
def t_th_THCS(t):
r'\}\['
t.lexer.begin('thc')
return t
def t_tht_THC(t):
r'\}'
if term_dic.has_key(thn_temp) == False:
print(f"{thn_temp} is unknown!")
elif len(th_temp) == 0:
print(f"No abbreviation for {thn_temp} is found!")
else:
term_dic[thn_temp] = th_temp
print(f"The abbreviation for {thn_temp} is {th_temp}!")
th_temp = ''
thn_temp = ''
t.lexer.begin('INITIAL')
return t
def t_th_THCC(t):
r'\}\{'
t.lexer.begin('tht')
return t
def t_thc_THSC(t):
r'\]\{'
t.lexer.begin('tht')
return t
#TOKEN(idb_list[0])
def t_ig_BT(t):
t.lexer.begin('INITIAL')
return t
#TOKEN(ide_list[0])
def t_ET(t):
t.lexer.begin('ig')
return t
def t_INITIAL_sec_thc_TEXT(t):
r'[\s\S]'
return t
def t_th_TEXT(t):
r'[\s\S]'
th_temp = th_temp + t.value()
return t
def t_tht_TEXT(t):
r'[\s\S]'
thn_temp = thn_temp + t.value()
return t
def t_ig_ITEXT(t):
r'[\s\S]'
pass
import ply.lex as lex
lex.lex(debug=True, debuglog = log)
Here are the errors:
ERROR: /Users/CatLover/Documents/Python_Beta/TexExtractor/texlexparse.py:154: No regular expression defined for rule 't_ET'
I don't know why the regular expression defined for 't_ET' etc using #TOKEN do not work.
Ply is a parser generator. It takes your parser/lexer description and compiles a parser/lexer from it. You cannot change the description of the language during the parse.
In this particular case, you might be better off writing a streaming ("online") scanner. But if you want to use Ply, then you will be better off not trying to modify the grammar to ignore parts of the input. Just parse the entire input and ignore the parts you're not interested in. You'll probably find that the code is much simpler.
I am making a would you rather game, and I would like to not have character restrictions for the W.Y.R. questions. I have seen many examples here on Stack Overflow and other websites, but they use other modules and methods I don't understand how to use or want to use. So I would rather use
button_text_font = pygame.font.Font(font_location, 20)
red_button_text = button_text_font.render(red_text, True, bg_color)
blue_button_text = button_text_font.render(blue_text, True, bg_color)
I would like to know how to use this method and, for example, somehow input how far the text can go until it wraps to the next line.
Thanks
P.S. If you could, please also include centering text, etc.
This is adapted from some very old code I wrote:
def renderTextCenteredAt(text, font, colour, x, y, screen, allowed_width):
# first, split the text into words
words = text.split()
# now, construct lines out of these words
lines = []
while len(words) > 0:
# get as many words as will fit within allowed_width
line_words = []
while len(words) > 0:
line_words.append(words.pop(0))
fw, fh = font.size(' '.join(line_words + words[:1]))
if fw > allowed_width:
break
# add a line consisting of those words
line = ' '.join(line_words)
lines.append(line)
# now we've split our text into lines that fit into the width, actually
# render them
# we'll render each line below the last, so we need to keep track of
# the culmative height of the lines we've rendered so far
y_offset = 0
for line in lines:
fw, fh = font.size(line)
# (tx, ty) is the top-left of the font surface
tx = x - fw / 2
ty = y + y_offset
font_surface = font.render(line, True, colour)
screen.blit(font_surface, (tx, ty))
y_offset += fh
The basic algorithm is to split the text into words and iteratively build up lines word by word checking the resulting width each time and splitting to a new line when you would exceed the width.
As you can query how wide the rendered text will be, you can figure out where to render it to centre it.
This is messy and there is far more you can do but if you want a specific length of text for say a paragraph...
font = pygame.font.SysFont("Times New Roman, Arial", 20, bold=True)
your_text = "blah blah blah"
txtX, txtY = 125, 500
wraplen = 50
count = 0
my_wrap = textwrap.TextWrapper(width=wraplen)
wrap_list = my_wrap.wrap(text=your_text)
# Draw one line at a time further down the screen
for i in wrap_list:
txtY = txtY + 35
Mtxt = font.render(f"{i}", True, (255, 255, 255))
WIN.blit(Mtxt, (txtX, txtY))
count += 1
# Update All Window and contents
pygame.display.update()
Using the implementation in Pygame Zero, text can be wrapped with the following function.
# Adapted from https://github.com/lordmauve/pgzero/blob/master/pgzero/ptext.py#L81-L143
def wrap_text(text, font, max_width):
texts = text.replace("\t", " ").split("\n")
lines = []
for text in texts:
text = text.rstrip(" ")
if not text:
lines.append("")
continue
# Preserve leading spaces in all cases.
a = len(text) - len(text.lstrip(" "))
# At any time, a is the rightmost known index you can legally split a line. I.e. it's legal
# to add text[:a] to lines, and line is what will be added to lines if
# text is split at a.
a = text.index(" ", a) if " " in text else len(text)
line = text[:a]
while a + 1 < len(text):
# b is the next legal place to break the line, with `bline`` the
# corresponding line to add.
if " " not in text[a + 1:]:
b = len(text)
bline = text
else:
# Lines may be split at any space character that immediately follows a non-space
# character.
b = text.index(" ", a + 1)
while text[b - 1] == " ":
if " " in text[b + 1:]:
b = text.index(" ", b + 1)
else:
b = len(text)
break
bline = text[:b]
bline = text[:b]
if font.size(bline)[0] <= max_width:
a, line = b, bline
else:
lines.append(line)
text = text[a:].lstrip(" ")
a = text.index(" ", 1) if " " in text[1:] else len(text)
line = text[:a]
if text:
lines.append(line)
return lines
Bear in mind that wrapping text requires multiple lines that must be rendered separately. Here's an example of how you could render each line.
def create_text(text, color, pos, size, max_width=None, line_spacing=1):
font = pygame.font.SysFont("monospace", size)
if max_width is not None:
lines = wrap_text(text, font, max_width)
else:
lines = text.replace("\t", " ").split("\n")
line_ys = (
np.arange(len(lines)) - len(lines) / 2 + 0.5
) * 1.25 * font.get_linesize() + pos[1]
# Create the surface and rect that make up each line
text_objects = []
for line, y_pos in zip(lines, line_ys):
text_surface = font.render(line, True, color)
text_rect = text_surface.get_rect(center=(pos[0], y_pos))
text_objects.append((text_surface, text_rect))
return text_objects
# Example case
lines = create_text(
text="Some long text that needs to be wrapped",
color=(255, 255, 255), # White
pos=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2), # Center of the screen
size=16,
max_width=SCREEN_WIDTH,
)
# Render each line
for text_object in lines:
screen.blit(*text_object)
I want to create a word search generator but I'm finding it a little hard. Ive looked online and found this word search generator which works well but i would like to use my own grid from a text file. Is there way I can code this and place my text file instead of random choice letters.
##while True:
## intext=input('Enter file name: ')
##
## if not intext=='grid.txt':
## print("No such file was found! Enter file name.")
## continue
## else:
##
## break
##grid= open(intext,'r')
import string
import random
width = 12
height = 12
def put_word(word,grid):
word = random.choice([word,word[::-1]])
d = random.choice([[1,0],[0,1],[1,1]])
xsize = width if d[0] == 0 else width - len(word)
ysize = height if d[1] == 0 else height - len(word)
x = random.randrange(0,xsize)
y = random.randrange(0,ysize)
print([x,y])
for i in range(0,len(word)):
grid[y + d[1]*i][x + d[0]*i] = word[i]
return grid
grid = [[random.choice(string.ascii_uppercase) for i in range(0,width)] for j in range(0,height)]
for word in ["HELLO", "THERE", "AGAIN"]:
grid = put_word(word, grid)
print("\n".join(map(lambda row: " ".join(row), grid))
in the grid.txt files are:
xmfycxvtljlqbbybkoumjqwbt
caubmeknbeydqmcnzyjpvrank
aqactivexnyvwdvcoshoyaohg
paghzkctudptjdphsztprhttl
sbsnakjwqbouftmgnjqbtlinu
tsewohvobdsduqjiffkyylodo
oukwwefroyamapmlrrpvdolop
cqkfxtlksjvtmtrsbycmqrrri
kfervlqidqaxaoanfqjlmcpjh
yoyywrbpfcjlfbcbbcoecspwl
twbxetyuyufvvmauawjmbwlqh
txokdexmdbtgvhpsvsqtmljdx
dcatenrehteoxqdgeueljtrrn
jarteqvtxejfsqddkbuhcysfq
hpdrowssapxtrxhpdxcdhicon