Untitled
unknown
plain_text
6 months ago
9.7 kB
6
Indexable
from collections import defaultdict import random import copy def find_slots(grid): """Identify all horizontal and vertical slots in the grid.""" slots = [] rows = len(grid) cols = len(grid[0]) if rows > 0 else 0 # Finding horizontal slots for row in range(rows): start = None for col in range(cols): if grid[row][col] == '-': if start is None: start = col else: if start is not None and col - start > 1: slots.append(("H", row, start, col - start)) start = None if start is not None and cols - start > 1: slots.append(("H", row, start, cols - start)) # Finding vertical slots for col in range(cols): start = None for row in range(rows): if grid[row][col] == '-': if start is None: start = row else: if start is not None and row - start > 1: slots.append(("V", start, col, row - start)) start = None if start is not None and rows - start > 1: slots.append(("V", start, col, rows - start)) return slots def get_intersections(slots): """Find all intersections between slots.""" intersections = defaultdict(list) for i, slot1 in enumerate(slots): dir1, row1, col1, length1 = slot1 for j, slot2 in enumerate(slots): if i >= j: continue dir2, row2, col2, length2 = slot2 if dir1 == "H" and dir2 == "V": if col2 in range(col1, col1 + length1) and row1 in range(row2, row2 + length2): intersections[i].append((j, col2 - col1, row1 - row2)) intersections[j].append((i, row1 - row2, col2 - col1)) elif dir1 == "V" and dir2 == "H": if row2 in range(row1, row1 + length1) and col1 in range(col2, col2 + length2): intersections[i].append((j, row2 - row1, col1 - col2)) intersections[j].append((i, col1 - col2, row2 - row1)) return intersections def can_place_word(grid, word, slot): """Check if a word can be placed in the given slot.""" direction, row, col, length = slot if len(word) != length: return False for i in range(length): if direction == "H": if grid[row][col + i] not in ('-', word[i]): return False elif direction == "V": if grid[row + i][col] not in ('-', word[i]): return False return True def place_word(grid, word, slot): """Place a word in the given slot.""" direction, row, col, length = slot for i in range(length): if direction == "H": grid[row][col + i] = word[i] elif direction == "V": grid[row + i][col] = word[i] def remove_word(grid, slot): """Remove a word from the slot (restore empty cells).""" direction, row, col, length = slot for i in range(length): if direction == "H": grid[row][col + i] = '-' elif direction == "V": grid[row + i][col] = '-' def validate_grid_words(grid, word_bank): """Check that every filled horizontal and vertical word is in the word_bank.""" slots = find_slots(grid) words_formed = [] for direction, row, col, length in slots: word = "" for i in range(length): if direction == "H": word += grid[row][col + i] elif direction == "V": word += grid[row + i][col] words_formed.append(word) return all(word in word_bank for word in words_formed) def solve_crossword(grid, word_bank, slots, intersections): """Backtracking function to solve the crossword and get all possible solutions.""" solutions = [] backtrack(grid, word_bank, slots, intersections, {}, solutions) return solutions def backtrack(grid, word_bank, slots, intersections, slot_to_word, solutions): """Perform backtracking with intelligent slot selection and constraint propagation.""" # If all slots are filled, store the current grid configuration if len(slot_to_word) == len(slots): if validate_grid_words(grid, word_bank): solutions.append(copy.deepcopy(grid)) return # Choose the most constrained slot slot_idx = min([i for i in range(len(slots)) if i not in slot_to_word], key=lambda idx: len([w for w in word_bank if can_place_word(grid, w, slots[idx])])) # Find all valid words for this slot slot = slots[slot_idx] valid_words = [word for word in word_bank if can_place_word(grid, word, slot)] for word in valid_words: # Place the word in the slot place_word(grid, word, slot) slot_to_word[slot_idx] = word word_bank.remove(word) # Propagate constraints to intersecting slots backtrack(grid, word_bank, slots, intersections, slot_to_word, solutions) # Backtrack: remove the word and restore state remove_word(grid, slot) word_bank.append(word) del slot_to_word[slot_idx] def print_grid(grid): """Print the crossword grid in a readable format.""" for row in grid: print("".join(row)) print() # For better separation between solutions # Sample grid and word bank for testing grid = [ ['#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'], ['#', '#', '#', '#', '#', '-', '-', '-', '#', '#', '#', '#'], ['#', '#', '#', '#', '#', '-', '#', '#', '#', '#', '#', '#'], ['#', '#', '#', '#', '#', '-', '#', '#', '#', '#', '#', '#'], ['#', '#', '#', '#', '#', '-', '#', '#', '#', '#', '#', '#'], ['#', '#', '#', '#', '#', '-', '#', '#', '#', '#', '#', '#'], ['#', '#', '#', '#', '#', '-', '#', '-', '-', '-', '-', '#'], ['#', '#', '#', '#', '#', '-', '#', '#', '-', '#', '-', '#'], ['#', '#', '#', '#', '#', '-', '-', '-', '-', '#', '-', '#'], ['#', '#', '#', '#', '#', '-', '#', '#', '-', '#', '-', '-'], ['#', '#', '#', '#', '#', '-', '#', '#', '#', '#', '-', '#'], ['#', '#', '#', '#', '#', '-', '#', '#', '#', '#', '#', '#'] ] word_bank = [ 'AP', 'ACH', 'DAO', 'DNA', 'GAP', 'GDP', 'HAT', 'HDC', 'HMT', 'NMJ', 'RHO', 'RNA', 'TSS', 'UGA', 'UPR', 'UTR', 'VAT', 'NE', 'NA', 'BETA', 'CAMP', 'CHAT', 'DOPA', 'EXIT', 'EXON', 'FULL', 'GENE', 'GPCR', 'HDAC', 'KDEL', 'MAST', 'MRNA', 'MULE', 'OCAT', 'RATE', 'RRNA', 'SNAP', 'STOP', 'TATA', 'TRNA', 'VAMP', 'VMAT', 'CGMP', 'ALPHA', 'AMINE', 'CODON', 'DIMER', 'EDMAN', 'GAMMA', 'GOLGI', 'HELIX', 'NOCAT', 'PROBE', 'SHEET', 'SNARE', 'SPARE', 'TOXIN', 'TRANS', 'VIRUS', 'BIASED', 'CODING', 'ENZYME', 'FUSION', 'GENOME', 'GRADED', 'GYRASE', 'INTRON', 'KINASE', 'LIGAND', 'MYELIN', 'NERNST', 'PLASMA', 'POLLEN', 'PURINE', 'RIBOSE', 'SANGER', 'SODIUM', 'TRIMER', 'ULCERS', 'URACIL', 'ADENINE', 'ADRENAL', 'AGONIST', 'ALLERGY', 'ANTIGEN', 'CAPPING', 'CHOLINE', 'COCAINE', 'CYCLASE', 'CYTOSOL', 'DOCKING', 'FOLDING', 'GOLDMAN', 'HISTONE', 'HORMONE', 'INVERSE', 'ITCHING', 'KINESIN', 'MEDULLA', 'OKAZAKI', 'PARTIAL', 'PEPTIDE', 'POTENCY', 'PRIMARY', 'PROTEIN', 'QUANTAL', 'RELEASE', 'SOMATIC', 'SUBUNIT', 'ADENYLYL', 'AFFINITY', 'ANTIBODY', 'ARCHAEAN', 'ARRESTIN', 'CARBOXYL', 'CHLORIDE', 'CYTOSINE', 'DOPAMINE', 'ENHANCER', 'ENVELOPE', 'EFFICACY', 'ERGOSOME', 'GRANULES', 'HAYFLICK', 'HELICASE', 'KINETICS', 'OBLIGATE', 'PEPTIDYL', 'POLYSOME', 'PROMOTER', 'RECEPTOR', 'RESPONSE', 'RIBOSOME', 'SILENCER', 'SPLICING', 'SVEDBERG', 'SYNAPTIC', 'SYNTHASE', 'TELOMERE', 'TERTIARY', 'TETRAMER', 'TOPOLOGY', 'TRIMERIC', 'TYROSINE', 'CONSTITUTIVE', 'POLYRIBOSOME', 'SCOMBROTOXIN', 'STREPTOMYCES', 'TRANSDUCTION', 'ACETYLCHOLINE', 'AMPLIFICATION', 'COMMUNICATION', 'COMPLEMENTARY', 'INTRACELLULAR', 'NEUROMUSCULAR', 'NORADRENALINE', 'PHENYLALANINE', 'PHOSPHOLIPASE', 'PREINITIATION', 'PROTEINOGENIC', 'TOPOISOMERASE', 'TRANSCRIPTION', 'CONFORMATIONAL', 'HETEROTETRAMER', 'NOREPINEPHRINE', 'SELENOCYSTEINE', 'COMPLEMENTATION', 'DESENSITIZATION', 'PARASYMPATHETIC', 'PHOSPHORYLATION', 'POLYADENYLATION', 'ULTRACENTIRFUGE', 'ACTIVATOR', 'AMINOACYL', 'AUTOCRINE', 'AUTONOMIC', 'CYCLIC GMP', 'CHROMATIN', 'CYTOPLASM', 'ENDOCRINE', 'EUKARYOTE', 'GUANYLATE', 'HISTAMINE', 'INTRINSIC', 'MESSENGER', 'MONOMERIC', 'PACKAGING', 'PARACRINE', 'PHOSPHATE', 'POTASSIUM', 'RECEPTION', 'REPRESSOR', 'SCOMBROID', 'SECONDARY', 'SYNTHESIS', 'TERMINATE', 'TETHERING', 'NICOTINIC', 'ADRENALINE', 'ALLOSTERIC', 'ANTAGONIST', 'APPOSITION', 'AUREOMYCIN', 'BIOPOLYMER', 'CARBOXYLIC', 'DEPENDENCE', 'ELONGATION', 'EXPRESSION', 'GANGLIONIC', 'IMMUNOBLOT', 'INITIATION', 'MUSCARINIC', 'NARCOLEPSY', 'NUCLEOSOME', 'NUCLEOTIDE', 'POLYMERASE', 'PROKARYOTE', 'PYRIMIDINE', 'QUATERNARY', 'REGULATION', 'STOCHASTIC', 'TELOMERASE', 'ACETYLATION', 'COMPETITIVE', 'DEOXYRIBOSE', 'EPINEPHRINE', 'EQUILIBRIUM', 'HYDROXYLASE', 'METHYLATION', 'POLYPEPTIDE', 'RECOGNITION', 'REPLICATION', 'SYMPATHETIC', 'TERMINATION', 'TRANSLATION', 'DEPHOSPHORYLATION', 'METHYLTRANSFERASE', 'NEUROTRANSMITTER' ] random.shuffle(word_bank) # Step 1: Identify the slots in the grid slots = find_slots(grid) # Step 2: Find intersections between slots intersections = get_intersections(slots) # Step 3: Solve the crossword and get all solutions solutions = solve_crossword(grid, word_bank, slots, intersections) # Step 4: Print all solutions print(f"Total Solutions: {len(solutions)}") for solution in solutions: print_grid(solution)
Editor is loading...
Leave a Comment