import os
def encode_message_to_coords(message: str) -> list[tuple[int, int, str]]:
"""
Encodes a string message into a list of (x, y, character) coordinates.
The message is encoded sequentially, filling a conceptual grid row by row.
"""
coordinates = []
x, y = 0, 0
max_x_per_row = 50 # Arbitrary max width for visual clarity in a text file
for char in message:
coordinates.append((x, y, char))
x += 1
if x >= max_x_per_row:
x = 0
y += 1
return coordinates
def save_coords_to_file(coordinates: list[tuple[int, int, str]], filename: str):
"""
Saves the list of coordinates to a text file, one coordinate per line.
"""
try:
with open(filename, 'w') as f:
for x, y, char in coordinates:
f.write(f"{x} {y} {char}\n")
print(f"Coordinates saved to {filename}")
except IOError as e:
print(f"Error saving coordinates to file: {e}")
raise
def load_coords_from_file(filename: str) -> list[tuple[int, int, str]]:
"""
Loads coordinates from a text file. Each line should be in the format 'x y char'.
"""
coordinates = []
try:
with open(filename, 'r') as f:
for line in f:
parts = line.strip().split(maxsplit=2) # maxsplit=2 to handle multi-word chars if needed, though here it's single char
if len(parts) == 3:
try:
x = int(parts[0])
y = int(parts[1])
char = parts[2]
coordinates.append((x, y, char))
except ValueError:
print(f"Skipping malformed line (non-integer coordinates): {line.strip()}")
else:
print(f"Skipping malformed line (incorrect parts count): {line.strip()}")
except FileNotFoundError:
print(f"Error: File '{filename}' not found.")
raise
except IOError as e:
print(f"Error reading file '{filename}': {e}")
raise
return coordinates
def build_grid(coordinates: list[tuple[int, int, str]]) -> list[list[str]]:
"""
Reconstructs a 2D grid from a list of (x, y, character) coordinates.
The grid will be sized to fit all characters.
"""
if not coordinates:
return []
max_x = 0
max_y = 0
for x, y, _ in coordinates:
if x > max_x:
max_x = x
if y > max_y:
max_y = y
# Initialize grid with spaces
grid = [[' ' for _ in range(max_x + 1)] for _ in range(max_y + 1)]
# Place characters on the grid
for x, y, char in coordinates:
if 0 <= y <= max_y and 0 <= x <= max_x: # Ensure coordinates are within bounds
grid[y][x] = char
else:
print(f"Warning: Coordinate ({x},{y}) out of calculated grid bounds. Skipping character '{char}'.")
return grid
def decode_grid_to_message(grid: list[list[str]]) -> str:
"""
Decodes the characters from the grid back into a sequential message.
It reads row by row, then column by column, collecting non-space characters.
"""
if not grid:
return ""
message_chars = []
# Assuming the message was encoded sequentially, reading row by row, column by column
# will reconstruct it in order.
for row in grid:
for char in row:
if char != ' ': # Only collect actual characters, ignore padding spaces
message_chars.append(char)
return "".join(message_chars)
def print_grid_to_console(grid: list[list[str]]):
"""
Prints the grid to the console.
"""
if not grid:
print("Empty grid.")
return
for row in grid:
print(''.join(row))
# Example Usage (for testing the script directly)
if __name__ == "__main__":
# --- Encoding Example ---
secret_policy_message = "This is a highly confidential corporate policy directive. Unauthorized disclosure is strictly prohibited. All personnel must adhere to these guidelines by 2025-08-01."
print("--- Encoding Message ---")
print(f"Original Message:\n{secret_policy_message}\n")
encoded_coords = encode_message_to_coords(secret_policy_message)
print(f"Encoded Coordinates (first 5):\n{encoded_coords[:5]}...\n")
# Save to a temporary file
temp_encoded_filename = "encoded_policy_document.txt"
try:
save_coords_to_file(encoded_coords, temp_encoded_filename)
except Exception as e:
print(f"Failed to save encoded file: {e}")
exit()
# --- Decoding Example ---
print("\n--- Decoding Message from File ---")
try:
loaded_coords = load_coords_from_file(temp_encoded_filename)
reconstructed_grid = build_grid(loaded_coords)
print("\nReconstructed Grid (visual):")
print_grid_to_console(reconstructed_grid)
decoded_message = decode_grid_to_message(reconstructed_grid)
print(f"\nDecoded Message:\n{decoded_message}")
# Verification
if decoded_message == secret_policy_message:
print("\nDecoding successful: Original message matches decoded message!")
else:
print("\nDecoding failed: Messages do NOT match.")
except Exception as e:
print(f"Failed to decode file: {e}")
finally:
# Clean up temporary file
if os.path.exists(temp_encoded_filename):
os.remove(temp_encoded_filename)
print(f"\nCleaned up temporary file: {temp_encoded_filename}")