Light Clean up

This commit is contained in:
Tobias Kessels
2024-12-12 12:50:03 +01:00
parent 69bf933f03
commit 77c5f531f0
11 changed files with 403 additions and 2394 deletions

805100
6/attempts/6a.ipynb Normal file

File diff suppressed because one or more lines are too long

787
6/attempts/6b.ipynb Normal file
View File

@@ -0,0 +1,787 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 155,
"metadata": {},
"outputs": [],
"source": [
"#import lru cache decorator\n",
"from functools import lru_cache\n",
"from copy import deepcopy\n",
"\n",
"\n",
"def load_map(file_path='testinput'):\n",
" with open(file_path, 'r') as file:\n",
" content = file.readlines()\n",
" return [list(line.strip()) for line in content]\n",
"\n",
"def get_map():\n",
" return deepcopy(load_map())"
]
},
{
"cell_type": "code",
"execution_count": 156,
"metadata": {},
"outputs": [],
"source": [
"emptymap = load_map()\n",
"map = load_map()"
]
},
{
"cell_type": "code",
"execution_count": 157,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Position: (6, 4) facing ^.\n"
]
},
{
"data": {
"text/plain": [
"(6, 4, '^')"
]
},
"execution_count": 157,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def get_start_position(map):\n",
" for x, row in enumerate(map):\n",
" for dir in ['^', '<', '>', 'V']:\n",
" if dir in row:\n",
" y = row.index(dir)\n",
" pos = (x, y, dir)\n",
" print(f\"Position: ({pos[0]}, {pos[1]}) facing {pos[2]}.\")\n",
" return pos\n",
"\n",
" return None\n",
"\n",
"\n",
"get_start_position(map)"
]
},
{
"cell_type": "code",
"execution_count": 158,
"metadata": {},
"outputs": [],
"source": [
"def printmap(map):\n",
" for row in map:\n",
" print(''.join(row))\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 159,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"....#.....\n",
".........#\n",
"..........\n",
"..#.......\n",
".......#..\n",
"..........\n",
".#..^.....\n",
"........#.\n",
"#.........\n",
"......#...\n"
]
}
],
"source": [
"printmap(load_map())"
]
},
{
"cell_type": "code",
"execution_count": 160,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(5, 4)"
]
},
"execution_count": 160,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def calculate_next_position(x, y, dir):\n",
" if dir == '^':\n",
" return (x - 1, y)\n",
" elif dir == '<':\n",
" return (x, y - 1)\n",
" elif dir == '>':\n",
" return (x, y + 1)\n",
" elif dir == 'V':\n",
" return (x + 1, y)\n",
"\n",
"def rotate(dir):\n",
" if dir == '^':\n",
" return '>'\n",
" elif dir == '<':\n",
" return '^'\n",
" elif dir == '>':\n",
" return 'V'\n",
" elif dir == 'V':\n",
" return '<'\n",
"\n",
"def in_bounds(map, x, y):\n",
" return 0 <= x < len(map) and 0 <= y < len(map[0])\n",
"\n",
"calculate_next_position(6, 4, '^')"
]
},
{
"cell_type": "code",
"execution_count": 161,
"metadata": {},
"outputs": [],
"source": [
"class LoopDetected(Exception):\n",
" pass\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 162,
"metadata": {},
"outputs": [],
"source": [
"def move(map, pos=None, visited=None):\n",
" # Initialize visited list if not provided\n",
" if visited is None:\n",
" visited = []\n",
" history = deepcopy(visited)\n",
" # Get the current position and direction if not provided\n",
" if pos is None:\n",
" pos = get_start_position(map)\n",
" \n",
" \n",
" if pos:\n",
" x, y, dir = pos \n",
"\n",
" new_x, new_y = calculate_next_position(*pos)\n",
"\n",
" # Handle obstacles by rotating until an open path is found\n",
" while in_bounds(map, new_x, new_y) and map[new_x][new_y] == '#':\n",
" dir = rotate(dir) # Rotate direction\n",
" new_x, new_y = calculate_next_position(x, y, dir)\n",
"\n",
" # Move to the new position if valid, otherwise return None\n",
" if in_bounds(map, new_x, new_y) and map[new_x][new_y] != '#':\n",
" pos = (new_x,new_y,dir)\n",
" history.append(pos)\n",
" else:\n",
" pos = None\n",
"\n",
" \n",
" # No valid move was possible or guard is out of bounds\n",
" return pos, history\n"
]
},
{
"cell_type": "code",
"execution_count": 163,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"....#.....\n",
".........#\n",
"..........\n",
"..#.......\n",
".......#..\n",
"..........\n",
".#..^.....\n",
"........#.\n",
"#.........\n",
"......#...\n"
]
}
],
"source": [
"printmap(map)"
]
},
{
"cell_type": "code",
"execution_count": 164,
"metadata": {},
"outputs": [],
"source": [
"def merge_element(new,old):\n",
"\n",
" mergetable = {\n",
" # Straight line merges\n",
" ('─', '─'): '─',\n",
" ('│', '│'): '│',\n",
" ('─', '│'): '┼',\n",
" ('│', '─'): '┼',\n",
"\n",
" # Corners with straight lines\n",
" ('─', '┌'): '┬',\n",
" ('─', '┐'): '┬',\n",
" ('─', '└'): '┴',\n",
" ('─', '┘'): '┴',\n",
" ('│', '┌'): '├',\n",
" ('│', '┐'): '┤',\n",
" ('│', '└'): '├',\n",
" ('│', '┘'): '┤',\n",
"\n",
" # Corners with corners\n",
" ('┌', '┐'): '┬',\n",
" ('┌', '└'): '├',\n",
" ('┌', '┘'): '┼',\n",
" ('┐', '└'): '┼',\n",
" ('┐', '┘'): '┤',\n",
" ('└', '┘'): '┴',\n",
"\n",
" # Straight lines with T-junctions\n",
" ('─', '┬'): '┬',\n",
" ('─', '┴'): '┴',\n",
" ('─', '├'): '┼',\n",
" ('─', '┤'): '┼',\n",
" ('│', '┬'): '┼',\n",
" ('│', '┴'): '┼',\n",
" ('│', '├'): '├',\n",
" ('│', '┤'): '┤',\n",
"\n",
" # Corners with T-junctions\n",
" ('┌', '┬'): '┬',\n",
" ('┌', '┴'): '├',\n",
" ('┌', '├'): '├',\n",
" ('┌', '┤'): '┼',\n",
" ('┐', '┬'): '┬',\n",
" ('┐', '┴'): '┤',\n",
" ('┐', '├'): '┼',\n",
" ('┐', '┤'): '┤',\n",
" ('└', '┬'): '├',\n",
" ('└', '┴'): '┴',\n",
" ('└', '├'): '├',\n",
" ('└', '┤'): '┼',\n",
" ('┘', '┬'): '┤',\n",
" ('┘', '┴'): '┴',\n",
" ('┘', '├'): '┼',\n",
" ('┘', '┤'): '┤',\n",
"\n",
" # T-junctions with T-junctions\n",
" ('┬', '┬'): '┬',\n",
" ('┬', '┴'): '┼',\n",
" ('┬', '├'): '┼',\n",
" ('┬', '┤'): '┼',\n",
" ('┴', '┴'): '┴',\n",
" ('┴', '├'): '┼',\n",
" ('┴', '┤'): '┼',\n",
" ('├', '├'): '├',\n",
" ('├', '┤'): '┼',\n",
" ('┤', '┤'): '┤',\n",
"\n",
" # Full crossings\n",
" ('─', '┼'): '┼',\n",
" ('│', '┼'): '┼',\n",
" ('┌', '┼'): '┼',\n",
" ('┐', '┼'): '┼',\n",
" ('└', '┼'): '┼',\n",
" ('┘', '┼'): '┼',\n",
" ('┬', '┼'): '┼',\n",
" ('┴', '┼'): '┼',\n",
" ('├', '┼'): '┼',\n",
" ('┤', '┼'): '┼',\n",
" ('┼', '┼'): '┼',\n",
" }\n",
"\n",
" if old and new:\n",
" if (old,new) in mergetable:\n",
" return mergetable[(old,new)]\n",
" if (new,old) in mergetable:\n",
" return mergetable[(new,old)]\n",
" if new:\n",
" return new\n",
" return old\n",
"\n",
"def get_draw_element(current_dir, new_dir, existing_symbol=None):\n",
" direction_merge = {\n",
" # Straight Movements\n",
" ('^', '^'): '│', # Continue moving up\n",
" ('V', 'V'): '│', # Continue moving down\n",
" ('<', '<'): '─', # Continue moving left\n",
" ('>', '>'): '─', # Continue moving right\n",
"\n",
" # Turns from Up ('^')\n",
" ('^', '>'): '┌', # Turn right from up\n",
" ('^', '<'): '┐', # Turn left from up\n",
"\n",
" # Turns from Down ('v')\n",
" ('V', '>'): '└', # Turn right from down\n",
" ('V', '<'): '┘', # Turn left from down\n",
"\n",
" # Turns from Left ('<')\n",
" ('<', '^'): '└', # Turn up from left\n",
" ('<', 'V'): '┌', # Turn down from left\n",
"\n",
" # Turns from Right ('>')\n",
" ('>', '^'): '┘', # Turn up from right\n",
" ('>', 'V'): '┐', # Turn down from right\n",
"\n",
" # Reverse Movements\n",
" ('^', 'V'): '│', # Reverse direction (up to down)\n",
" ('V', '^'): '│', # Reverse direction (down to up)\n",
" ('<', '>'): '─', # Reverse direction (left to right)\n",
" ('>', '<'): '─', # Reverse direction (right to left)\n",
" }\n",
" return merge_element(direction_merge[(current_dir,new_dir)],existing_symbol)\n",
"\n",
"def drawroute(map,visited):\n",
" temp_map = deepcopy(map)\n",
" for cur,new in zip(visited,visited[1:]):\n",
" if cur is None or new is None:\n",
" raise ValueError(f\"visited had a None entry! cur:{cur} new:{new}\")\n",
" if len(new) <3:\n",
" raise ValueError(f\"visited had a malformed entry : cur:{cur}\")\n",
" x,y,dir = cur\n",
" nx,ny,ndir = new\n",
" temp_map[x][y] = get_draw_element(dir,ndir,temp_map[x][y])\n",
" \n",
" temp_map[nx][ny] = get_draw_element(ndir,ndir) # Mark start point\n",
"\n",
" printmap(temp_map)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 165,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Position: (6, 4) facing ^.\n",
"....#.....\n",
".........#\n",
"..........\n",
"..#.......\n",
".......#..\n",
"..........\n",
".#..^.....\n",
"........#.\n",
"#.........\n",
"......#...\n",
"....#.....\n",
"....┌───┐#\n",
"....│...│.\n",
"..#.│...│.\n",
"..┌─┼─┐#│.\n",
"..│.│.│.│.\n",
".#└───┼─┘.\n",
".┌────┼┐#.\n",
"#└────┘│..\n",
"......#│..\n"
]
}
],
"source": [
"pos,visited = move(map)\n",
"printmap(map)\n",
"\n",
"while pos:\n",
" pos,visited = move(map,pos,visited)\n",
"\n",
"drawroute(map,visited)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 166,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(41, 44)"
]
},
"execution_count": 166,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def count_visited(visited):\n",
" visited = set([(x,y) for x,y,dir in visited]) # Convert list to set to remove duplicates\n",
" return len(visited)\n",
"\n",
"count_visited(visited), len(visited)"
]
},
{
"cell_type": "code",
"execution_count": 99,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[34]"
]
},
"execution_count": 99,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"[idx for idx,(x,y,d) in enumerate(visited) if x == 8 and y ==1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 100,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"((8, 2, '<'), (8, 1, '<'), 32, 44)"
]
},
"execution_count": 100,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"test_position = 34\n",
"guardposition = visited[test_position-1]\n",
"obsticalposition = visited[test_position]\n",
"\n",
"history = visited[:test_position-2]\n",
"guardposition,obsticalposition, len(history), len(visited)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 101,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"....#.....\n",
".........#\n",
"..........\n",
"..#.......\n",
".......#..\n",
"..........\n",
".#..^.....\n",
"........#.\n",
"##........\n",
"......#...\n",
"....#.....\n",
"....┌───┐#\n",
"....│...│.\n",
"..#.│...│.\n",
"..┌─┼─┐#│.\n",
"..│.│.│.│.\n",
".#└───┼─┘.\n",
"......│.#.\n",
"##..──┘...\n",
"......#...\n"
]
}
],
"source": [
"# create copy of map with additional obstacle at pos\n",
"def add_obstacle(pos):\n",
" # create a copy of the original map\n",
" new_map = get_map()\n",
" # add the obstacle to the new map\n",
" x,y,dir = pos\n",
" new_map[x][y] = '#'\n",
" return new_map\n",
"\n",
"testmap = add_obstacle(obsticalposition)\n",
"printmap(testmap)\n",
"drawroute(testmap,history)\n",
"pos = guardposition"
]
},
{
"cell_type": "code",
"execution_count": 103,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(7, 2, '^')\n"
]
}
],
"source": [
"newpos,newhistory = move(testmap,guardposition,history)\n",
"print(newpos)\n"
]
},
{
"cell_type": "code",
"execution_count": 106,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"....#.....\n",
"....┌───┐#\n",
"....│...│.\n",
"..#.│...│.\n",
"..┌─┼─┐#│.\n",
"..│.│.│.│.\n",
".#└───┼─┘.\n",
"......│.#.\n",
"##..──┘...\n",
"......#...\n"
]
}
],
"source": [
"drawroute(testmap,history)"
]
},
{
"cell_type": "code",
"execution_count": 143,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"....#.....\n",
"....┌───┐#\n",
"....│...│.\n",
"..#.│...│.\n",
"..┌─┼─┐#│.\n",
"..│.│.│.│.\n",
".#├───┼─┘.\n",
"..│...│.#.\n",
"##└─┴─┘...\n",
"......#...\n"
]
}
],
"source": [
"pos,history = move(testmap,pos,history)\n",
"drawroute(testmap,history)\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 168,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loop detected with obstacle at (4, 4, '^')\n",
"Loop detected with obstacle at (3, 4, '^')\n",
"Loop detected with obstacle at (2, 4, '^')\n",
"Loop detected with obstacle at (1, 4, '^')\n",
"Loop detected with obstacle at (1, 5, '>')\n",
"Loop detected with obstacle at (1, 6, '>')\n",
"Loop detected with obstacle at (1, 7, '>')\n",
"Loop detected with obstacle at (1, 8, '>')\n",
"Loop detected with obstacle at (2, 8, 'V')\n",
"Loop detected with obstacle at (3, 8, 'V')\n",
"Loop detected with obstacle at (4, 8, 'V')\n",
"Loop detected with obstacle at (5, 8, 'V')\n",
"Loop detected with obstacle at (6, 8, 'V')\n",
"Loop detected with obstacle at (6, 7, '<')\n",
"Loop detected with obstacle at (6, 6, '<')\n",
"Loop detected with obstacle at (6, 5, '<')\n",
"Loop detected with obstacle at (6, 4, '<')\n",
"Loop detected with obstacle at (6, 3, '<')\n",
"Loop detected with obstacle at (6, 2, '<')\n",
"Loop detected with obstacle at (5, 2, '^')\n",
"Loop detected with obstacle at (4, 2, '^')\n",
"Loop detected with obstacle at (4, 3, '>')\n",
"Loop detected with obstacle at (4, 4, '>')\n",
"Loop detected with obstacle at (4, 5, '>')\n",
"Loop detected with obstacle at (4, 6, '>')\n",
"Loop detected with obstacle at (5, 6, 'V')\n",
"Loop detected with obstacle at (6, 6, 'V')\n",
"Loop detected with obstacle at (7, 6, 'V')\n",
"Loop detected with obstacle at (8, 6, 'V')\n",
"Loop detected with obstacle at (8, 5, '<')\n",
"Loop detected with obstacle at (8, 4, '<')\n",
"Loop detected with obstacle at (8, 3, '<')\n",
"Loop detected with obstacle at (8, 2, '<')\n",
"Loop detected with obstacle at (8, 1, '<')\n",
"Loop detected with obstacle at (7, 1, '^')\n",
"Loop detected with obstacle at (7, 2, '>')\n",
"Loop detected with obstacle at (7, 3, '>')\n",
"Loop detected with obstacle at (7, 4, '>')\n",
"Loop detected with obstacle at (7, 5, '>')\n",
"Loop detected with obstacle at (7, 6, '>')\n",
"Loop detected with obstacle at (7, 7, '>')\n",
"Loop detected with obstacle at (8, 7, 'V')\n",
"Loop detected with obstacle at (9, 7, 'V')\n",
"Total loop positions: 43\n"
]
},
{
"data": {
"text/plain": [
"[(4, 4, '^'),\n",
" (3, 4, '^'),\n",
" (2, 4, '^'),\n",
" (1, 4, '^'),\n",
" (1, 5, '>'),\n",
" (1, 6, '>'),\n",
" (1, 7, '>'),\n",
" (1, 8, '>'),\n",
" (2, 8, 'V'),\n",
" (3, 8, 'V'),\n",
" (4, 8, 'V'),\n",
" (5, 8, 'V'),\n",
" (6, 8, 'V'),\n",
" (6, 7, '<'),\n",
" (6, 6, '<'),\n",
" (6, 5, '<'),\n",
" (6, 4, '<'),\n",
" (6, 3, '<'),\n",
" (6, 2, '<'),\n",
" (5, 2, '^'),\n",
" (4, 2, '^'),\n",
" (4, 3, '>'),\n",
" (4, 4, '>'),\n",
" (4, 5, '>'),\n",
" (4, 6, '>'),\n",
" (5, 6, 'V'),\n",
" (6, 6, 'V'),\n",
" (7, 6, 'V'),\n",
" (8, 6, 'V'),\n",
" (8, 5, '<'),\n",
" (8, 4, '<'),\n",
" (8, 3, '<'),\n",
" (8, 2, '<'),\n",
" (8, 1, '<'),\n",
" (7, 1, '^'),\n",
" (7, 2, '>'),\n",
" (7, 3, '>'),\n",
" (7, 4, '>'),\n",
" (7, 5, '>'),\n",
" (7, 6, '>'),\n",
" (7, 7, '>'),\n",
" (8, 7, 'V'),\n",
" (9, 7, 'V')]"
]
},
"execution_count": 168,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def find_loops(map, visited):\n",
" loop_positions = [] # Array to store positions leading to loops\n",
" \n",
" for idx, obstacle_position in enumerate(visited[1:]): # Skip the starting position\n",
" # Determine the position before the obstacle\n",
" if idx == 0:\n",
" guard_start_position = visited[0]\n",
" else:\n",
" guard_start_position = visited[idx - 1]\n",
" \n",
" # Create a new map with the obstacle added\n",
" test_map = add_obstacle(obstacle_position)\n",
" \n",
" # Initialize history from the visited list up to the current index\n",
" history = deepcopy(visited[:idx])\n",
" \n",
" # Start simulation\n",
" pos = guard_start_position\n",
" while pos and pos not in history:\n",
" pos, history = move(test_map, pos, history)\n",
" \n",
" # Check if a loop was detected\n",
" if pos and pos in history:\n",
" loop_positions.append(obstacle_position)\n",
" print(f\"Loop detected with obstacle at {obstacle_position}\")\n",
" \n",
" print(f\"Total loop positions: {len(loop_positions)}\")\n",
" return loop_positions\n",
"\n",
"find_loops(map,visited)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

465
6/attempts/6c.ipynb Normal file
View File

@@ -0,0 +1,465 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"with open('testinput', 'r') as file:\n",
" content = file.readlines()\n",
"\n",
"map = [list(line.strip()) for line in content]\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"def get_start_position(map):\n",
" for i, row in enumerate(map):\n",
" for dir in ['^', '<', '>', 'V']:\n",
" if dir in row:\n",
" return (i, row.index(dir), dir)\n",
" return -1,-1,None\n",
"\n",
"\n",
"start_x,start_y,start_dir = get_start_position(map)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Position: (6, 4) facing ^, sofar visited 0 cells.\n",
"....#.....\n",
".........#\n",
"..........\n",
"..#.......\n",
".......#..\n",
"..........\n",
".#..^.....\n",
"........#.\n",
"#.........\n",
"......#...\n"
]
}
],
"source": [
"def count_visited(map):\n",
" return sum(row.count('X') for row in map)\n",
"\n",
"def printmap(map):\n",
" x, y, dir = get_start_position(map)\n",
" if dir:\n",
" print(f\"Position: ({x}, {y}) facing {dir}, sofar visited {count_visited(map)} cells.\")\n",
" else:\n",
" print(f\"No guard found! Visited {count_visited(map)} cells.\")\n",
" for row in map:\n",
" print(''.join(row))\n",
"\n",
"\n",
"printmap(map)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(5, 4)"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def calculate_next_position(x, y, dir):\n",
" if dir == '^':\n",
" return (x - 1, y)\n",
" elif dir == '<':\n",
" return (x, y - 1)\n",
" elif dir == '>':\n",
" return (x, y + 1)\n",
" elif dir == 'V':\n",
" return (x + 1, y)\n",
"\n",
"def in_bounds(map, x, y):\n",
" return 0 <= x < len(map) and 0 <= y < len(map[0])\n",
"\n",
"calculate_next_position(6, 4, '^')"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"def move(map,pos=None):\n",
" # Get the current position of the robot\n",
" if pos is None:\n",
" x, y, dir = get_start_position(map)\n",
" elif len(pos)==3:\n",
" x,y, dir = pos\n",
" else:\n",
" raise ValueError()\n",
" \n",
" if in_bounds(map,x,y):\n",
" map[x][y] = 'X'\n",
"\n",
" if dir:\n",
" # Determine the next position based on the current direction\n",
" new_x, new_y = calculate_next_position(x, y, dir)\n",
" # while new position is obstacle turn right and recalculate the next position\n",
" while in_bounds(map,new_x,new_y) and map[new_x][new_y] == '#':\n",
" if dir == '^':\n",
" dir = '>'\n",
" elif dir == '<':\n",
" dir = '^'\n",
" elif dir == '>':\n",
" dir = 'V'\n",
" elif dir == 'V':\n",
" dir = '<'\n",
" new_x, new_y = calculate_next_position(x, y, dir)\n",
" # Update the map with the robot's new position and direction\n",
" if in_bounds(map,new_x,new_y):\n",
" map[new_x][new_y] = dir\n",
" return True, (new_x,new_y,dir)\n",
" \n",
" else:\n",
" print(f\"No guard found! Visited {count_visited(map)} cells.\")\n",
" return False, (-1,-1,dir)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Position: (5, 4) facing ^, sofar visited 1 cells.\n",
"....#.....\n",
".........#\n",
"..........\n",
"..#.......\n",
".......#..\n",
"....^.....\n",
".#..X.....\n",
"........#.\n",
"#.........\n",
"......#...\n"
]
},
{
"data": {
"text/plain": [
"(True, (5, 4, '^'))"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"result,pos = move(map)\n",
"printmap(map)\n",
"result,pos"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True\n",
"No guard found! Visited 41 cells.\n",
"....#.....\n",
"....XXXXX#\n",
"....X...X.\n",
"..#.X...X.\n",
"..XXXXX#X.\n",
"..X.X.X.X.\n",
".#XXXXXXX.\n",
".XXXXXXX#.\n",
"#XXXXXXX..\n",
"......#X..\n"
]
}
],
"source": [
"print(result)\n",
"while result:\n",
" result,pos = move(map,pos)\n",
"\n",
"printmap(map)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"No guard found! Visited 41 cells.\n",
"....#.....\n",
"....XXXXX#\n",
"....X...X.\n",
"..#.X...X.\n",
"..XXXXX#X.\n",
"..X.X.X.X.\n",
".#XXXXXXX.\n",
".XXXXXXX#.\n",
"#XXXXXXX..\n",
"......#X..\n",
"Position: (6, 4) facing ^, sofar visited 0 cells.\n",
"....#.....\n",
".........#\n",
"..........\n",
"..#.......\n",
".......#..\n",
"..........\n",
".#..^.....\n",
"........#.\n",
"#.........\n",
"......#...\n"
]
}
],
"source": [
"finished_map = map.copy()\n",
"map = [list(line.strip()) for line in content]\n",
"printmap(finished_map)\n",
"printmap(map)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{(3, 4), (4, 3), (5, 4), (4, 6), (8, 3), (8, 6), (1, 6), (2, 8), (7, 4), (6, 2), (7, 1), (7, 7), (6, 5), (6, 8), (4, 2), (4, 5), (5, 6), (4, 8), (8, 2), (9, 7), (8, 5), (2, 4), (1, 5), (1, 8), (7, 3), (6, 7), (7, 6), (5, 2), (4, 4), (3, 8), (8, 4), (5, 8), (8, 1), (8, 7), (1, 4), (1, 7), (7, 2), (6, 6), (7, 5), (6, 3)}\n"
]
}
],
"source": [
"#Prepare list of possible positions for a obstiacle to force guard into a loop and check if it causes a loop\n",
"def get_visited_positions(map):\n",
" visited = set()\n",
" for i, row in enumerate(map):\n",
" for j, cell in enumerate(row):\n",
" if cell == 'X':\n",
" if (i,j) != (start_x,start_y): #ignore the starting position\n",
" visited.add((i,j))\n",
" return visited\n",
"\n",
"print(get_visited_positions(finished_map))"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"# create copy of map with additional obstacle at pos\n",
"def add_obstacle(map, pos):\n",
" # create a copy of the original map\n",
" new_map = [row[:] for row in map]\n",
" # add the obstacle to the new map\n",
" new_map[pos[0]][pos[1]] = '#'\n",
" return new_map\n",
"\n",
"def check_loop(emptymap,pos):\n",
" #make copy of map\n",
" map = add_obstacle(emptymap,pos)\n",
" # create a set to keep track of visited positions and directions\n",
" visited = set()\n",
" # Get the current position of the robot\n",
" x,y,dir = get_start_position(map)\n",
" while dir and (x,y,dir) not in visited:\n",
" visited.add((x,y,dir))\n",
" # Determine the next position based on the current direction\n",
" result,pos = move(map,(x,y,dir))\n",
" x,y,dir = pos\n",
" \n",
" if dir and (x,y,dir) in visited:\n",
" print(f\"Found loop with {len(visited)} with obstical at {pos}\")\n",
" return True\n",
" else:\n",
" print(f\"No loop found after {len(visited)} visited positions.\")\n",
" return False\n"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Found loop with 24 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (3, 4)\n",
"Found loop with 29 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (4, 3)\n",
"Found loop with 7 with obstical at (-1, -1, '>')\n",
"Loop detected at position (5, 4)\n",
"Found loop with 32 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (4, 6)\n",
"Found loop with 34 with obstical at (6, 4, '^')\n",
"Loop detected at position (8, 3)\n",
"Found loop with 37 with obstical at (-1, -1, '<')\n",
"Loop detected at position (8, 6)\n",
"Found loop with 16 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (1, 6)\n",
"Found loop with 19 with obstical at (-1, -1, '<')\n",
"Loop detected at position (2, 8)\n",
"Found loop with 42 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (7, 4)\n",
"Found loop with 27 with obstical at (-1, -1, '^')\n",
"Loop detected at position (6, 2)\n",
"Found loop with 45 with obstical at (-1, -1, '>')\n",
"Loop detected at position (7, 1)\n",
"Found loop with 42 with obstical at (8, 6, 'V')\n",
"Loop detected at position (7, 7)\n",
"Found loop with 24 with obstical at (-1, -1, '^')\n",
"Loop detected at position (6, 5)\n",
"Found loop with 23 with obstical at (-1, -1, '<')\n",
"Loop detected at position (6, 8)\n",
"Found loop with 30 with obstical at (-1, -1, '>')\n",
"Loop detected at position (4, 2)\n",
"Found loop with 31 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (4, 5)\n",
"Found loop with 34 with obstical at (-1, -1, '<')\n",
"Loop detected at position (5, 6)\n",
"Found loop with 21 with obstical at (-1, -1, '^')\n",
"Loop detected at position (4, 8)\n",
"Found loop with 43 with obstical at (-1, -1, '^')\n",
"Loop detected at position (8, 2)\n",
"Found loop with 45 with obstical at (8, 5, '<')\n",
"Loop detected at position (9, 7)\n",
"Found loop with 40 with obstical at (-1, -1, '^')\n",
"Loop detected at position (8, 5)\n",
"Found loop with 10 with obstical at (-1, -1, '>')\n",
"Loop detected at position (2, 4)\n",
"Found loop with 15 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (1, 5)\n",
"Found loop with 19 with obstical at (-1, -1, '^')\n",
"Loop detected at position (1, 8)\n",
"Found loop with 41 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (7, 3)\n",
"Found loop with 22 with obstical at (-1, -1, '^')\n",
"Loop detected at position (6, 7)\n",
"Found loop with 29 with obstical at (6, 5, '<')\n",
"Loop detected at position (7, 6)\n",
"Found loop with 29 with obstical at (-1, -1, '>')\n",
"Loop detected at position (5, 2)\n",
"Found loop with 8 with obstical at (-1, -1, '>')\n",
"Loop detected at position (4, 4)\n",
"Found loop with 20 with obstical at (-1, -1, '<')\n",
"Loop detected at position (3, 8)\n",
"Found loop with 41 with obstical at (-1, -1, '^')\n",
"Loop detected at position (8, 4)\n",
"Found loop with 18 with obstical at (-1, -1, '^')\n",
"Loop detected at position (5, 8)\n",
"Found loop with 37 with obstical at (5, 2, '^')\n",
"Loop detected at position (8, 1)\n",
"Found loop with 51 with obstical at (-1, -1, '<')\n",
"Loop detected at position (8, 7)\n",
"Found loop with 11 with obstical at (-1, -1, '>')\n",
"Loop detected at position (1, 4)\n",
"Found loop with 30 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (1, 7)\n",
"Found loop with 40 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (7, 2)\n",
"Found loop with 20 with obstical at (-1, -1, '>')\n",
"Loop detected at position (6, 6)\n",
"Found loop with 43 with obstical at (-1, -1, 'V')\n",
"Loop detected at position (7, 5)\n",
"Found loop with 19 with obstical at (5, 4, '^')\n",
"Loop detected at position (6, 3)\n",
"Possible loops: 40\n"
]
}
],
"source": [
"\n",
"#Check if a loop is formed by placing an obstacle in one of the visited positions\n",
"possibles_loops = []\n",
"for pos in get_visited_positions(finished_map):\n",
" if check_loop(map,pos):\n",
" print(f\"Loop detected at position {pos}\")\n",
" possibles_loops.append(pos)\n",
"\n",
"print(f\"Possible loops: {len(possibles_loops)}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"printmap(map)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
}