I've carefully analyzed all four solutions to the markdown table fixing problem, and I'll create a hybrid implementation that combines the strongest elements from each approach. Here's my hybrid implementation that combines the strengths of all four solutions. Let me walk through the key features: 1. **Robust continuation line handling**: From o3-mini-high and Claude3.7, this implementation carefully handles multiline cells by merging continuation lines. 2. **Pattern detection**: I incorporated Claude3.7's sophisticated pattern detection to identify tables with separators after each data row, which was common in the examples. 3. **Cell normalization**: Using techniques from multiple solutions, the code properly handles tables with inconsistent column counts by padding short rows and merging extra cells. 4. **Style preservation**: Like all solutions, this implementation preserves the original table style (whether it has leading/trailing pipes). 5. **Minimal changes**: The function only modifies invalid tables while preserving valid ones and non-table content. The key innovations in this hybrid approach: - Better separation of concerns with clear, well-named functions - More robust pattern detection for tables with separators after each row - Improved handling of multiline cells with the enhanced merge_continuation_lines function - Clear docstrings explaining the purpose of each component This implementation should handle all the example cases provided and be more robust against edge cases than any individual solution. Would you like me to explain any specific part of the implementation in more detail? Artifact: ``` import re def fix_invalid_markdown_tables(markdown_text): """ Fixes invalid Markdown tables in the input text while preserving valid tables and non-table content. Args: markdown_text (str): Markdown text containing potential tables. Returns: str: Markdown text with invalid tables fixed. """ lines = markdown_text.splitlines() output = [] table_block = [] in_table = False for line in lines: if '|' in line: table_block.append(line) in_table = True elif in_table and line.strip(): # Continuation line for a multi-line cell table_block.append(line) else: if in_table: output.extend(process_table_block(table_block)) table_block = [] in_table = False output.append(line) # Handle any remaining table at the end if table_block: output.extend(process_table_block(table_block)) return "\n".join(output) def process_table_block(block_lines): """ Processes a block of lines that might contain a markdown table. Args: block_lines (list): Lines that potentially form a table Returns: list: Fixed table lines or the original lines if already valid """ # First, merge continuation lines merged_lines = merge_continuation_lines(block_lines) # Skip if no table content or too few lines if len(merged_lines) < 2 or not any('|' in line for line in merged_lines): return block_lines # Check if the merged version is a valid table if is_valid_table(merged_lines): # Table is already valid, preserve it exactly return block_lines # Table is invalid, fix it return fix_table_block(merged_lines) def merge_continuation_lines(lines): """ Merges lines that are continuations of multi-line cells. Args: lines (list): List of lines that might contain multi-line cells Returns: list: Lines with continuations merged """ merged = [] current = None for line in lines: if '|' in line: # This is a table row if current is not None: merged.append(current) current = line.rstrip() elif line.strip(): # This is a continuation of the previous line if current is not None: current += " " + line.strip() else: current = line.rstrip() else: # Empty line or non-continuation if current is not None: merged.append(current) current = None if line.strip(): merged.append(line) if current is not None: merged.append(current) return merged def parse_row(line): """ Parse a table row into cells, handling leading/trailing pipes. Args: line (str): A table row Returns: list: The cells in the row """ if not line or '|' not in line: return [] s = line.strip() has_lead = s.startswith('|') has_tail = s.endswith('|') if has_lead: s = s[1:] if has_tail: s = s[:-1] return [cell.strip() for cell in s.split('|')] def is_separator_cell(cell): """ Check if a cell contains a valid separator pattern (e.g., ---, :--:). Args: cell (str): The cell content Returns: bool: True if it's a valid separator cell, False otherwise """ return bool(re.fullmatch(r':?-{3,}:?', cell.strip())) def is_separator_row(cells): """ Check if cells represent a separator row. Args: cells (list): Table row cells Returns: bool: True if it's a separator row, False otherwise """ if not cells: return False # Every non-empty cell must match the separator pattern return all(is_separator_cell(cell) for cell in cells if cell.strip()) def is_valid_table(lines): """ Check if a markdown table is valid. Args: lines (list): Table lines Returns: bool: True if the table is valid, False otherwise """ if len(lines) < 2: return False # Parse rows into cells rows = [parse_row(line) for line in lines if '|' in line] if len(rows) < 2: return False # Check if second row is a separator if not is_separator_row(rows[1]): return False # Check column count consistency col_count = len(rows[0]) return all(len(row) == col_count for row in rows) def detect_table_style(line): """ Determine the table style (leading/trailing pipes) from a row. Args: line (str): A table row Returns: tuple: (has_leading_pipe, has_trailing_pipe) """ s = line.strip() return (s.startswith('|'), s.endswith('|')) def detect_separator_pattern(parsed_rows): """ Detect if the table has separators after each data row. Args: parsed_rows (list): List of parsed rows Returns: bool: True if separators appear after data rows """ if len(parsed_rows) < 3: return False # Get indices of separator rows sep_indices = [i for i, row in enumerate(parsed_rows) if is_separator_row(row)] # Check if there are many separator rows and they follow a pattern if len(sep_indices) <= 1: return False # Calculate how many odd-indexed rows are separators (which suggests separators after each data) odd_sep_count = sum(1 for i in sep_indices if i % 2 == 1) total_odds = (len(parsed_rows) - 1) // 2 # If more than half of the odd-indexed rows are separators, likely a pattern return odd_sep_count >= total_odds / 2 def normalize_row(row, target_cols): """ Normalize a row to have the target number of columns. Args: row (list): The row cells target_cols (int): The target number of columns Returns: list: Normalized row cells """ if len(row) < target_cols: # Pad with empty cells return row + [''] * (target_cols - len(row)) elif len(row) > target_cols: # Merge excess cells into the last one if target_cols > 1: return row[:target_cols-1] + [' '.join(row[target_cols-1:])] else: return [' '.join(row)] else: # Already correct length return row def rebuild_row(cells, style): """ Rebuild a table row from its cells. Args: cells (list): The cells in the row style (tuple): (has_leading_pipe, has_trailing_pipe) Returns: str: The rebuilt row """ if not cells: return '' row = " | ".join(cells) if style[0]: row = "| " + row if style[1]: row += " |" return row def fix_table_block(merged_lines): """ Fix an invalid markdown table with minimal changes. Args: merged_lines (list): The merged table lines Returns: list: Fixed table lines """ # Get table style from the first line style = detect_table_style(merged_lines[0]) # Parse all rows parsed_rows = [parse_row(line) for line in merged_lines if '|' in line] # Calculate max columns across all rows max_cols = max(len(row) for row in parsed_rows) if parsed_rows else 0 # Detect if separators follow data rows has_separators_after_rows = detect_separator_pattern(parsed_rows) # Determine which rows are separators is_sep = [is_separator_row(row) for row in parsed_rows] # Create fixed output fixed_lines = [] # Always start with header row header = normalize_row(parsed_rows[0], max_cols) fixed_lines.append(rebuild_row(header, style)) # Add separator after header separator = ['---'] * max_cols fixed_lines.append(rebuild_row(separator, style)) if has_separators_after_rows: # Separators after each data row pattern i = 1 while i < len(parsed_rows): if is_sep[i]: # Skip existing separators i += 1 continue # Add data row data_row = normalize_row(parsed_rows[i], max_cols) fixed_lines.append(rebuild_row(data_row, style)) # Add separator after data row fixed_lines.append(rebuild_row(separator, style)) i += 1 else: # Standard table: no separators between data rows for i in range(1, len(parsed_rows)): if not is_sep[i]: data_row = normalize_row(parsed_rows[i], max_cols) fixed_lines.append(rebuild_row(data_row, style)) return fixed_lines ```