AI/Unit 4/crossword/Scavotto_z_U4_L4.py

279 lines
11 KiB
Python

import sys; args = sys.argv[1:] #gets rid of the .py from the list, not needed to look at
import re
BLOCKCHAR = "#" # blocked square (black square)
OPENCHAR = "-" # open square (not decided yet)
PROTECTEDCHAR = "~" #protected
def initialize(height, width, words ,numBlocks):
xword = OPENCHAR * (int(height) * int(width))
for word in words:
startingIndex = int(int(word[1]) * width + int(word[2]))
for letter in word[3]:
xword = xword[:startingIndex] + letter + xword[startingIndex + 1:]
if letter == BLOCKCHAR:
numBlocks -= 1
if word[0] == "V":
startingIndex += int(width)
else:
startingIndex += 1
return xword, numBlocks
def initialProtSymmetry(board):
length = len(board)
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ#"
for x in range(length):
temp = x + 1
if board[x] != OPENCHAR and board[x] != PROTECTEDCHAR and board[x] in alphabet:
indexToReplace = length - temp + 1
if board[indexToReplace-1] not in alphabet:
board = board[:indexToReplace -1] + PROTECTEDCHAR + board[indexToReplace:]
if length % 2 != 0:
indexToReplace = (length // 2) + 1
board = board[:indexToReplace -1] + PROTECTEDCHAR + board[indexToReplace:]
return board
def horizontalProt(board, height, width):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for y in range(height):
letterCount = 0
#for x in range(width):
# if board[(y * height) + x] in alphabet:
# letterCount += 1
# else:
# break
#if letterCount < 3 and letterCount > 0:
# for x in range(3):
# if board[(y * height) + x] == OPENCHAR:
# board = board[:(y * height) + x] + PROTECTEDCHAR + board[(y * height) + x + 1:]
for x in range(width):
#print(y*width+x,board[y*width+x])
if board[(y * width) + x] in alphabet or (board[(y*width)+x] == PROTECTEDCHAR and board[(y*width)+x-1] != PROTECTEDCHAR):
letterCount += 1
else:
if letterCount < 3 and letterCount > 0 and x+1 < width:
for z in range(3-letterCount):
if board[(y * width) + x + z] == OPENCHAR:
board = board[:(y * width) + x + z] + PROTECTEDCHAR + board[(y * width) + x + z + 1:]
letterCount = 0
return board
def verticalProt(board, height, width):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for x in range(width):
letterCount = 0
for y in range(height):
if board[(y * height) + x] in alphabet:
letterCount += 1
else:
break
if letterCount < 3 and letterCount > 0:
for y in range(3):
if board[(y * height) + x] == OPENCHAR:
board = board[:(y * height) + x] + PROTECTEDCHAR + board[(y * height) + x + 1:]
return board
def symmetricalProt(board):
length = len(board)
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ#"
for x in range(length):
temp = x + 1
if board[x] == PROTECTEDCHAR and (board[length - temp] not in alphabet):
indexToReplace = length - temp + 1
board = board[:indexToReplace -1] + PROTECTEDCHAR + board[indexToReplace:]
return board
def addBlocks(board, height, width, numBlocks):
pos_list = [x for x in range(len(board)) if board[x] == OPENCHAR and board[len(board)-x-1] == OPENCHAR]
return recursiveBacktrack(board,height,width,numBlocks, pos_list)
def recursiveBacktrack(board,height,width,numBlocks, pos_list):
if len(pos_list) == 0 or numBlocks == 0: return board
for option in pos_list:
pos_list.remove(option)
if isValid(board,option,height,width):
newBoard = board[:option] + BLOCKCHAR + board[option+1:]
newBoard = newBoard[:len(board)-option-1] + BLOCKCHAR + newBoard[len(board)-option:height*width]
result = recursiveBacktrack(newBoard,height,width,numBlocks-2, pos_list)
if result!= None:
return result
board = board[:option] + OPENCHAR + board[option+1:]
board = board[:len(board)-option-1] + OPENCHAR + board[len(board)-option:]
pos_list.insert(0, option)
numBlocks += 2
return None
def transpose(board, newWidth):
return "".join([board[col:newWidth] for col in range(newWidth)])
def isValid(board,index,height,width):
#checks if block can go there
#ALSO KEEP IN MIND IT HAS TO BE SYMMETRIC
if board[index] != OPENCHAR:
return False
tempBoard = board[:index] + BLOCKCHAR + board[index+1:]
illegalRegex = "[{}](.?({}|{})|({}|{}).?)[{}]".format(BLOCKCHAR, PROTECTEDCHAR,OPENCHAR, PROTECTEDCHAR,OPENCHAR, BLOCKCHAR)
if re.search(illegalRegex, tempBoard) != None or re.search(illegalRegex, transpose(tempBoard, height)) != None:
return False
else:
if board[len(tempBoard)-index-1] != OPENCHAR:
return False
tempBoard = tempBoard[:len(tempBoard)-index-1] + BLOCKCHAR + tempBoard[len(tempBoard)-index:]
if re.search(illegalRegex, tempBoard) != None or re.search(illegalRegex, transpose(tempBoard, height)) != None:
return False
return True
def selectSpot(board,blockOptions,height,width):
for option in blockOptions:
if isValid(board,option,height,width):
return option
return -1
def subLettersForProctected(board):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for index in range(len(board)):
if board[index] in alphabet:
board = board[:index] + PROTECTEDCHAR + board[index+1:]
return board
def display(board, height, width):
startInd = 0
for y in range(height):
print(board[startInd:startInd + width])
startInd = startInd + width
def processInput(args):
dimmMatch = r"^(\d+)x(\d+)$"
blockMatch = r"^\d+$"
wordMatch = r"^(H|V)(\d+)x(\d+)(.+)$"
height, width = 0, 0
numBlocks = 0
prePlacedWords = []
for input in args:
if re.match(dimmMatch, input) != None:
indexOfX = input.index("x")
height, width = int(input[:indexOfX]), int(input[indexOfX + 1:])
args.remove(input)
break
for input in args:
if re.match(blockMatch, input) != None:
numBlocks = int(input)
args.remove(input)
break
unprocessWords = []
for input in args:
if re.match(wordMatch, input, re.I) != None:
unprocessWords.append(input)
for word in unprocessWords:
args.remove(word)
orient = word[0].upper()
word = word[1:]
digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
if "x" in word:
indexOfX = word.index("x")
else:
indexOfX = word.index("X")
finalIndex = indexOfX + 1
row = word[:indexOfX]
while word[finalIndex] in digits:
finalIndex += 1
col = word[indexOfX + 1:finalIndex]
restOfWord = word[finalIndex:]
prePlacedWords.append((orient, row, col, restOfWord.upper()))
if len(args) > 0:
file = args[0]
return file,height, width, numBlocks, prePlacedWords
def removeOuter(board,height,width):
toReturn = ""
for i in range(len(board)):
if (i > width) and ((i+1) % width != 0) and (i % width != 0) and (height*width-width > i):
toReturn += board[i]
return toReturn
def finalize(xword, xw):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
toReturn = ""
for i in range(len(xword)):
if xword[i] in alphabet or xword[i] == BLOCKCHAR:
toReturn += xword[i]
elif xword[i] == PROTECTEDCHAR:
toReturn += OPENCHAR
elif xw[i] == BLOCKCHAR:
toReturn += BLOCKCHAR
else:
toReturn += OPENCHAR
return toReturn
def inputtedBlocksSym(board, numBlocks):
length = len(board)
for i in range(length):
if board[i] == BLOCKCHAR and board[len(board)-i-1] != BLOCKCHAR:
temp = i + 1
indexToReplace = length - temp + 1
board = board[:indexToReplace -1] + BLOCKCHAR + board[indexToReplace:]
numBlocks -=1
return board, numBlocks
def main():
#USE ONLY THE BELOW LINE IN VSCODE, IF USING JGRASP COMMENT THE BELOW LINE!!!!!!!!!!!!!!!!!!!
#COMMENT BELOW LINE OUT WHEN SUBMITTING!!!!!!!!!!!
#GOOD RUNS:
#sys.argv = ['Scavotto_z_U4_L4.py',"scrabble.txt","3x3","9"]
#sys.argv = ['Scavotto_z_U4_L4.py', "7x7", "6", "scrabble.txt", "v0x0come", "v0x1here", "h0x2ers"]
#sys.argv = ['Scavotto_z_U4_L4.py', "9x13", "18", "xwords.txt", "V0x1Who"]
#sys.argv = ['Scavotto_z_U4_L4.py',"9x9", "14", "xwords.txt", "V0x4con", "V6x4rum"]
#NEED FIX
#sys.argv = ['Scavotto_z_U4_L4.py',"15x15", "32", "dct20k.txt", "H0x0Mute", "V0x0mule", "V10x13Risen", "H7x5#", "V3x4#", "H6x7#", "V11x3#"]
#sys.argv = ['Scavotto_z_U4_L4.py', "10x14", "32", "dct20k.txt", "V6x0#", "V9x3#", "H3x10#", "V0x6Indulgence"]
#13x13 32 dct20k.txt H1x4#Toe# H9x2# V3x6# H10x0Scintillating V0x5stirrup H4x2##Ordained V0x1Pits V0x12Ffi V5x0orb
#13x13 32 dct20k.txt V2x4# V1x9# V3x2# h8x2#moo# v5x5#two# h6x4#ten# v3x7#own# h4x6#orb# H12x4Vlan
#13x13 25 dct20k.txt H6x4no#on v5x5rot v0x0ankles h0x4Trot H0x9Calf V0x12foot
#9x22 36 dct20k.txt h4x8e# h3x5s# h2x5# v2x0pan V5x1#w V8x18c
#args = sys.argv #gets the sys args
#args = args[1:]
#COMMENT ALL ABOVE TO SUBMIT
filetext,height, width, numBlocks, words = processInput(args) #processes the inputs
if numBlocks == height*width:
xword = BLOCKCHAR * numBlocks
display(xword, height,width)
else:
xword, numBlocks = initialize(height, width, words, numBlocks)
display(xword, height, width)
if numBlocks != 0:
print("\nMaking Any Inputted Blocks Symmetrical")
xword, numBlocks = inputtedBlocksSym(xword, numBlocks)
display(xword, height, width)
print("\nAdding Symmetrical Protected Characters")
xword = initialProtSymmetry(xword)
display(xword, height, width)
print("\nHorizontal Protection")
xword = horizontalProt(xword, height, width)
display(xword, height, width)
print("\nVertical Protection")
xword = verticalProt(xword, height, width)
display(xword, height, width)
print("\nMaking Protection Symmetric")
xword = symmetricalProt(xword)
display(xword, height, width)
xw = BLOCKCHAR*(width+3)
xw +=(BLOCKCHAR*2).join([xword[p:p+width] for p in range(0,len(xword),width)])
xw += BLOCKCHAR*(width+3)
print("\nTurning into xw")
xwHeight = height+2
xwWidth = width+2
display(xw,xwHeight,xwWidth)
print("\nSubbing Letters")
subbedXW = subLettersForProctected(xw)
display(subbedXW, xwHeight, xwWidth)
print("\nAdding Blocks")
xw = addBlocks(subbedXW, xwHeight, xwWidth, numBlocks)
display(xw,xwHeight,xwWidth)
print("\nRemoving Outer Border")
xw = removeOuter(xw, xwHeight,xwWidth)
display(xw, height, width)
print("\nPutting in Letters and Replacing Protected With Open\n")
xword = finalize(xword, xw)
print(xword)
print("\nThe Displayed Board:")
display(xword, height, width)
if __name__ == '__main__': main()