vimalk78's picture
Add complete Python backend with AI-powered crossword generation
38c016b
raw
history blame
10.2 kB
#!/usr/bin/env python3
"""
Test to identify and fix word boundary issues causing unwanted prefixes/suffixes.
"""
import sys
from pathlib import Path
# Add project root to path
project_root = Path(__file__).parent.parent # Go up from test-integration to backend-py
sys.path.insert(0, str(project_root))
from src.services.crossword_generator_fixed import CrosswordGeneratorFixed
def test_word_boundary_violations():
"""Test for word boundary violations that create unwanted prefixes/suffixes."""
generator = CrosswordGeneratorFixed(vector_service=None)
# Test case 1: Simple word placement with boundary checking
print("🧪 Testing word boundary violations...\n")
# Create a grid and place a word
grid = [["." for _ in range(10)] for _ in range(10)]
# Place "MACHINE" horizontally at row 5, col 2
placed_words = []
# First, place MACHINE
if generator._can_place_word(grid, "MACHINE", 5, 2, "horizontal"):
original_state = generator._place_word(grid, "MACHINE", 5, 2, "horizontal")
placed_words.append({
"word": "MACHINE",
"row": 5,
"col": 2,
"direction": "horizontal",
"number": 1
})
print("✅ Placed MACHINE horizontally")
print_grid_section(grid, 4, 7, 0, 10)
else:
print("❌ Cannot place MACHINE")
return False
# Now try to place a word that might create boundary violations
# Try placing "CAR" vertically intersecting with "A" in MACHINE
test_words = [
("CAR", 3, 4, "vertical"), # Should intersect at 'A' in MACHINE
("ACE", 4, 3, "vertical"), # Should intersect at 'C' in MACHINE
("RIG", 6, 7, "vertical"), # Should intersect at 'I' in MACHINE
]
for word, row, col, direction in test_words:
print(f"\n🔍 Testing placement of '{word}' at ({row}, {col}) {direction}")
if generator._can_place_word(grid, word, row, col, direction):
# Check if this placement would create boundary issues
print(f"✅ Can place '{word}' - checking for boundary violations...")
# Simulate the placement
test_grid = [row[:] for row in grid] # Deep copy
test_original = generator._place_word(test_grid, word, row, col, direction)
print_grid_section(test_grid, 2, 9, 0, 10)
# Check if any unintended words are formed
violations = check_word_boundary_violations(test_grid, word, row, col, direction, placed_words)
if violations:
print(f"❌ Boundary violations detected: {violations}")
else:
print(f"✅ No boundary violations for '{word}'")
# Restore grid
generator._remove_word(test_grid, test_original)
else:
print(f"❌ Cannot place '{word}' at ({row}, {col}) {direction}")
print("\n" + "="*50)
return True
def print_grid_section(grid, start_row, end_row, start_col, end_col):
"""Print a section of the grid for visualization."""
print("Grid section:")
for r in range(start_row, min(end_row, len(grid))):
row_str = ""
for c in range(start_col, min(end_col, len(grid[0]))):
if grid[r][c] == ".":
row_str += ". "
else:
row_str += f"{grid[r][c]} "
print(f"Row {r:2d}: {row_str}")
print()
def check_word_boundary_violations(grid, new_word, row, col, direction, existing_words):
"""Check if placing a word creates unintended word extensions."""
violations = []
# Check the immediate boundaries of the new word
if direction == "horizontal":
# Check before the word
if col > 0 and grid[row][col - 1] != ".":
violations.append(f"Unwanted prefix: letter '{grid[row][col - 1]}' before '{new_word}'")
# Check after the word
if col + len(new_word) < len(grid[0]) and grid[row][col + len(new_word)] != ".":
violations.append(f"Unwanted suffix: letter '{grid[row][col + len(new_word)]}' after '{new_word}'")
# Check perpendicular extensions at each letter
for i, letter in enumerate(new_word):
letter_col = col + i
# Check above and below each letter for unintended words
above_letters = []
below_letters = []
# Collect letters above
r = row - 1
while r >= 0 and grid[r][letter_col] != ".":
above_letters.insert(0, grid[r][letter_col])
r -= 1
# Collect letters below
r = row + 1
while r < len(grid) and grid[r][letter_col] != ".":
below_letters.append(grid[r][letter_col])
r += 1
# Check if this forms an unintended word
if above_letters or below_letters:
full_vertical_word = "".join(above_letters) + letter + "".join(below_letters)
if len(full_vertical_word) > 1:
# Check if this is an intended word from existing placements
intended = False
for existing in existing_words:
if (existing["direction"] == "vertical" and
existing["col"] == letter_col and
existing["word"] == full_vertical_word):
intended = True
break
if not intended and len(full_vertical_word) > 1:
violations.append(f"Unintended vertical word '{full_vertical_word}' at column {letter_col}")
else: # vertical
# Check before the word (above)
if row > 0 and grid[row - 1][col] != ".":
violations.append(f"Unwanted prefix: letter '{grid[row - 1][col]}' above '{new_word}'")
# Check after the word (below)
if row + len(new_word) < len(grid) and grid[row + len(new_word)][col] != ".":
violations.append(f"Unwanted suffix: letter '{grid[row + len(new_word)][col]}' below '{new_word}'")
# Check perpendicular extensions at each letter
for i, letter in enumerate(new_word):
letter_row = row + i
# Collect letters to the left and right
left_letters = []
right_letters = []
# Collect letters to the left
c = col - 1
while c >= 0 and grid[letter_row][c] != ".":
left_letters.insert(0, grid[letter_row][c])
c -= 1
# Collect letters to the right
c = col + 1
while c < len(grid[0]) and grid[letter_row][c] != ".":
right_letters.append(grid[letter_row][c])
c += 1
# Check if this forms an unintended word
if left_letters or right_letters:
full_horizontal_word = "".join(left_letters) + letter + "".join(right_letters)
if len(full_horizontal_word) > 1:
# Check if this is an intended word from existing placements
intended = False
for existing in existing_words:
if (existing["direction"] == "horizontal" and
existing["row"] == letter_row and
existing["word"] == full_horizontal_word):
intended = True
break
if not intended and len(full_horizontal_word) > 1:
violations.append(f"Unintended horizontal word '{full_horizontal_word}' at row {letter_row}")
return violations
def test_enhanced_boundary_checking():
"""Test enhanced boundary checking logic."""
print("🧪 Testing enhanced boundary checking logic...\n")
generator = CrosswordGeneratorFixed(vector_service=None)
# Test problematic scenario from the images
# Create a scenario where MACHINE might get extended to MACHINERY
grid = [["." for _ in range(12)] for _ in range(12)]
# Place MACHINE first
generator._place_word(grid, "MACHINE", 5, 2, "horizontal")
placed_words = [{
"word": "MACHINE", "row": 5, "col": 2, "direction": "horizontal", "number": 1
}]
print("Initial grid with MACHINE:")
print_grid_section(grid, 4, 7, 0, 12)
# Now try to place words that might create the "RY" suffix issue
# Place "Y" somewhere that might extend MACHINE
problem_placements = [
("RYOT", 5, 9, "horizontal"), # This would make MACHINE -> MACHINERYOT
("CAR", 3, 8, "vertical"), # This might create unwanted extensions
]
for word, row, col, direction in problem_placements:
print(f"\n🔍 Testing problematic placement: '{word}' at ({row}, {col}) {direction}")
# Check current can_place_word logic
can_place = generator._can_place_word(grid, word, row, col, direction)
print(f"Current _can_place_word result: {can_place}")
if can_place:
# Show what would happen
test_grid = [row[:] for row in grid]
generator._place_word(test_grid, word, row, col, direction)
print("Result grid:")
print_grid_section(test_grid, 3, 8, 0, 12)
# Check for violations manually
violations = check_word_boundary_violations(test_grid, word, row, col, direction, placed_words)
if violations:
print(f"❌ This placement creates violations: {violations}")
else:
print("✅ No violations detected")
if __name__ == "__main__":
print("🔍 Testing Word Boundary Issues\n")
test_word_boundary_violations()
print("\n" + "="*60 + "\n")
test_enhanced_boundary_checking()
print("\n🎯 Analysis complete. Check output for boundary violation patterns.")