Problem p01212 - Generation 3

Orig Description

Problem F: Mysterious Dungeons
The Kingdom of Aqua Canora Mystica is a very affluent and peaceful country, but around the
kingdom, there are many evil monsters that kill people. So the king gave an order to you to kill
the master monster.
You came to the dungeon where the monster lived. The dungeon consists of a grid of square
cells. You explored the dungeon moving up, down, left and right. You finally found, fought
against, and killed the monster.
Now, you are going to get out of the dungeon and return home. However, you found strange
carpets and big rocks are placed in the dungeon, which were not there until you killed the
monster. They are caused by the final magic the monster cast just before its death! Every rock
occupies one whole cell, and you cannot go through that cell. Also, each carpet covers exactly
one cell. Each rock is labeled by an uppercase letter and each carpet by a lowercase. Some of
the rocks and carpets may have the same label.
While going around in the dungeon, you observed the following behaviors. When you enter
into the cell covered by a carpet, all the rocks labeled with the corresponding letter (e.g., the
rocks with ‘A’ for the carpets with ‘a’) disappear. After the disappearance, you can enter the
cells where the rocks disappeared, but if you enter the same carpet cell again or another carpet
cell with the same label, the rocks revive and prevent your entrance again. After the revival,
you have to move on the corresponding carpet cell again in order to have those rocks disappear
again.
Can you exit from the dungeon? If you can, how quickly can you exit? Your task is to write
a program that determines whether you can exit the dungeon, and computes the minimum
required time.
Input
The input consists of some data sets.
Each data set begins with a line containing two integers, W and H (3 ≤ W, H ≤ 30). In each
of the following H lines, there are W characters, describing the map of the dungeon as W × H
grid of square cells. Each character is one of the following:
 ‘@’ denoting your current position,
 ‘<’ denoting the exit of the dungeon,
 A lowercase letter denoting a cell covered by a carpet with the label of that letter,
 An uppercase letter denoting a cell occupied by a rock with the label of that letter,
 ‘#’ denoting a wall, and
 ‘.’ denoting an empty cell.
Every dungeon is surrounded by wall cells (‘#’), and has exactly one ‘@’ cell and one ‘<’ cell.
There can be up to eight distinct uppercase labels for the rocks and eight distinct lowercase
labels for the carpets.
You can move to one of adjacent cells (up, down, left, or right) in one second. You cannot move
to wall cells or the rock cells.
A line containing two zeros indicates the end of the input, and should not be processed.
Output
For each data set, output the minimum time required to move from the ‘@’ cell to the ‘<’ cell,
in seconds, in one line. If you cannot exit, output -1.
Sample Input
8 3
########
#
                

Extracted Specification

An integer W (3 ≤ W ≤ 30) and an integer H (3 ≤ H ≤ 30), describing dimensions.
An H x W grid of characters, where:
- '@' denotes a starting position.
- '<' denotes an exit.
- Lowercase letters 'a'-'h' denote a specific type of cell.
- Uppercase letters 'A'-'H' denote another specific type of cell.
- '#' denotes a wall.
- '.' denotes an empty cell.
A line containing two zeros indicates the end of input and should not be processed.

### Example Input:

```
8 3
########
#
                

Test Case Generator

To create a test case generator for the "Mysterious Dungeons" problem, we need to generate random dungeon grids within the specified constraints. Here's a function that generates such test cases:

```python
import random
import string

def generate_dungeon(W, H):
    # Initialize grid with walls
    dungeon = [['#'] * W for _ in range(H)]
    
    # Place the player's starting position and the exit
    free_cells = [(i, j) for i in range(1, H-1) for j in range(1, W-1)]
    start_pos = random.choice(free_cells)
    free_cells.remove(start_pos)
    exit_pos = random.choice(free_cells)
    free_cells.remove(exit_pos)
    
    dungeon[start_pos[0]][start_pos[1]] = '@'
    dungeon[exit_pos[0]][exit_pos[1]] = '<'
    
    # Place rocks and carpets
    num_labels = random.randint(1, 8)
    labels = random.sample(string.ascii_uppercase[:8], num_labels)
    
    for label in labels:
        num_rocks = random.randint(1, 3)
        rock_positions = random.sample(free_cells, num_rocks)
        for pos in rock_positions:
            dungeon[pos[0]][pos[1]] = label
            free_cells.remove(pos)
        
        carpet_pos = random.choice(free_cells)
        dungeon[carpet_pos[0]][carpet_pos[1]] = label.lower()
        free_cells.remove(carpet_pos)
    
    # Fill remaining free cells with empty spaces
    for pos in free_cells:
        dungeon[pos[0]][pos[1]] = '.'
    
    return dungeon

def dungeon_to_string(dungeon):
    return "\n".join("".join(row) for row in dungeon)

def tcgen():
    test_cases = []
    
    # Generate a random number of test cases
    num_test_cases = random.randint(1, 10)
    
    for _ in range(num_test_cases):
        W = random.randint(3, 30)
        H = random.randint(3, 30)
        
        dungeon = generate_dungeon(W, H)
        test_case = f"{W} {H}\n{dungeon_to_string(dungeon)}"
        
        test_cases.append(test_case)
    
    # Add the termination line "0 0"
    test_cases.append("0 0")
    
    return "\n".join(test_cases)

# Example usage
print(tcgen())
```

This code defines a function `tcgen` that generates a set of random test cases for the "Mysterious Dungeons" problem. Here's a breakdown of the steps involved:

1. **Grid Initialization**: The dungeon is initialized as a grid filled with walls (`#`).
2. **Start and Exit Positions**: Random positions for the start (`@`) and exit (`<`) are chosen from the list of available cells.
3. **Rocks and Carpets**: A random number of rock and carpet labels (up to 8) are chosen. Each label has a random number (1-3) of rocks placed in the grid, and one carpet associated with it.
4. **Remaining Cells**: All remaining free cells are filled with empty spaces (`.`).
5. **Test Case Generation**: A random number of test cases (up to 10) are generated, each formatted as specified in the problem statement.
6. **Termination Line**: The line "0 0" is appended to indicate the end of the input.

This generator ensures that the generated dungeons adhere to the constraints and format specified in the problem statement.

Extract Arguments

def extract_arguments(fh):
    datasets = []
    while True:
        W, H = map(int, fh.readline().strip().split())
        if W == 0 and H == 0:
            break
        grid = [fh.readline().strip() for _ in range(H)]
        datasets.append((W, H, grid))
    return datasets

# if __name__ == "__main__":
#     input_path = sys.argv[1]
#     with open(input_path, 'r') as fh: 
#         inputs = extract_arguments(fh)
#         f(inputs)