diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..860f418 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +.vscode/ \ No newline at end of file diff --git a/7.Reverse_integer/.ipynb_checkpoints/debug_testing-checkpoint.ipynb b/.ipynb_checkpoints/139. Word Break-checkpoint.ipynb similarity index 100% rename from 7.Reverse_integer/.ipynb_checkpoints/debug_testing-checkpoint.ipynb rename to .ipynb_checkpoints/139. Word Break-checkpoint.ipynb diff --git a/.ipynb_checkpoints/21. Merge Two Sorted Lists-checkpoint.ipynb b/.ipynb_checkpoints/21. Merge Two Sorted Lists-checkpoint.ipynb new file mode 100644 index 0000000..2fd6442 --- /dev/null +++ b/.ipynb_checkpoints/21. Merge Two Sorted Lists-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/.ipynb_checkpoints/402. Remove K Digits-checkpoint.ipynb b/.ipynb_checkpoints/402. Remove K Digits-checkpoint.ipynb new file mode 100644 index 0000000..3aff7bb --- /dev/null +++ b/.ipynb_checkpoints/402. Remove K Digits-checkpoint.ipynb @@ -0,0 +1,151 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Problem description\n", + "Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible.\n", + "\n", + "Note:\n", + "The length of num is less than 10002 and will be ≥ k.\n", + "The given num does not contain any leading zero.\n", + "\n", + "Example 1:\n", + "Input: num = \"1432219\", k = 3 \n", + "Output: \"1219\" \n", + "Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest. \n", + "\n", + "Example 2: \n", + "Input: num = \"10200\", k = 1 \n", + "Output: \"200\" \n", + "Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes. \n", + "\n", + "Example 3: \n", + "Input: num = \"10\", k = 2 \n", + "Output: \"0\" \n", + "Explanation: Remove all the digits from the number and it is left with nothing which is 0." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Solution(object):\n", + " def removeKdigits(self, num, k):\n", + " \"\"\"\n", + " :type num: str\n", + " :type k: int\n", + " :rtype: str\n", + " \"\"\"\n", + " if k == len(num):\n", + " return \"0\"\n", + " if k == 0:\n", + " return min(num)\n", + " candidate = [int(num[:i]+num[i+1:]) for i in range(len(num))]\n", + " return removeKdigits(_, candidate, k-1)\n", + " \n", + " \n", + "\n", + "num = \"1432219\"\n", + "k = 3\n", + "Solution.removeKdigits(_, num, k)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['1', '0', '0', '0', '2', '0']" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(\"100020\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[432219, 132219, 142219, 143219, 143219, 143229, 143221]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "num = \"1432219\"\n", + "candidate = [int(num[:i]+num[i+1:]) for i in range(len(num))]\n", + "candidate" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "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.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/.ipynb_checkpoints/540. Single Element in a Sorted Array-checkpoint.ipynb b/.ipynb_checkpoints/540. Single Element in a Sorted Array-checkpoint.ipynb new file mode 100644 index 0000000..2fd6442 --- /dev/null +++ b/.ipynb_checkpoints/540. Single Element in a Sorted Array-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/.ipynb_checkpoints/937. Reorder Data in Log Files-checkpoint.ipynb b/.ipynb_checkpoints/937. Reorder Data in Log Files-checkpoint.ipynb new file mode 100644 index 0000000..2fd6442 --- /dev/null +++ b/.ipynb_checkpoints/937. Reorder Data in Log Files-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/.ipynb_checkpoints/Linked_list_related-checkpoint.ipynb b/.ipynb_checkpoints/Linked_list_related-checkpoint.ipynb new file mode 100644 index 0000000..240f936 --- /dev/null +++ b/.ipynb_checkpoints/Linked_list_related-checkpoint.ipynb @@ -0,0 +1,206 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "class ListNode(object):\n", + " def __init__(self, val=0, next=None):\n", + " self.val = val\n", + " self.next = next" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "LN1 = ListNode(2, ListNode(4, ListNode(3)))\n", + "LN2 = ListNode(5, ListNode(6, ListNode(4)))\n", + "LN3 = ListNode(5, ListNode(6, ListNode(4, ListNode(1))))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "num1=2, num2=5, tmp_num=7, total_num=7\n", + "num1=4, num2=6, tmp_num=100, total_num=107\n", + "num1=3, num2=4, tmp_num=700, total_num=807\n" + ] + }, + { + "data": { + "text/plain": [ + "807" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def addTwoNumbers(l1, l2):\n", + " \"\"\"\n", + " :type l1: ListNode\n", + " :type l2: ListNode\n", + " :rtype: ListNode\n", + " \"\"\"\n", + " digit = 0\n", + " total_num = 0\n", + " while l1 and l2:\n", + " num1 = l1.val\n", + " num2 = l2.val\n", + " tmp_num = (num1+num2)*(10**digit)\n", + " total_num += tmp_num\n", + " print(f\"num1={num1}, num2={num2}, tmp_num={tmp_num}, total_num={total_num}\")\n", + " l1 = l1.next\n", + " l2 = l2.next\n", + " digit += 1\n", + "\n", + " while l1: #l2 exhausted\n", + " num1 = l1.val\n", + " tmp_num = num1 * (10**digit)\n", + " total_num += tmp_num\n", + " print(f\"num1={num1}, num2={num2}, tmp_num={tmp_num}, total_num={total_num}\")\n", + " l1 = l1.next\n", + " digit += 1\n", + "\n", + " while l2:\n", + " num2 = l2.val\n", + " tmp_num = num2 * (10**digit)\n", + " total_num += tmp_num\n", + " print(f\"num1={num1}, num2={num2}, tmp_num={tmp_num}, total_num={total_num}\")\n", + " l2 = l2.next\n", + " digit += 1\n", + " \n", + " out = ListNode(0,ListNode())\n", + " tmp = out.next\n", + " for i in list(str(total_num))[::-1]:\n", + "# print(i)\n", + " tmp.val = int(i)\n", + " tmp.next = ListNode()\n", + " tmp = tmp.next\n", + " return out.next\n", + "\n", + "\n", + "addTwoNumbers(LN1, LN2) #807" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "num1=2, num2=5, tmp_num=7, total_num=7\n", + "num1=4, num2=6, tmp_num=100, total_num=107\n", + "num1=3, num2=4, tmp_num=700, total_num=807\n", + "num1=3, num2=1, tmp_num=1000, total_num=1807\n" + ] + }, + { + "data": { + "text/plain": [ + "1807" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "addTwoNumbers(LN1, LN3) #1807" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "7\n", + "0\n", + "8\n" + ] + } + ], + "source": [ + "out = ListNode(0,ListNode())\n", + "tmp = out.next\n", + "for i in list(str(807))[::-1]:\n", + " print(i)\n", + "\n", + " tmp.val = i\n", + " tmp.next = ListNode()\n", + " tmp = tmp.next\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'8'" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "out.next.next.next.val" + ] + }, + { + "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.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/.ipynb_checkpoints/Untitled1-checkpoint.ipynb b/.ipynb_checkpoints/Untitled1-checkpoint.ipynb new file mode 100644 index 0000000..2fd6442 --- /dev/null +++ b/.ipynb_checkpoints/Untitled1-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/.ipynb_checkpoints/Untitled2-checkpoint.ipynb b/.ipynb_checkpoints/Untitled2-checkpoint.ipynb new file mode 100644 index 0000000..2fd6442 --- /dev/null +++ b/.ipynb_checkpoints/Untitled2-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/.vscode/.ropeproject/config.py b/.vscode/.ropeproject/config.py new file mode 100644 index 0000000..455b3be --- /dev/null +++ b/.vscode/.ropeproject/config.py @@ -0,0 +1,125 @@ +# The default ``config.py`` +# flake8: noqa + + +def set_prefs(prefs): + """This function is called before opening the project""" + + # Specify which files and folders to ignore in the project. + # Changes to ignored resources are not added to the history and + # VCSs. Also they are not returned in `Project.get_files()`. + # Note that ``?`` and ``*`` match all characters but slashes. + # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc' + # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc' + # '.svn': matches 'pkg/.svn' and all of its children + # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o' + # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o' + prefs["ignored_resources"] = [ + "*.pyc", + "*~", + ".ropeproject", + ".hg", + ".svn", + "_svn", + ".git", + ".tox", + ".venv", + "venv", + ] + + # Specifies which files should be considered python files. It is + # useful when you have scripts inside your project. Only files + # ending with ``.py`` are considered to be python files by + # default. + # prefs['python_files'] = ['*.py'] + + # Custom source folders: By default rope searches the project + # for finding source folders (folders that should be searched + # for finding modules). You can add paths to that list. Note + # that rope guesses project source folders correctly most of the + # time; use this if you have any problems. + # The folders should be relative to project root and use '/' for + # separating folders regardless of the platform rope is running on. + # 'src/my_source_folder' for instance. + # prefs.add('source_folders', 'src') + + # You can extend python path for looking up modules + # prefs.add('python_path', '~/python/') + + # Should rope save object information or not. + prefs["save_objectdb"] = True + prefs["compress_objectdb"] = False + + # If `True`, rope analyzes each module when it is being saved. + prefs["automatic_soa"] = True + # The depth of calls to follow in static object analysis + prefs["soa_followed_calls"] = 0 + + # If `False` when running modules or unit tests "dynamic object + # analysis" is turned off. This makes them much faster. + prefs["perform_doa"] = True + + # Rope can check the validity of its object DB when running. + prefs["validate_objectdb"] = True + + # How many undos to hold? + prefs["max_history_items"] = 32 + + # Shows whether to save history across sessions. + prefs["save_history"] = True + prefs["compress_history"] = False + + # Set the number spaces used for indenting. According to + # :PEP:`8`, it is best to use 4 spaces. Since most of rope's + # unit-tests use 4 spaces it is more reliable, too. + prefs["indent_size"] = 4 + + # Builtin and c-extension modules that are allowed to be imported + # and inspected by rope. + prefs["extension_modules"] = [] + + # Add all standard c-extensions to extension_modules list. + prefs["import_dynload_stdmods"] = True + + # If `True` modules with syntax errors are considered to be empty. + # The default value is `False`; When `False` syntax errors raise + # `rope.base.exceptions.ModuleSyntaxError` exception. + prefs["ignore_syntax_errors"] = False + + # If `True`, rope ignores unresolvable imports. Otherwise, they + # appear in the importing namespace. + prefs["ignore_bad_imports"] = False + + # If `True`, rope will insert new module imports as + # `from import ` by default. + prefs["prefer_module_from_imports"] = False + + # If `True`, rope will transform a comma list of imports into + # multiple separate import statements when organizing + # imports. + prefs["split_imports"] = False + + # If `True`, rope will remove all top-level import statements and + # reinsert them at the top of the module when making changes. + prefs["pull_imports_to_top"] = True + + # If `True`, rope will sort imports alphabetically by module name instead + # of alphabetically by import statement, with from imports after normal + # imports. + prefs["sort_imports_alphabetically"] = False + + # Location of implementation of + # rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general + # case, you don't have to change this value, unless you're an rope expert. + # Change this value to inject you own implementations of interfaces + # listed in module rope.base.oi.type_hinting.providers.interfaces + # For example, you can add you own providers for Django Models, or disable + # the search type-hinting in a class hierarchy, etc. + prefs[ + "type_hinting_factory" + ] = "rope.base.oi.type_hinting.factory.default_type_hinting_factory" + + +def project_opened(project): + """This function is called after opening the project""" + # Do whatever you like here! diff --git a/.vscode/.ropeproject/objectdb b/.vscode/.ropeproject/objectdb new file mode 100644 index 0000000..0a47446 Binary files /dev/null and b/.vscode/.ropeproject/objectdb differ diff --git a/11.Container_with_most_water/11. Container With Most Water.ipynb b/11. Container_with_most_water/11. Container With Most Water.ipynb similarity index 100% rename from 11.Container_with_most_water/11. Container With Most Water.ipynb rename to 11. Container_with_most_water/11. Container With Most Water.ipynb diff --git a/1109-Corporate-flight-booking/main.py b/1109-Corporate-flight-booking/main.py new file mode 100644 index 0000000..9895762 --- /dev/null +++ b/1109-Corporate-flight-booking/main.py @@ -0,0 +1,23 @@ +DEBUG = True + + +def corpFlightBookings(bookings, n): + print("Bookings = ", bookings) + myList = [0] * (n + 2) + for start, end, val in bookings: + myList[start] += val + myList[end + 1] -= val + if DEBUG: + print(f"start = {start}, end = {end}, val = {val}.") + print("myList = ", myList) + if DEBUG: print("finish first stage.") + for i in range(1, n + 2): + myList[i] += myList[i - 1] + if DEBUG: + print("myList = ", myList, end="\n") + return myList[1:-1] + + +# corpFlightBookings([[1, 2, 10], [2, 3, 20], [2, 5, 25]], 5) + +corpFlightBookings([[3, 3, 5], [1, 3, 20], [1, 2, 15]], 3) diff --git a/1155.NumberOfDiceRollsWithTargetSum.py b/1155.NumberOfDiceRollsWithTargetSum.py new file mode 100644 index 0000000..f66c032 --- /dev/null +++ b/1155.NumberOfDiceRollsWithTargetSum.py @@ -0,0 +1,24 @@ +def numRollsToTarget(n: int, k: int, target: int) -> int: + # divid and conquer? -> dp from small to large + # f(n, k, target) = f(n-1, k, targe-1) + f(n-1, k, target-2) + ... + f(n-1, k, target-k) + dp = [[0] * (target + 1) for _ in range(n + 1)] # dp[n][target] + + for row in range(1, n + 1): # number of dices, also row + for i in range(1, target + 1): # target + if row == 1 and i <= k: + dp[row][i] = 1 + elif row == 1 and i > k: + continue + elif row * k < i: # n > 1 + continue + else: + dp[row][i] = sum( + [dp[row - 1][i - cur] for cur in range(1, min(i, k + 1))] + ) + print(dp[row]) + + return dp[n][target] + + +numRollsToTarget(30, 30, 500) + diff --git a/12.Integer_to_Roman/12. Integer to Roman.ipynb b/12. Integer_to_Roman/12. Integer to Roman.ipynb similarity index 100% rename from 12.Integer_to_Roman/12. Integer to Roman.ipynb rename to 12. Integer_to_Roman/12. Integer to Roman.ipynb diff --git a/130.Surrounded Regions.py b/130.Surrounded Regions.py new file mode 100644 index 0000000..28ede37 --- /dev/null +++ b/130.Surrounded Regions.py @@ -0,0 +1,51 @@ +from typing import List + + +def solve(board: List[List[str]]) -> None: + """ + Do not return anything, modify board in-place instead. + """ + # start from any boarder Os, keep them, other wise return + ROWS, COLS = len(board), len(board[0]) + res = [["X" for _ in range(COLS)] for _ in range(ROWS)] + visited = set() + + def dfs(row, col): + if ( + row < 0 + or row == ROWS + or col < 0 + or col == COLS + or board[row][col] == "X" + or (row, col) in visited + ): + return + + visited.add((row, col)) + res[row][col] = "O" + dfs(row + 1, col) + dfs(row - 1, col) + dfs(row, col + 1) + dfs(row, col - 1) + + for col in range(COLS): + dfs(0, col) + dfs(ROWS - 1, col) + + for row in range(ROWS): + dfs(row, 0) + dfs(row, COLS - 1) + + return res + + +tmp = solve( + [ + ["X", "X", "X", "X"], + ["X", "O", "O", "X"], + ["X", "X", "O", "X"], + ["X", "O", "X", "X"], + ] +) + +print(tmp) diff --git a/1305.AllElementsInTwoBinarySearchTrees/Solution.cs b/1305.AllElementsInTwoBinarySearchTrees/Solution.cs new file mode 100644 index 0000000..2b3aace --- /dev/null +++ b/1305.AllElementsInTwoBinarySearchTrees/Solution.cs @@ -0,0 +1,71 @@ +/** +2020-09-07 TAKE AWAY: +Queue doesn't support index; +List kind of doesn't support pop, but there's a way to hack it +(get value and then RemoveAt(0)) + +public void for functions without a return (in place change) +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * public int val; + * public TreeNode left; + * public TreeNode right; + * public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +public class Solution { + public List list1 = new List(); + public List list2 = new List(); + // public Queue list1 = new Queue(); + // public Queue list2 = new Queue(); + public List output = new List(); + + public void inOrder(TreeNode node, List list){ + if (node != null) + { + inOrder(node.left, list); + list.Add(node.val); + inOrder(node.right, list); + } + } + + public IList GetAllElements(TreeNode root1, TreeNode root2) { + inOrder(root1, list1); + inOrder(root2, list2); + + while (list1.Count > 0 && list2.Count > 0) + { + if (list1[0] < list2[0]) + { + output.Add(list1[0]); + list1.RemoveAt(0); + } + else + { + output.Add(list2[0]); + list2.RemoveAt(0); + } + } + + while (list1.Count > 0) + { + output.Add(list1[0]); + list1.RemoveAt(0); + } + while (list2.Count > 0) + { + output.Add(list2[0]); + list2.RemoveAt(0); + } + + return output; + + } +} \ No newline at end of file diff --git a/1365.HowManyNumbersAreSmallerThanTheCurrentNumber/CSharpSoultions.cs b/1365.HowManyNumbersAreSmallerThanTheCurrentNumber/CSharpSoultions.cs new file mode 100644 index 0000000..3123c5c --- /dev/null +++ b/1365.HowManyNumbersAreSmallerThanTheCurrentNumber/CSharpSoultions.cs @@ -0,0 +1,41 @@ +// Merhod 1: Brutal Force +public class Solution { + public int[] SmallerNumbersThanCurrent(int[] nums) { + int[] aaa = new int[nums.Length]; + + for (int i = 0; i < nums.Length; i++) + { + int tmp_count = 0; + foreach (int val in nums.ToList().FindAll(e=>(e < nums[i])).ToList()) + { + tmp_count += 1; + } + aaa[i] = tmp_count; + } + return aaa; + } +} + +// Method 2: sort and use a cache +public class Solution { + public int[] SmallerNumbersThanCurrent(int[] nums) { + int[] aaa = new int[nums.Length]; + Array.Copy(nums, 0, aaa, 0, nums.Length); + Array.Sort(aaa); + + Dictionary store = new Dictionary (); + for (int i = 0; i < aaa.Length; i++) + { + if (store.ContainsKey(aaa[i]) == false) + { + store[aaa[i]] = i; + } + } + + for (int i = 0; i < nums.Length; i++) + { + aaa[i] = store[nums[i]]; + } + return aaa; + } +} \ No newline at end of file diff --git a/1365.HowManyNumbersAreSmallerThanTheCurrentNumber/README.md b/1365.HowManyNumbersAreSmallerThanTheCurrentNumber/README.md new file mode 100644 index 0000000..30b6af4 --- /dev/null +++ b/1365.HowManyNumbersAreSmallerThanTheCurrentNumber/README.md @@ -0,0 +1 @@ +https://leetcode.com/problems/how-many-numbers-are-smaller-than-the-current-number/ diff --git a/139. Word Break.ipynb b/139. Word Break.ipynb new file mode 100644 index 0000000..7540d6f --- /dev/null +++ b/139. Word Break.ipynb @@ -0,0 +1,175 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "i=1; \n", + "dp=[True, False, False, False, False, False, False, False, False]\n", + "w = leet\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=\n", + "w = code\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=\n", + "\n", + "\n", + "i=2; \n", + "dp=[True, False, False, False, False, False, False, False, False]\n", + "w = leet\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=\n", + "w = code\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=\n", + "\n", + "\n", + "i=3; \n", + "dp=[True, False, False, False, False, False, False, False, False]\n", + "w = leet\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=\n", + "w = code\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=\n", + "\n", + "\n", + "i=4; \n", + "dp=[True, False, False, False, False, False, False, False, False]\n", + "w = leet\n", + "len(w)=4, dp[i-len(w)]=True, s[i-len(w):i]=leet\n", + "if triggered, dp = [True, False, False, False, True, False, False, False, False]\n", + "w = code\n", + "len(w)=4, dp[i-len(w)]=True, s[i-len(w):i]=leet\n", + "\n", + "\n", + "i=5; \n", + "dp=[True, False, False, False, True, False, False, False, False]\n", + "w = leet\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=eetc\n", + "w = code\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=eetc\n", + "\n", + "\n", + "i=6; \n", + "dp=[True, False, False, False, True, False, False, False, False]\n", + "w = leet\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=etco\n", + "w = code\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=etco\n", + "\n", + "\n", + "i=7; \n", + "dp=[True, False, False, False, True, False, False, False, False]\n", + "w = leet\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=tcod\n", + "w = code\n", + "len(w)=4, dp[i-len(w)]=False, s[i-len(w):i]=tcod\n", + "\n", + "\n", + "i=8; \n", + "dp=[True, False, False, False, True, False, False, False, False]\n", + "w = leet\n", + "len(w)=4, dp[i-len(w)]=True, s[i-len(w):i]=code\n", + "w = code\n", + "len(w)=4, dp[i-len(w)]=True, s[i-len(w):i]=code\n", + "if triggered, dp = [True, False, False, False, True, False, False, False, True]\n", + "\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def wordBreak(s, wordDict):\n", + " n = len(s)\n", + " dp = [False for i in range(n+1)]\n", + " dp[0] = True\n", + " for i in range(1,n+1):\n", + " print(f\"i={i}; \\ndp={dp}\")\n", + " for w in wordDict:\n", + " print(f\"w = {w}\")\n", + " print(f\"len(w)={len(w)}, dp[i-len(w)]={dp[i-len(w)]}, s[i-len(w):i]={s[i-len(w):i]}\")\n", + " if dp[i-len(w)] and s[i-len(w):i]==w:\n", + " dp[i]=True\n", + " print(f\"if triggered, dp = {dp}\")\n", + " print(\"\\n\")\n", + " return dp[-1]\n", + "\n", + "s = \"leetcode\"\n", + "wordDict = [\"leet\", \"code\"]\n", + "wordBreak(s, wordDict)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'leet'" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s[0:4]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "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.6.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/139.WordBreak.py b/139.WordBreak.py new file mode 100644 index 0000000..df4aadc --- /dev/null +++ b/139.WordBreak.py @@ -0,0 +1,26 @@ +from typing import List + + +class Solution: + def wordBreak(self, s: str, wordDict: List[str]) -> bool: + if len(s) == 0: + return True + + for i in range(len(s) + 1): + if s[:i] in wordDict and self.wordBreak(s[i:], wordDict): + return True + return False + + def wordBreakDp(self, s: str, wordDict: List[str]) -> bool: + n = len(s) + dp = [False for _ in range(n + 1)] + dp[n] = True + + for i in range(n - 1, -1, -1): + for word in wordDict: + if s[i : i + len(word)] == word: + dp[i] = dp[i + len(word)] + return dp[0] + + +Solution().wordBreak("leetcode", ["leet", "code"]) diff --git a/15.3Sum.py b/15.3Sum.py new file mode 100644 index 0000000..caa45cf --- /dev/null +++ b/15.3Sum.py @@ -0,0 +1,35 @@ +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + sortedNums = sorted(nums) + i = 0 + res = [] + + while i < len(sortedNums): + if i > 0 and sortedNums[i] == sortedNums[i - 1]: + i += 1 + continue + qualifiedPairs = self.twoSum(sortedNums[i + 1 :], sortedNums[i]) + if qualifiedPairs: + print(qualifiedPairs) + res.extend(qualifiedPairs) + i += 1 + + return res + + def twoSum(self, sortedNums, target): + l, r = 0, len(sortedNums) - 1 + res = [] + while l < r: + numL = sortedNums[l] + numR = sortedNums[r] + if numL + numR + target == 0: + toAdd = [numL, numR, target] + if toAdd not in res: + res.append(toAdd) + l += 1 + # r -= 1 + if numL + numR + target < 0: + l += 1 + if numL + numR + target > 0: + r -= 1 + return res diff --git a/152.MaximumProductSubarray/Solution.cs b/152.MaximumProductSubarray/Solution.cs new file mode 100644 index 0000000..eaca030 --- /dev/null +++ b/152.MaximumProductSubarray/Solution.cs @@ -0,0 +1,31 @@ +public class Solution { + public int MaxProduct(int[] nums) + { + if (nums.Length == 0){ + return 0; + } + List max_so_far = new List() {nums[0]}; + List min_so_far = new List() {nums[0]}; + + int maximum = nums[0]; + + for (int i = 1; i < nums.Length; i++) + { + int n = nums[i]; + // Console.WriteLine("i = {0}, n = {1}", i, n); + int local_max = new [] {n, n*max_so_far[i-1], n*min_so_far[i-1]}.Max(); + int local_min = new [] {n, n*max_so_far[i-1], n*min_so_far[i-1]}.Min(); + + max_so_far.Add(local_max); + min_so_far.Add(local_min); + + if (local_max > maximum) + { + maximum = local_max; + } + } + + + return maximum; + } +} \ No newline at end of file diff --git a/1567.MaximumLengthOfSubarrayWithPositiveProduct.py b/1567.MaximumLengthOfSubarrayWithPositiveProduct.py new file mode 100644 index 0000000..f512cb9 --- /dev/null +++ b/1567.MaximumLengthOfSubarrayWithPositiveProduct.py @@ -0,0 +1,24 @@ +def getMaxLength(nums): + for i in range(len(nums)): + print(nums[i]) + i += 1 + + +# def getMaxLength(nums): +# pos, neg, ans = 0, 0, 0 +# for n in nums: +# new_pos, new_neg = 0, 0 +# if n > 0: +# new_pos = pos + 1 +# new_neg = neg + 1 if neg > 0 else 0 +# elif n < 0: +# new_pos = neg + 1 if neg > 0 else 0 +# new_neg = pos + 1 + +# pos, neg = new_pos, new_neg +# ans = max(ans, pos) +# print(ans) +# return ans + + +getMaxLength([1, -2, -3, 4, 0, 5, -6, -7, 8, 9]) diff --git a/198.HouseRobber/Solution.py b/198.HouseRobber/Solution.py new file mode 100644 index 0000000..4c32b6c --- /dev/null +++ b/198.HouseRobber/Solution.py @@ -0,0 +1,13 @@ +class Solution: + + def recurssive_rob(self, i, nums): + if i < 0: + return 0 + if i not in self.cache: + self.cache[i] = max(self.recurssive_rob(i-1,nums), self.recurssive_rob(i-2, nums) + nums[i]) + return self.cache[i] + + + def rob(self, nums: List[int]) -> int: + self.cache = {} + return self.recurssive_rob(len(nums)-1, nums) \ No newline at end of file diff --git a/206.Reverse_Linked_List.py b/206.Reverse_Linked_List.py new file mode 100644 index 0000000..4d19121 --- /dev/null +++ b/206.Reverse_Linked_List.py @@ -0,0 +1,51 @@ +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +# Solution 1, iterate with stack +class Solution: + # time: O(2n) -> O(n) + # space: O(n) for stack + def reverseList(self, head: ListNode) -> ListNode: + stack = [] + cur = head + while cur: + stack.append(cur) + cur = cur.next + + out = cur = ListNode() + while stack: + cur.next = stack.pop(-1) + cur = cur.next + cur.next = None + return out.next + +# Solution 2, read once and change along the way +class Solution: + # time: O(n) + # space: O(1) + def reverseList(self, head: ListNode) -> ListNode: + prev = None + cur = head + while cur: + nxt = cur.next + cur.next = prev + prev = cur + cur = nxt + return prev + +# Solution 3, recursive +class Solution: + # time: O(n) + # space: O(n) due to recursive stack, which can go n levels deep + def reverseList(self, head: ListNode) -> ListNode: + if not head or not head.next: + return head # bottom + p = reverseList(head.next) # reverse all the parts after head + head.next.next = head + head.next = None # need it for the last recurisve call to remove the loop + return p + \ No newline at end of file diff --git a/21. Merge Two Sorted Lists.ipynb b/21. Merge Two Sorted Lists.ipynb new file mode 100644 index 0000000..6381aa2 --- /dev/null +++ b/21. Merge Two Sorted Lists.ipynb @@ -0,0 +1,208 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "# Definition for singly-linked list.\n", + "class ListNode(object):\n", + " def __init__(self, val=0, next=None):\n", + " self.val = val\n", + " self.next = next\n", + " \n", + " def __str__(self):\n", + " out = \"Linked List: \"\n", + " cur = self\n", + " while cur.val:\n", + " out += str(cur.val) + \"-> \"\n", + " if cur.next:\n", + " cur = cur.next\n", + " else:\n", + " break\n", + " return out[:-3]\n", + " \n", + " def __repr__(self):\n", + " out = \"Linked List: \"\n", + " cur = self\n", + " while cur.val:\n", + " out += str(cur.val) + \"-> \"\n", + " if cur.next:\n", + " cur = cur.next\n", + " else:\n", + " break\n", + " return out[:-3]" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Linked List: 1-> 2-> 4\n" + ] + } + ], + "source": [ + "l1 = ListNode(1)\n", + "l1.next = ListNode(2, ListNode(4))\n", + "print(l1)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Linked List: 1-> 3-> 4\n" + ] + } + ], + "source": [ + "l2 = ListNode(1, ListNode(3, ListNode(4)))\n", + "print(l2)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Linked List: 1\n", + "case2 Linked List: 1-> 1\n", + "case1 Linked List: 1-> 1-> 2\n", + "case2 Linked List: 1-> 1-> 2-> 3\n", + "case1 Linked List: 1-> 1-> 2-> 3-> 4\n", + "l2 long Linked List: 1-> 1-> 2-> 3-> 4-> 4\n" + ] + }, + { + "data": { + "text/plain": [ + "Linked List: 1-> 1-> 2-> 3-> 4-> 4" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def mergeTwoLists(l1, l2):\n", + " \"\"\"\n", + " :type l1: ListNode\n", + " :type l2: ListNode\n", + " :rtype: ListNode\n", + " \"\"\"\n", + " out = ListNode()\n", + " if l1.val <= l2.val:\n", + " out.val = l1.val\n", + " l1 = l1.next\n", + " else:\n", + " out.val = l2.val\n", + " l2 = l2.next\n", + " print(\"1\", out)\n", + " cur = out\n", + " while l1 and l2:\n", + " if l1.val <= l2.val:\n", + " cur.next = ListNode(l1.val)\n", + " l1 = l1.next\n", + " cur = cur.next\n", + " print(\"case1\", out)\n", + " else:\n", + " cur.next = ListNode(l2.val)\n", + " l2 = l2.next\n", + " cur = cur.next\n", + " print(\"case2\", out)\n", + " if l1:\n", + " cur.next = l1\n", + " print(\"l1 long\", out)\n", + " else:\n", + " cur.next = l2\n", + " print(\"l2 long\", out)\n", + " return out\n", + "mergeTwoLists(l1,l2)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Linked List: 1\n" + ] + }, + { + "data": { + "text/plain": [ + "Linked List: 2-> 4" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [] + }, + { + "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.6.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/22.GeneratePyarentheses.py b/22.GeneratePyarentheses.py new file mode 100644 index 0000000..862b8b3 --- /dev/null +++ b/22.GeneratePyarentheses.py @@ -0,0 +1,23 @@ +def generateParenthesis(n): + res, stack = [], [] + + def backtrack(openN, closeN): + if openN == closeN == n: + res.append("".join(stack)) + return + + if openN < n: + stack.append("(") + backtrack(openN + 1, closeN) + stack.pop() + + if closeN < openN: + stack.append(")") + backtrack(openN, closeN + 1) + stack.pop() + + backtrack(0, 0) + return res + + +generateParenthesis(3) diff --git a/242.Valid_Anagram/242. Valid Anagram.ipynb b/242. Valid_Anagram/242. Valid Anagram.ipynb similarity index 100% rename from 242.Valid_Anagram/242. Valid Anagram.ipynb rename to 242. Valid_Anagram/242. Valid Anagram.ipynb diff --git a/2430.MaximumDeletionsOnString.py b/2430.MaximumDeletionsOnString.py new file mode 100644 index 0000000..f7abaaa --- /dev/null +++ b/2430.MaximumDeletionsOnString.py @@ -0,0 +1,23 @@ +class Solution: + def deleteString(self, s: str) -> int: + if all(x == s[0] for x in s): + return len(s) + + @cache + def dfs(word_index): + length = len(s) - word_index + if length == 1: + return 1 + res = 1 + for i in range(1, length // 2 + 1): + if len(s) - word_index - i + 1 <= res: + break + if ( + s[word_index : word_index + i] + == s[word_index + i : word_index + 2 * i] + ): + res = max(res, 1 + dfs(word_index + i)) + return res + + res = dfs(0) + return res diff --git a/2434.UsingaRobottoPrintTheLexicographicallySmallestString.py b/2434.UsingaRobottoPrintTheLexicographicallySmallestString.py new file mode 100644 index 0000000..969907d --- /dev/null +++ b/2434.UsingaRobottoPrintTheLexicographicallySmallestString.py @@ -0,0 +1,31 @@ +from collections import Counter + + +def robotWithString(s: str) -> str: + res = "" + remain = "" + candidates = list(s) + while len(candidates) > 0: + print(candidates) + minVal = min(candidates) + while remain and remain[-1] <= minVal: + res += remain[-1] + remain = remain[:-1] + last = len(candidates) - 1 - candidates[::-1].index(minVal) + count = Counter(candidates)[minVal] + res += minVal * count + remain += "".join(candidates[:last]).replace(minVal, "") + candidates = candidates[last + 1 :] + # remain = "".join(candidates[first:]).replace(minVal, "") + # candidates = candidates[:first] + # if remain: + # candidates = [remain] + candidates + + # res += "".join(candidates) + res += remain[::-1] + print(res) + + +# robotWithString("zza") +robotWithString("vzhofnpo") +# robotWithString("bac") diff --git a/2458. Height of Binary Tree After Subtree Removal Queries.py b/2458. Height of Binary Tree After Subtree Removal Queries.py new file mode 100644 index 0000000..1ad472b --- /dev/null +++ b/2458. Height of Binary Tree After Subtree Removal Queries.py @@ -0,0 +1,61 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def treeQueries(self, root: Optional[TreeNode], queries: List[int]) -> List[int]: + # idea: mark all the depth, then bfs one time to find the answer -> N + N + + # 1. mark the height of each node + def dfs(node): + if not node: + return 0 + if node.right or node.left: + node.height = max(dfs(node.left), dfs(node.right)) + 1 + if not node.right and not node.left: + node.height = 0 + # print(node, node.height) + return node.height + + dfs(root) + + # 2. bfs and find the ans + ret = [-1] * len(queries) + cache = {} + for num in queries: + cache[num] = 0 + queue = [root] + cur_level = 0 + while queue: + tmp_queue = [] + # while queue: + # tmp_queue.append(queue.pop(0)) + tmp_values = [_.val for _ in tmp_queue] + tmp_heights = [_.height for _ in tmp_queue] + targets = list(set(tmp_values).intersection(queries)) + for target in targets: + # queryId = queries.index(target) + heightId = tmp_values.index(target) + select = [_ for index, _ in enumerate(tmp_heights) if index != heightId] + if select: + queryAns = max(select) + cur_level + else: + queryAns = cur_level - 1 + # print(queryAns, cur_level) + # ret[queryId] = queryAns + cache[target] = queryAns + + cur_level += 1 + + for node in tmp_queue: + if node.left: + queue.append(node.left) + if node.right: + queue.append(node.right) + + # handle query duplicates + for i in range(len(ret)): + ret[i] = cache[queries[i]] + return ret diff --git a/2488. Count Subarrays With Median K.py b/2488. Count Subarrays With Median K.py new file mode 100644 index 0000000..d72b08f --- /dev/null +++ b/2488. Count Subarrays With Median K.py @@ -0,0 +1,72 @@ +from typing import List +import collections + + +def countSubarrays(nums: List[int], k: int) -> int: + n = len(nums) + for i in range(n): + if nums[i] < k: + nums[i] = -1 + elif nums[i] == k: + nums[i] = 0 + else: + nums[i] = 1 + + ret = 0 + presum_odd = collections.defaultdict(int) + presum_even = collections.defaultdict(int) + # presum_even[0] = 1 + presum_odd[0] = 1 + + curPresum = 0 + for i in range(n): + curPresum += nums[i] + if i % 2 == 0: # nums[0:i] is even length + ret += presum_odd[curPresum - 0] + ret += presum_even[curPresum - 1] + presum_even[curPresum] += 1 + else: + ret += presum_odd[curPresum - 1] + ret += presum_even[curPresum - 0] + presum_odd[curPresum] += 1 + return ret + # n = len(nums) + + # for i in range(n): + # if nums[i] > k: + # nums[i] = 1 + # elif nums[i] == k: + # nums[i] = 0 + # else: + # nums[i] = -1 + + # ret = 0 + # presum_even = collections.defaultdict(int) + # presum_odd = collections.defaultdict(int) + + # presum_even[0] = 1 + # s = 0 # s是前缀和 + # for i in range(n): + # s += nums[i] + # if i % 2 == 0: + # ret += presum_even[ + # s - 0 + # ] # 寻找之前所有 长度为偶数 并且前缀和是s的项目,找到的话 nums[that+1:i]的和就是0! + # ret += presum_odd[s - 1] + # presum_odd[s] += 1 + # else: + # ret += presum_even[s - 1] + # ret += presum_odd[s - 0] + # presum_even[s] += 1 + # return ret + + +k = 4 +case1 = [3, 2, 1, 4, 5] +case2 = [2, 3, 1, 2, 3, 1, 5, 2, 4, 4, 10, 2, 3, 1, 11, 22, 1, 9] +case3 = [2, 5, 1, 4, 3, 6] +case4 = [4, 1, 3, 2] + +# countSubarrays(case1, k) +countSubarrays(case4, 1) + diff --git a/290.WordPattern/Solution.py b/290.WordPattern/Solution.py new file mode 100644 index 0000000..daf1301 --- /dev/null +++ b/290.WordPattern/Solution.py @@ -0,0 +1,23 @@ +class Solution: + def wordPattern(self, pattern: str, string: str) -> bool: + # idea: translate both of them into same dictionary mapping + + pattern = list(pattern) + dict1, dict2 = {}, {} + count1, count2 = 0, 0 + trans1, trans2 = "", "" + + for letter in pattern: + if letter not in dict1: + dict1[letter] = count1 + count1 += 1 + trans1 += " " + str(dict1[letter]) + + string = string.split(" ") + for w in string: + if w not in dict2: + dict2[w] = count2 + count2 += 1 + trans2 += " " + str(dict2[w]) + + return trans1 == trans2 \ No newline at end of file diff --git a/303.Range_Sum_Query/303. Range Sum Query - Immutable.ipynb b/303. Range_Sum_Query/303. Range Sum Query - Immutable.ipynb similarity index 100% rename from 303.Range_Sum_Query/303. Range Sum Query - Immutable.ipynb rename to 303. Range_Sum_Query/303. Range Sum Query - Immutable.ipynb diff --git a/304.Range_Sum_Query_2D/304. Range Sum Query 2D - Immutable.ipynb b/304. Range_Sum_Query_2D/304. Range Sum Query 2D - Immutable.ipynb similarity index 100% rename from 304.Range_Sum_Query_2D/304. Range Sum Query 2D - Immutable.ipynb rename to 304. Range_Sum_Query_2D/304. Range Sum Query 2D - Immutable.ipynb diff --git a/34. Find First and Last Position of Element in Sorted Array.py b/34. Find First and Last Position of Element in Sorted Array.py new file mode 100644 index 0000000..f18b4cf --- /dev/null +++ b/34. Find First and Last Position of Element in Sorted Array.py @@ -0,0 +1,69 @@ +class Solution: + def searchRange(self, nums: List[int], target: int) -> List[int]: + def bs_lowerBound(nums, target): # return index + l, r = 0, len(nums) + while l < r: + m = l + (r - l) // 2 + if nums[m] < target: + l = m + 1 + else: + r = m + # print(l) + return l + + def bs_upperBound(nums, target): # not inclusive [l, r) + l, r = 0, len(nums) + while l < r: + m = l + (r - l) // 2 + if nums[m] <= target: + l = m + 1 + else: + r = m + # print(l, r) + return l + + # search to see find + upper = bs_upperBound(nums, target) - 1 + lower = bs_lowerBound(nums, target) + if lower == len(nums): + return [-1, -1] + if nums[lower] != target: + return [-1, -1] + return [lower, upper] + + +def bs_lowerBound(nums, target): # return index + l, r = 0, len(nums) + while l < r: + m = l + (r - l) // 2 + if nums[m] >= target: + r = m + else: + l = m + 1 + print(l) + return l + + +def bs_upperBound(nums, target): # not inclusive [l, r) + l, r = 0, len(nums) + while l < r: + m = l + (r - l) // 2 + if nums[m] > target: + r = m + else: + l = m + 1 + print(l, r) + return l + + +# test +a = [5, 7, 7, 8, 8, 10] +bs_lowerBound(a, 10) +bs_lowerBound(a, 8) +bs_lowerBound([5], 5) +bs_lowerBound(a, 6) + +bs_upperBound(a, 10) +bs_upperBound(a, 8) +bs_upperBound([5], 5) +bs_upperBound(a, 6) diff --git a/4.Median_TwoSortedArrays/4_median_twosortedarrays.py b/4. Median_TwoSortedArrays/4_median_twosortedarrays.py similarity index 100% rename from 4.Median_TwoSortedArrays/4_median_twosortedarrays.py rename to 4. Median_TwoSortedArrays/4_median_twosortedarrays.py diff --git a/402. Remove K Digits.ipynb b/402. Remove K Digits.ipynb new file mode 100644 index 0000000..e3de56d --- /dev/null +++ b/402. Remove K Digits.ipynb @@ -0,0 +1,298 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Problem description\n", + "Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible.\n", + "\n", + "Note:\n", + "The length of num is less than 10002 and will be ≥ k.\n", + "The given num does not contain any leading zero.\n", + "\n", + "Example 1:\n", + "Input: num = \"1432219\", k = 3 \n", + "Output: \"1219\" \n", + "Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest. \n", + "\n", + "Example 2: \n", + "Input: num = \"10200\", k = 1 \n", + "Output: \"200\" \n", + "Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes. \n", + "\n", + "Example 3: \n", + "Input: num = \"10\", k = 2 \n", + "Output: \"0\" \n", + "Explanation: Remove all the digits from the number and it is left with nothing which is 0." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'1219'" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "class Solution(object):\n", + " def removeKdigits(self, num, k):\n", + " \"\"\"\n", + " :type num: str\n", + " :type k: int\n", + " :rtype: str\n", + " \"\"\"\n", + " def remove_1_digit(num):\n", + " nums = list(num)\n", + " for current_index in range(1, len(nums)):\n", + " left_index = current_index - 1\n", + " if nums[left_index] > nums[current_index]:\n", + " return num[:left_index] + num[current_index:]\n", + " return num[:-1]\n", + " for _ in range(k):\n", + " num = remove_1_digit(num)\n", + " return num\n", + " \n", + "\n", + " \n", + "num = \"1432219\"\n", + "k = 3\n", + "Solution.removeKdigits(_, num, k)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'143221'" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "num = \"1432219\"\n", + "num[:-1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[432219, 132219, 142219, 143219, 143219, 143229, 143221]\n", + "132219 2\n", + "[32219, 12219, 13219, 13219, 13229, 13221]\n", + "12219 1\n", + "[2219, 1219, 1219, 1229, 1221]\n", + "1219 0\n" + ] + }, + { + "data": { + "text/plain": [ + "'1219'" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# approach 1, time out brutal.\n", + "\n", + "class Solution(object):\n", + " def removeKdigits(self, num, k):\n", + " \"\"\"\n", + " :type num: str\n", + " :type k: int\n", + " :rtype: str\n", + " \"\"\"\n", + " if k == len(num):\n", + " return \"0\"\n", + " if k == 0:\n", + " return num\n", + " candidate = [int(num[:i]+num[i+1:]) for i in range(len(num))]\n", + " print(candidate)\n", + " print(str(min(candidate)), k-1)\n", + " return Solution.removeKdigits(_, str(min(candidate)), k-1)\n", + " \n", + "num = \"1432219\"\n", + "k = 3\n", + "Solution.removeKdigits(_, num, k)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[200, 1200, 1000, 1020, 1020]\n", + "200 0\n" + ] + }, + { + "data": { + "text/plain": [ + "'200'" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "num = \"10200\"\n", + "k = 1\n", + "Solution.removeKdigits(_, num, k)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'0'" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "num = \"10\"\n", + "k = 2\n", + "Solution.removeKdigits(_, num, k)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[432219, 132219, 142219, 143219, 143219, 143229, 143221]\n" + ] + }, + { + "data": { + "text/plain": [ + "'132219'" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "num = \"1432219\"\n", + "candidate = [int(num[:i]+num[i+1:]) for i in range(len(num))]\n", + "print(candidate)\n", + "str(min(candidate))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "could not convert string to float: ", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfloat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mValueError\u001b[0m: could not convert string to float: " + ] + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "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.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/416. Partition Equal Subset Sum.py b/416. Partition Equal Subset Sum.py new file mode 100644 index 0000000..cbe18c5 --- /dev/null +++ b/416. Partition Equal Subset Sum.py @@ -0,0 +1,44 @@ +from typing import List + + +class Solution: + def canPartition(self, nums: List[int]) -> bool: + if sum(nums) % 2 == 1: + return False + + target = sum(nums) // 2 + ## Let's look into way we can not use list and need set + ## It turns out that: + ## using for seenValue in dp will result an unexpected extended for loop + ## such that each iteration we add a new value to it and it keeps running. + ## What's more, using list instead of set will lead to a memory limit exceed + ## on leetcode + # dp = [0] + # for i, num in enumerate(nums): + # # for seenValue in dp: + # for j in range(len(dp)): + # seenValue = dp[j] + # if seenValue + num == target: + # return True + # dp.append(seenValue + num) + # return False + + # Correct way: using set + dp = set() + dp.add(0) + # for i in range(len(nums)): + for num in nums: + nextDP = set() + for seenValue in dp: + if seenValue + num == target: + return True + nextDP.add(seenValue + num) + nextDP.add(seenValue) + dp = nextDP + return False + + +case1 = [3, 3, 3, 4, 5] # true +case2 = [1, 2, 5] # false +result = Solution().canPartition(case2) +print(result) diff --git a/472.ConcatenatedWords.py b/472.ConcatenatedWords.py new file mode 100644 index 0000000..d1f40fb --- /dev/null +++ b/472.ConcatenatedWords.py @@ -0,0 +1,94 @@ +# class Solution: +# # 1 - need to fix the cache. +# # 2 - lru_cache decorator can only be used on hashable objects (i.e. can't be applied on dict) +# def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]: +# def isValid(word, lookup): +# # print(f"word = {word}") +# # print("cache = ", cache) +# # print() + +# # if word in cache: +# # return cache[word] +# if word in res: +# return True + +# if len(word) == 0: +# return True +# first_letter = word[0] +# for candidate in lookup[first_letter]: +# if candidate == word[: len(candidate)] and isValid( +# word[len(candidate) :], lookup +# ): +# cache[word] = True +# return True +# # cache[word] = False +# return False + +# cache = {} +# from collections import defaultdict + +# lookup = defaultdict(set) +# # form +# for word in words: +# if len(word) == 0: +# continue +# lookup[word[0]].add(word) # key: first letter, value: word + +# res = [] +# for word in words: +# if len(word) == 0: +# continue +# lookup[word[0]].remove(word) +# if isValid(word, lookup): +# res.append(word) +# lookup[word[0]].add(word) +# return res + + +class Solution: + def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]: + cache = {} + from collections import defaultdict + + lookup = defaultdict(set) + + # form + for word in words: + if len(word) == 0: + continue + + if word[0] not in lookup: + lookup[word[0]] = set() + lookup[word[0]].add(word) # key: first letter, value: word + + def isValid(word, lookup): + nonlocal cache + if word in cache: + return cache[word] + + if len(word) == 0: + return True + first_letter = word[0] + for candidate in lookup[first_letter]: + if candidate == word[: len(candidate)] and isValid( + word[len(candidate) :], lookup + ): + cache[word] = True + return True + return False + + res = [] + for word in words: + if len(word) == 0: + continue + lookup[word[0]].remove(word) + if isValid(word, lookup): + res.append(word) + print(f"word = {word}") + print("res = ", res) + print("cache = ", cache) + print() + + lookup[word[0]].add(word) + + return res diff --git a/5.Longest_Palindromic_Substring/5. Longest Palindromic Substring.ipynb b/5. Longest_Palindromic_Substring/5. Longest Palindromic Substring.ipynb similarity index 100% rename from 5.Longest_Palindromic_Substring/5. Longest Palindromic Substring.ipynb rename to 5. Longest_Palindromic_Substring/5. Longest Palindromic Substring.ipynb diff --git a/540. Single Element in a Sorted Array.ipynb b/540. Single Element in a Sorted Array.ipynb new file mode 100644 index 0000000..d692f4e --- /dev/null +++ b/540. Single Element in a Sorted Array.ipynb @@ -0,0 +1,105 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Problem Description\n", + "You are given a sorted array consisting of only integers where every element appears exactly twice, except for one element which appears exactly once. Find this single element that appears only once.\n", + "\n", + " \n", + "\n", + "Example 1: \n", + "Input: [1,1,2,3,3,4,4,8,8] \n", + "Output: 2 \n", + "\n", + "Example 2: \n", + "Input: [3,3,7,7,10,11,11] \n", + "Output: 10 \n", + " \n", + "\n", + "Note: Your solution should run in O(log n) time and O(1) space." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# approach 1, works but not good enough\n", + "class Solution(object):\n", + " def singleNonDuplicate(self, nums):\n", + " \"\"\"\n", + " :type nums: List[int]\n", + " :rtype: int\n", + " \"\"\"\n", + " for index in range(0, len(nums)-1, 2):\n", + " left = nums[index]\n", + " right = nums[index+1]\n", + " if left != right:\n", + " return left\n", + " return nums[-1]\n", + " \n", + "Solution.singleNonDuplicate(_, [3,3,7,7,10,11,11])" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [] + }, + { + "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.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/57.InsertInterval/Solution.cs b/57.InsertInterval/Solution.cs new file mode 100644 index 0000000..264eb36 --- /dev/null +++ b/57.InsertInterval/Solution.cs @@ -0,0 +1,41 @@ +public class Solution { + // Notice this is not the best practical solution + // Shall come back later for better coding + // e.g. use linkedlist + public int[][] Insert(int[][] intervals, int[] newInterval) { + int head = newInterval[0]; + int end = newInterval[1]; + List output = new List(); + + int i = 0; + while (i < intervals.Count()) + { + int cur_head = intervals[i][0], cur_end = intervals[i][1]; + if (head <= cur_end) + { + if (end < cur_head) + { + break; + } + else + { + head = Math.Min(head, cur_head); + end = Math.Max(end, cur_end); + } + } + else + { + output.Add(intervals[i]); + } + i += 1; + } + output.Add(new int[2] {head, end}); + + while (i < intervals.Count()) + { + output.Add(intervals[i]); + i++; + } + return output.ToArray(); + } +} \ No newline at end of file diff --git a/57.InsertInterval/Solution.py b/57.InsertInterval/Solution.py new file mode 100644 index 0000000..2a9c0c3 --- /dev/null +++ b/57.InsertInterval/Solution.py @@ -0,0 +1,29 @@ +class Solution: + def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]: + i = 0 + head, end = newInterval + output = [] + + while i < len(intervals): + cur_head, cur_end = intervals[i] + # we only need to insert one interval + # and the first task is to find where to start + if head <= cur_end: + if end < cur_head: + # easy case, new interval shall be at position 0 + break + else: + # start merging, we will keep doing this + # until the updated end < cur_head + head = min(head, cur_head) + end = max(end, cur_end) + # merge not start yet, append + else: + output.append(intervals[i]) + i += 1 + output.append([head,end]) + output.extend(intervals[i:]) + return output + + + \ No newline at end of file diff --git a/6.ZigZag_Conversion/6. ZigZag Conversion.ipynb b/6. ZigZag_Conversion/6. ZigZag Conversion.ipynb similarity index 100% rename from 6.ZigZag_Conversion/6. ZigZag Conversion.ipynb rename to 6. ZigZag_Conversion/6. ZigZag Conversion.ipynb diff --git a/6265. Count Pairs Of Similar Strings.py b/6265. Count Pairs Of Similar Strings.py new file mode 100644 index 0000000..3587eae --- /dev/null +++ b/6265. Count Pairs Of Similar Strings.py @@ -0,0 +1,372 @@ +import math +from typing import List +from collections import defaultdict + + +# class Solution: +# def similarPairs(self, words: List[str]) -> int: +# # def getUniqueStr(string): +# # unique_str = "" +# # for char in sorted(string): + +# # store = defaultdict(list) +# store = {} + +# for word in words: +# unique_str = "".join(set(sorted(word))) +# if unique_str not in store: +# store[unique_str] = [] +# store[unique_str].append(word) + +# print(len(store)) +# res = 0 +# for value in store.values(): +# res += math.comb(len(value), 2) + +# print(res) +# return res + + +# case1 = [ +# "ofwqemdbhrcckcnqvovyjwnbqxckhfohlripwumugcirazdtwo", +# "hsrmuokwhksqkkjblkomibcifqilkwobwcpwwkjlzohffsajrt", +# "uzvsxxbdwfohaujijxmeijbwyydgjiifcqvxfzmkqgwnkpxlpp", +# "ksdoiwhffhymsxebloadgyigkveizbahnbmvmxsuuxaaegxmpe", +# "fcsjnezuizcnfsuaxpmxpdivamaijvvyyqlsjsqlkifahjuanb", +# "odfwurhxumkpwndsppoflaualeghyscdqqwpntxokxviqmjhyq", +# "jbahicbweamnlfbljwyloparlmgqlwiootzoeqovytpapzjezn", +# "vsjxngyknxpkjfexdvmoikjaiccplcwtxcfrljqavatpcoeaqe", +# "lxiztvpppvsjmnnuunvdxalvzuvxlxbdnipexklmgsssyzlesb", +# "kbmiambdsahiptndziqysctinvdekysrsslssusqwhshpwehco", +# "wuwkvgrrshrmbtpyozgzzwiyflpiuklsepljvthmxnppaspuqt", +# "lkajvmdzpsxoaqzrgrhuhhmwlgwfnruxsrjolnielwcyjvvhaa", +# "imvgnslsxyqfshgmgecdrignarewusftipgjpteocnlqsfkdcy", +# ] + +# case2 = [ +# "abcdefghijklmnopqrtuvwxyz", +# "abcdefghijklmnopqsuvwxyz", +# "abcdefhijklmnpqsuvxyz", +# "abcdehiklmnopqrstuvwyz", +# "abcefghijlmnopqrtvwyz", +# "abcfhijklmopqrstuwz", +# "abdefghiklmnopsuvwxyz", +# "abdegijklmnpstuvxyz", +# "abefghijklmnopqrstuvwxyz", +# "acdefghijklmnopqrstuvwxy", +# "acdefghijklmnopqrstuvwxy", +# "acdefghijklmnopqrsuvwxyz", +# "acdefgijklmnopqrstvwxy", +# ] +# Solution().similarPairs(case1) + +## P2 +# def largest_prime_factor(n): +# i = 2 +# while i * i <= n: +# if n % i: +# i += 1 +# else: +# n //= i +# return n + + +# def primeConvert(value): +# if value <= 4: +# return value + +# # check is prime +# if largest_prime_factor(value) == value: +# return value + +# primeDivident = largest_prime_factor(value) +# res = primeDivident +# reminder = value // primeDivident +# while largest_prime_factor(reminder) != reminder: +# primeDivident = largest_prime_factor(reminder) +# reminder = reminder // primeDivident +# res += primeDivident +# res += reminder +# print(res) +# return res + + +# primeConvert(12) + +## P3 +# edges = [[1, 2], [2, 3], [3, 4], [4, 2], [1, 4], [2, 5]] +# edges = [[1, 2], [3, 4]] +# edges = [[1, 2], [1, 3], [1, 4]] + + +def isPossible(n: int, edges: List[List[int]]) -> bool: + graph = defaultdict(list) + for a, b in edges: + graph[a].append(b) + graph[b].append(a) + + oddNodes = [] + for node in graph: + if len(graph[node]) % 2 == 1: + oddNodes.append(node) + + if len(oddNodes) == 0: + return True + + if len(oddNodes) > 4 or len(oddNodes) == 1: + return False + + if len(oddNodes) == 2: + # direct connect + if oddNodes[0] not in graph[oddNodes[1]]: + return True + # or link via the third common non-connected node + one, two = oddNodes + # for i in range(1, n + 1): + # if i != one and i != two: + # if i not in graph[one] and i not in graph[two]: + # return True + ## to speed up + candidate = set([_ for _ in range(1, n + 1)]) + candidate = candidate.difference(set(graph[one]), set(graph[two])) + for i in candidate: + if i not in graph[one] and i not in graph[two]: + return True + return False + + if len(oddNodes) == 3: + # # we will need two addable edges with 3 possibilities: 12, 23, 13 + # one, two, three = oddNodes + # possible_links = ( + # (one not in graph[two]) + # + (two not in graph[three]) + # + (one not in graph[three]) + # ) + # return possible_links >= 2 + return False + + if len(oddNodes) == 4: + one, two, three, four = oddNodes + # we will need two addable edges with 6 possibilities: 12, 23, 13 + return ( + ((one not in graph[two]) and (three not in graph[four])) + or ((one not in graph[three]) and (two not in graph[four])) + or ((one not in graph[four]) and (two not in graph[three])) + ) + + +# 1. +# print(isPossible(4, edges=edges)) + +n = 21 +edges = [ + [2, 19], + [16, 17], + [8, 14], + [2, 16], + [12, 20], + [12, 14], + [16, 18], + [15, 16], + [10, 21], + [3, 5], + [13, 18], + [17, 20], + [14, 17], + [9, 12], + [5, 15], + [5, 6], + [3, 7], + [2, 21], + [10, 13], + [8, 16], + [7, 18], + [4, 6], + [9, 1], + [13, 21], + [18, 20], + [7, 14], + [4, 19], + [5, 8], + [3, 11], + [11, 1], + [7, 12], + [4, 7], + [3, 16], + [13, 17], + [17, 19], + [9, 13], + [7, 19], + [10, 16], + [4, 13], + [4, 5], + [2, 15], + [12, 19], + [11, 16], + [2, 9], + [11, 17], + [17, 1], + [16, 21], + [4, 10], + [10, 14], + [14, 16], + [4, 1], + [13, 20], + [5, 20], + [4, 14], + [4, 21], + [10, 20], + [2, 14], + [8, 15], + [4, 8], + [6, 19], + [15, 1], + [19, 1], + [8, 19], + [15, 21], + [3, 12], + [11, 18], + [9, 17], + [18, 19], + [7, 21], + [3, 21], + [16, 19], + [11, 15], + [5, 1], + [8, 17], + [3, 15], + [8, 1], + [10, 19], + [3, 8], + [6, 16], + [2, 8], + [5, 18], + [11, 13], + [11, 20], + [14, 21], + [6, 20], + [4, 20], + [12, 13], + [5, 12], + [10, 11], + [9, 15], + [3, 19], + [9, 20], + [14, 18], + [21, 1], + [13, 19], + [8, 21], + [2, 13], + [3, 10], + [9, 18], + [19, 21], + [6, 7], + [3, 18], + [2, 18], + [6, 14], + [3, 17], + [5, 21], + [14, 20], + [8, 9], + [16, 1], + [3, 4], + [13, 1], + [5, 9], + [4, 15], + [17, 21], + [20, 21], + [2, 17], + [13, 14], + [11, 14], + [9, 16], + [10, 18], + [6, 15], + [6, 12], + [3, 13], + [5, 11], + [6, 1], + [12, 17], + [8, 10], + [5, 10], + [8, 18], + [4, 12], + [10, 1], + [6, 13], + [4, 18], + [7, 20], + [7, 16], + [2, 6], + [12, 21], + [4, 17], + [15, 18], + [13, 16], + [15, 20], + [7, 10], + [6, 10], + [2, 20], + [7, 15], + [18, 1], + [12, 1], + [3, 20], + [7, 1], + [14, 15], + [4, 9], + [11, 19], + [7, 9], + [5, 17], + [18, 21], + [6, 21], + [8, 11], + [6, 17], + [3, 14], + [7, 11], + [5, 7], + [7, 13], + [6, 8], + [6, 9], + [10, 12], + [5, 16], + [2, 4], + [17, 18], + [9, 11], + [12, 16], + [3, 6], + [12, 18], + [3, 9], + [11, 12], + [14, 19], + [10, 15], + [5, 13], + [8, 13], + [15, 17], + [2, 10], + [11, 21], + [20, 1], + [6, 18], + [2, 12], + [19, 20], + [6, 11], + [8, 12], + [2, 3], + [12, 15], + [2, 11], + [9, 10], + [7, 17], + [9, 19], + [13, 15], + [7, 8], + [4, 11], + [2, 5], + [5, 19], + [16, 20], + [15, 19], + [9, 14], + [14, 1], + [10, 17], + [9, 21], + [2, 7], + [8, 20], + [5, 14], + [4, 16], +] +print(isPossible(n, edges=edges)) diff --git a/7. Reverse_integer/.ipynb_checkpoints/debug_testing-checkpoint.ipynb b/7. Reverse_integer/.ipynb_checkpoints/debug_testing-checkpoint.ipynb new file mode 100644 index 0000000..2fd6442 --- /dev/null +++ b/7. Reverse_integer/.ipynb_checkpoints/debug_testing-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/7.Reverse_integer/README.md b/7. Reverse_integer/README.md similarity index 100% rename from 7.Reverse_integer/README.md rename to 7. Reverse_integer/README.md diff --git a/7.Reverse_integer/Reverse_Integer.py b/7. Reverse_integer/Reverse_Integer.py similarity index 100% rename from 7.Reverse_integer/Reverse_Integer.py rename to 7. Reverse_integer/Reverse_Integer.py diff --git a/7.Reverse_integer/__init__.py b/7. Reverse_integer/__init__.py similarity index 100% rename from 7.Reverse_integer/__init__.py rename to 7. Reverse_integer/__init__.py diff --git a/7.Reverse_integer/debug_testing.ipynb b/7. Reverse_integer/debug_testing.ipynb similarity index 100% rename from 7.Reverse_integer/debug_testing.ipynb rename to 7. Reverse_integer/debug_testing.ipynb diff --git a/7.Reverse_integer/test_Reverse_integer.py b/7. Reverse_integer/test_Reverse_integer.py similarity index 100% rename from 7.Reverse_integer/test_Reverse_integer.py rename to 7. Reverse_integer/test_Reverse_integer.py diff --git a/787.CheapestFlightsWithinKStops.py b/787.CheapestFlightsWithinKStops.py new file mode 100644 index 0000000..673736a --- /dev/null +++ b/787.CheapestFlightsWithinKStops.py @@ -0,0 +1,144 @@ +import math +from typing import List + + +#failed +class Solution: + def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int: + # dfs with early stop (k) + # build graph + adj = {i: [] for i in range(n)} + for from_i, to_i, price_i in flights: + adj[from_i].append((to_i, price_i)) + + ret = math.inf + cache = {} + path = [] + + def dfs(node, priceSoFar, stepSoFar, pathSoFar): + nonlocal path + if node == dst and stepSoFar <= k: + path.append((priceSoFar, pathSoFar)) + return priceSoFar + if stepSoFar > k: + return math.inf + if (node, stepSoFar) in cache: + # print(node, stepSoFar, cache[(node, stepSoFar)]) + return cache[(node, stepSoFar)] + + ans = math.inf + for to_i, price_i in adj[node]: + ans = min(ans, dfs(to_i, priceSoFar+price_i, stepSoFar+1, pathSoFar + "-" + str(to_i))) + cache[(node, stepSoFar)] = ans + # print(path) + return ans + + ret = dfs(src, 0, -1, str(src)) + print(path) + return ret if ret != math.inf else -1 + + + + +print("solution1") +testFLights = [[10, 14, 43], [1, 12, 62], [4, 2, 62], [14, 10, 49], [9, 5, 29], [13, 7, 53], [4, 12, 90], [14, 9, 38], [11, 2, 64], [2, 13, 92], [11, 5, 42], [10, 1, 89], [14, 0, 32], [9, 4, 81], [3, 6, 97], [7, 13, 35], [11, 9, 63], [5, 7, 82], [13, 6, 57], [4, 5, 100], [2, 9, 34], [11, 13, 1], [14, 8, 1], [12, 10, 42], [2, 4, 41], [0, 6, 55], [ + 5, 12, 1], [13, 3, 67], [3, 13, 36], [3, 12, 73], [7, 5, 72], [5, 6, 100], [7, 6, 52], [4, 7, 43], [6, 3, 67], [3, 1, 66], [8, 12, 30], [8, 3, 42], [9, 3, 57], [12, 6, 31], [2, 7, 10], [14, 4, 91], [2, 3, 29], [8, 9, 29], [2, 11, 65], [3, 8, 49], [6, 14, 22], [4, 6, 38], [13, 0, 78], [1, 10, 97], [8, 14, 40], [7, 9, 3], [14, 6, 4], [4, 8, 75], [1, 6, 56]] +Solution().findCheapestPrice(n=15, flights=testFLights, src=1, dst=4, k=10) # expected: 169 + + +#case 1 +# testFLights = [[0,1,100],[1,2,100],[2,0,100],[1,3,600],[2,3,200]] +# Solution().findCheapestPrice(n=4, flights=testFLights, src=0, dst=3, k=1) # expected: 700 +# print() +# Solution().findCheapestPrice(n=4, flights=testFLights, src=0, dst=3, k=2) # expected: 400 + +# passed +class Solution: + def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int: + # dfs with early stop (k) + # build graph + adj = {i: [] for i in range(n)} + for from_i, to_i, price_i in flights: + adj[from_i].append((to_i, price_i)) + + ret = math.inf + cache = {} + path = [] + def dfs(node, priceSoFar, stepSoFar, pathSoFar): + nonlocal path + if node == dst and stepSoFar <= k: + path.append((priceSoFar, pathSoFar)) + return 0 + if stepSoFar > k: + return math.inf + if (node, stepSoFar) in cache: + # print(node, stepSoFar, cache[(node, stepSoFar)]) + return cache[(node, stepSoFar)][0] + + ans = math.inf + for to_i, price_i in adj[node]: + # ans = min(ans, dfs(to_i, priceSoFar+price_i, stepSoFar+1)) + ans = dfs(to_i, priceSoFar, stepSoFar+1, pathSoFar + "-" + str(to_i)) + price_i + + cache[(node, stepSoFar)] = [ans, pathSoFar+"-"+str(to_i)] + # print(cache) + # print(path) + return ans + + ret = dfs(src, 0, -1, str(src)) + print(path) + return ret if ret != math.inf else -1 + +print("solution2") +testFLights = [[10, 14, 43], [1, 12, 62], [4, 2, 62], [14, 10, 49], [9, 5, 29], [13, 7, 53], [4, 12, 90], [14, 9, 38], [11, 2, 64], [2, 13, 92], [11, 5, 42], [10, 1, 89], [14, 0, 32], [9, 4, 81], [3, 6, 97], [7, 13, 35], [11, 9, 63], [5, 7, 82], [13, 6, 57], [4, 5, 100], [2, 9, 34], [11, 13, 1], [14, 8, 1], [12, 10, 42], [2, 4, 41], [0, 6, 55], [ + 5, 12, 1], [13, 3, 67], [3, 13, 36], [3, 12, 73], [7, 5, 72], [5, 6, 100], [7, 6, 52], [4, 7, 43], [6, 3, 67], [3, 1, 66], [8, 12, 30], [8, 3, 42], [9, 3, 57], [12, 6, 31], [2, 7, 10], [14, 4, 91], [2, 3, 29], [8, 9, 29], [2, 11, 65], [3, 8, 49], [6, 14, 22], [4, 6, 38], [13, 0, 78], [1, 10, 97], [8, 14, 40], [7, 9, 3], [14, 6, 4], [4, 8, 75], [1, 6, 56]] +Solution().findCheapestPrice(n=15, flights=testFLights, src=1, dst=4, k=10) # expected: 169 + +print() + +# visualization +import matplotlib.pyplot as plt +import networkx as nx + +G = nx.DiGraph() + +for source, destination, weight in testFLights: + G.add_edge(str(source), str(destination), weight=weight) + +elarge = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] > 0.5] +esmall = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] <= 0.5] + +pos = nx.spring_layout(G, seed=1) # positions for all nodes - seed for reproducibility + +# nodes +nx.draw_networkx_nodes(G, pos, node_size=700) + +# edges +# nx.draw_networkx_edges(G, pos, edgelist=elarge, width=4, arrowstyle="->", arrowsize=10) +nx.draw_networkx_edges(G, pos, node_size=300, width=4, arrowstyle="->", arrowsize=10) +# nx.draw_networkx_edges( +# G, pos, edgelist=esmall, width=4, alpha=0.5, edge_color="b", style="dashed" +# ) +# edges = nx.draw_networkx_edges( +# G, +# pos, +# node_size=node_sizes, +# arrowstyle="->", +# arrowsize=10, +# edge_color=edge_colors, +# edge_cmap=cmap, +# width=2, +# ) + + +# node labels +nx.draw_networkx_labels(G, pos, font_size=20, font_family="sans-serif") +# edge weight labels +edge_labels = nx.get_edge_attributes(G, "weight") +nx.draw_networkx_edge_labels(G, pos, edge_labels) + +ax = plt.gca() +ax.margins(0.08) +plt.axis("off") +plt.tight_layout() +plt.show() \ No newline at end of file diff --git a/79.WordSearch.py b/79.WordSearch.py new file mode 100644 index 0000000..7fe1061 --- /dev/null +++ b/79.WordSearch.py @@ -0,0 +1,76 @@ +""" +Sep 29 2022: +The most challenging part here is to mark the 'seen' elements. +I initially tried to do it was a set, but that passing the set +around is messy and TLE on LC. +Another way here is to modify the graph/board on the fly, and +here is an important backtracking technique! +1. you first check boundary condition (row, col, etc.) +2. check True condition (element == ) +3. visit the current node (modify) +4. use a for-loop to dfs +5. outside of the for-loop, convert the modified back +(so it doesn't affect other nodes' searchs) + +This convert back mechanism is interesting and totally new to me! +""" +import numpy as np + + +class Solution: + def exist(self, board, word): + """ + :type board: List[List[str]] + :type word: str + :rtype: bool + """ + self.ROWS = len(board) + self.COLS = len(board[0]) + self.board = board + + for row in range(self.ROWS): + for col in range(self.COLS): + if self.backtrack(row, col, word): + return True + + # no match found after all exploration + return False + + def backtrack(self, row, col, suffix): + # bottom case: we find match for each letter in the word + if len(suffix) == 0: + return True + + # Check the current status, before jumping into backtracking + if ( + row < 0 + or row == self.ROWS + or col < 0 + or col == self.COLS + or self.board[row][col] != suffix[0] + ): + return False + + ret = False + # mark the choice before exploring further. + self.board[row][col] = "#" + print(np.matrix(self.board)) + print() + # explore the 4 neighbor directions + for rowOffset, colOffset in [(0, 1), (1, 0), (0, -1), (-1, 0)]: + ret = self.backtrack(row + rowOffset, col + colOffset, suffix[1:]) + # break instead of return directly to do some cleanup afterwards + if ret: + break + + # revert the change, a clean slate and no side-effect + self.board[row][col] = suffix[0] + + # Tried all directions, and did not find any match + return ret + + +a = [["A", "B", "C", "E"], ["S", "F", "E", "S"], ["A", "E", "E", "E"]] +word = "FEEEC" +res = Solution().exist(board=a, word=word) +print(res) diff --git a/8.String2Integer/.ipynb_checkpoints/8. String to Integer-checkpoint.ipynb b/8. String2Integer/.ipynb_checkpoints/8. String to Integer-checkpoint.ipynb similarity index 100% rename from 8.String2Integer/.ipynb_checkpoints/8. String to Integer-checkpoint.ipynb rename to 8. String2Integer/.ipynb_checkpoints/8. String to Integer-checkpoint.ipynb diff --git a/8.String2Integer/8. String to Integer.ipynb b/8. String2Integer/8. String to Integer.ipynb similarity index 100% rename from 8.String2Integer/8. String to Integer.ipynb rename to 8. String2Integer/8. String to Integer.ipynb diff --git a/8.String2Integer/README.md b/8. String2Integer/README.md similarity index 100% rename from 8.String2Integer/README.md rename to 8. String2Integer/README.md diff --git a/807. Max Increase to Keep City Skyline/.ipynb_checkpoints/Max_Increase_to_Keep_City_Skyline-checkpoint.ipynb b/807. Max Increase to Keep City Skyline/.ipynb_checkpoints/Max_Increase_to_Keep_City_Skyline-checkpoint.ipynb new file mode 100644 index 0000000..379d235 --- /dev/null +++ b/807. Max Increase to Keep City Skyline/.ipynb_checkpoints/Max_Increase_to_Keep_City_Skyline-checkpoint.ipynb @@ -0,0 +1,396 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python 3.7.1\r\n" + ] + } + ], + "source": [ + "!python --version" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nIn a 2 dimensional array grid, each value grid[i][j] represents the \\nheight of a building located there. We are allowed to increase the \\nheight of any number of buildings, by any amount (the amounts can be \\ndifferent for different buildings). Height 0 is considered to be a \\nbuilding as well. \\n\\nAt the end, the \"skyline\" when viewed from all four directions of \\nthe grid, i.e. top, bottom, left, and right, must be the same as \\nthe skyline of the original grid. A city\\'s skyline is the outer \\ncontour of the rectangles formed by all the buildings when viewed \\nfrom a distance. See the following example.\\n\\nWhat is the maximum total sum that the height of the buildings can \\nbe increased?\\n\\n\\nExample:\\nInput: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]\\nOutput: 35\\nExplanation: \\nThe grid is:\\n[ [3, 0, 8, 4], \\n [2, 4, 5, 7],\\n [9, 2, 6, 3],\\n [0, 3, 1, 0] ]\\n\\nThe skyline viewed from top or bottom is: [9, 4, 8, 7]\\nThe skyline viewed from left or right is: [8, 7, 9, 3]\\n\\nThe grid after increasing the height of buildings without affecting skylines is:\\n\\ngridNew = [ [8, 4, 8, 7],\\n [7, 4, 7, 7],\\n [9, 4, 8, 7],\\n [3, 3, 3, 3] ]\\n\\nlink:\\nhttps://leetcode.com/problems/max-increase-to-keep-city-skyline/\\n'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "In a 2 dimensional array grid, each value grid[i][j] represents the \n", + "height of a building located there. We are allowed to increase the \n", + "height of any number of buildings, by any amount (the amounts can be \n", + "different for different buildings). Height 0 is considered to be a \n", + "building as well. \n", + "\n", + "At the end, the \"skyline\" when viewed from all four directions of \n", + "the grid, i.e. top, bottom, left, and right, must be the same as \n", + "the skyline of the original grid. A city's skyline is the outer \n", + "contour of the rectangles formed by all the buildings when viewed \n", + "from a distance. See the following example.\n", + "\n", + "What is the maximum total sum that the height of the buildings can \n", + "be increased?\n", + "\n", + "\n", + "Example:\n", + "Input: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]\n", + "Output: 35\n", + "Explanation: \n", + "The grid is:\n", + "[ [3, 0, 8, 4], \n", + " [2, 4, 5, 7],\n", + " [9, 2, 6, 3],\n", + " [0, 3, 1, 0] ]\n", + "\n", + "The skyline viewed from top or bottom is: [9, 4, 8, 7]\n", + "The skyline viewed from left or right is: [8, 7, 9, 3]\n", + "\n", + "The grid after increasing the height of buildings without affecting skylines is:\n", + "\n", + "gridNew = [ [8, 4, 8, 7],\n", + " [7, 4, 7, 7],\n", + " [9, 4, 8, 7],\n", + " [3, 3, 3, 3] ]\n", + "\n", + "link:\n", + "https://leetcode.com/problems/max-increase-to-keep-city-skyline/\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Solution 1\n", + "The idea is straight forward, height of each cell is bounded by two conditions: (max in the row, max in the col). \n", + "The challenge will be, how to find and fill it efficiently. \n", + "The first solution here, we use brutal force to begin with." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[9, 4, 8, 7]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# def maxIncreaseKeepingSkyline(grid):\n", + "grid = [ [3, 0, 8, 4], \n", + " [2, 4, 5, 7],\n", + " [9, 2, 6, 3],\n", + " [0, 3, 1, 0] ]\n", + "total_init = sum([sum(content) for content in grid])\n", + "max_col = [0] * len(grid)\n", + "# iterate through colum, bcz max(list) is easy to call\n", + "for col in range(len(grid)):\n", + " for row in range(len(grid)):\n", + " if grid[row][col] > max_col[col]:\n", + " max_col[col] = grid[row][col]\n", + "\n", + "max_col" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "gridNew = grid[:]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[3, 0, 8, 4], [2, 4, 5, 7], [9, 2, 6, 3], [0, 3, 1, 0]]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gridNew2 = grid.copy() # notice that [[0]*4]*4 will give error at the end\n", + "gridNew2" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 0 9 8 8\n", + "0 1 4 8 4\n", + "0 2 8 8 8\n", + "0 3 7 8 7\n", + "1 0 9 7 7\n", + "1 1 4 7 4\n", + "1 2 8 7 7\n", + "1 3 7 7 7\n", + "2 0 9 9 9\n", + "2 1 4 9 4\n", + "2 2 8 9 8\n", + "2 3 7 9 7\n", + "3 0 9 3 3\n", + "3 1 4 3 3\n", + "3 2 8 3 3\n", + "3 3 7 3 3\n" + ] + }, + { + "data": { + "text/plain": [ + "[[8, 4, 8, 7], [7, 4, 7, 7], [9, 4, 8, 7], [3, 3, 3, 3]]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "for row in range(len(grid)):\n", + " for col in range(len(grid)):\n", + " # new grid is bounded by max in col and max in row\n", + " gridNew[row][col] = min(max_col[col], max(grid[row]))\n", + " print(row, col, max_col[col], max(grid[row]), gridNew[row][col]) \n", + " \n", + "gridNew" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[8, 4, 8, 7], [7, 4, 7, 7], [9, 4, 8, 7], [3, 3, 3, 3]]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "grid # well.. due to the python copy problem..you will need deepcopy to \n", + " # generate a new copy with brand new pointer...\n", + " # ref: https://stackoverflow.com/questions/13783315/sum-of-list-of-lists-returns-sum-list\n", + " # a easier way here is to calculate total_init at the begining." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "57 92\n" + ] + }, + { + "data": { + "text/plain": [ + "35" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total_new = sum([sum(content) for content in gridNew])\n", + "print(total_init, total_new)\n", + "total_increase = total_new - total_init\n", + "total_increase" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "# put into a function:\n", + "class Solution(object):\n", + " def maxIncreaseKeepingSkyline(self, grid):\n", + " \"\"\"\n", + " :type grid: List[List[int]]\n", + " :rtype: int\n", + " \"\"\"\n", + " total_init = sum([sum(content) for content in grid])\n", + " max_col = [0] * len(grid)\n", + " # iterate through colum, bcz max(list) is easy to call\n", + " for col in range(len(grid)):\n", + " for row in range(len(grid)):\n", + " if grid[row][col] > max_col[col]:\n", + " max_col[col] = grid[row][col]\n", + " \n", + " gridNew = grid[:]\n", + " for row in range(len(grid)):\n", + " for col in range(len(grid)):\n", + " # new grid is bounded by max in col and max in row\n", + " gridNew[row][col] = min(max_col[col], max(grid[row]))\n", + " \n", + " total_new = sum([sum(content) for content in gridNew])\n", + " total_increase = total_new - total_init \n", + " return total_increase\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "35" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "grid = [ [3, 0, 8, 4], \n", + " [2, 4, 5, 7],\n", + " [9, 2, 6, 3],\n", + " [0, 3, 1, 0] ]\n", + "\n", + "Solution().maxIncreaseKeepingSkyline(grid)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "35" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# note:\n", + "# there are many place we can improve from this brutal approach,\n", + "# for example, we don't really need to create the girdNew, but \n", + "# instead, we only need to accumulate the difference between\n", + "# (height at current cell, possible max height). \n", + "# e.g. we know the possible max height at cell(0,0) is \n", + "# min(9, 8) = 8. So the difference = 8-3 = 5\n", + "# this will save both time and space, and it won't modify the original\n", + "# grid input.\n", + "\n", + "class Solution2(object):\n", + " def maxIncreaseKeepingSkyline(self, grid):\n", + " \"\"\"\n", + " :type grid: List[List[int]]\n", + " :rtype: int\n", + " \"\"\"\n", + " total_init = sum([sum(content) for content in grid])\n", + " max_col = [0] * len(grid)\n", + " # iterate through colum, bcz max(list) is easy to call\n", + " for col in range(len(grid)):\n", + " for row in range(len(grid)):\n", + " if grid[row][col] > max_col[col]:\n", + " max_col[col] = grid[row][col]\n", + " \n", + " output = 0\n", + " for row in range(len(grid)):\n", + " for col in range(len(grid)):\n", + " possible_local_max = min(max_col[col], max(grid[row]))\n", + " output += possible_local_max - grid[row][col]\n", + " \n", + " return output\n", + " \n", + "grid = [ [3, 0, 8, 4], \n", + " [2, 4, 5, 7],\n", + " [9, 2, 6, 3],\n", + " [0, 3, 1, 0] ]\n", + "Solution2().maxIncreaseKeepingSkyline(grid)" + ] + }, + { + "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.6.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/807. Max Increase to Keep City Skyline/Max_Increase_to_Keep_City_Skyline.ipynb b/807. Max Increase to Keep City Skyline/Max_Increase_to_Keep_City_Skyline.ipynb new file mode 100644 index 0000000..379d235 --- /dev/null +++ b/807. Max Increase to Keep City Skyline/Max_Increase_to_Keep_City_Skyline.ipynb @@ -0,0 +1,396 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python 3.7.1\r\n" + ] + } + ], + "source": [ + "!python --version" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nIn a 2 dimensional array grid, each value grid[i][j] represents the \\nheight of a building located there. We are allowed to increase the \\nheight of any number of buildings, by any amount (the amounts can be \\ndifferent for different buildings). Height 0 is considered to be a \\nbuilding as well. \\n\\nAt the end, the \"skyline\" when viewed from all four directions of \\nthe grid, i.e. top, bottom, left, and right, must be the same as \\nthe skyline of the original grid. A city\\'s skyline is the outer \\ncontour of the rectangles formed by all the buildings when viewed \\nfrom a distance. See the following example.\\n\\nWhat is the maximum total sum that the height of the buildings can \\nbe increased?\\n\\n\\nExample:\\nInput: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]\\nOutput: 35\\nExplanation: \\nThe grid is:\\n[ [3, 0, 8, 4], \\n [2, 4, 5, 7],\\n [9, 2, 6, 3],\\n [0, 3, 1, 0] ]\\n\\nThe skyline viewed from top or bottom is: [9, 4, 8, 7]\\nThe skyline viewed from left or right is: [8, 7, 9, 3]\\n\\nThe grid after increasing the height of buildings without affecting skylines is:\\n\\ngridNew = [ [8, 4, 8, 7],\\n [7, 4, 7, 7],\\n [9, 4, 8, 7],\\n [3, 3, 3, 3] ]\\n\\nlink:\\nhttps://leetcode.com/problems/max-increase-to-keep-city-skyline/\\n'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "In a 2 dimensional array grid, each value grid[i][j] represents the \n", + "height of a building located there. We are allowed to increase the \n", + "height of any number of buildings, by any amount (the amounts can be \n", + "different for different buildings). Height 0 is considered to be a \n", + "building as well. \n", + "\n", + "At the end, the \"skyline\" when viewed from all four directions of \n", + "the grid, i.e. top, bottom, left, and right, must be the same as \n", + "the skyline of the original grid. A city's skyline is the outer \n", + "contour of the rectangles formed by all the buildings when viewed \n", + "from a distance. See the following example.\n", + "\n", + "What is the maximum total sum that the height of the buildings can \n", + "be increased?\n", + "\n", + "\n", + "Example:\n", + "Input: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]\n", + "Output: 35\n", + "Explanation: \n", + "The grid is:\n", + "[ [3, 0, 8, 4], \n", + " [2, 4, 5, 7],\n", + " [9, 2, 6, 3],\n", + " [0, 3, 1, 0] ]\n", + "\n", + "The skyline viewed from top or bottom is: [9, 4, 8, 7]\n", + "The skyline viewed from left or right is: [8, 7, 9, 3]\n", + "\n", + "The grid after increasing the height of buildings without affecting skylines is:\n", + "\n", + "gridNew = [ [8, 4, 8, 7],\n", + " [7, 4, 7, 7],\n", + " [9, 4, 8, 7],\n", + " [3, 3, 3, 3] ]\n", + "\n", + "link:\n", + "https://leetcode.com/problems/max-increase-to-keep-city-skyline/\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Solution 1\n", + "The idea is straight forward, height of each cell is bounded by two conditions: (max in the row, max in the col). \n", + "The challenge will be, how to find and fill it efficiently. \n", + "The first solution here, we use brutal force to begin with." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[9, 4, 8, 7]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# def maxIncreaseKeepingSkyline(grid):\n", + "grid = [ [3, 0, 8, 4], \n", + " [2, 4, 5, 7],\n", + " [9, 2, 6, 3],\n", + " [0, 3, 1, 0] ]\n", + "total_init = sum([sum(content) for content in grid])\n", + "max_col = [0] * len(grid)\n", + "# iterate through colum, bcz max(list) is easy to call\n", + "for col in range(len(grid)):\n", + " for row in range(len(grid)):\n", + " if grid[row][col] > max_col[col]:\n", + " max_col[col] = grid[row][col]\n", + "\n", + "max_col" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "gridNew = grid[:]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[3, 0, 8, 4], [2, 4, 5, 7], [9, 2, 6, 3], [0, 3, 1, 0]]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gridNew2 = grid.copy() # notice that [[0]*4]*4 will give error at the end\n", + "gridNew2" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 0 9 8 8\n", + "0 1 4 8 4\n", + "0 2 8 8 8\n", + "0 3 7 8 7\n", + "1 0 9 7 7\n", + "1 1 4 7 4\n", + "1 2 8 7 7\n", + "1 3 7 7 7\n", + "2 0 9 9 9\n", + "2 1 4 9 4\n", + "2 2 8 9 8\n", + "2 3 7 9 7\n", + "3 0 9 3 3\n", + "3 1 4 3 3\n", + "3 2 8 3 3\n", + "3 3 7 3 3\n" + ] + }, + { + "data": { + "text/plain": [ + "[[8, 4, 8, 7], [7, 4, 7, 7], [9, 4, 8, 7], [3, 3, 3, 3]]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "for row in range(len(grid)):\n", + " for col in range(len(grid)):\n", + " # new grid is bounded by max in col and max in row\n", + " gridNew[row][col] = min(max_col[col], max(grid[row]))\n", + " print(row, col, max_col[col], max(grid[row]), gridNew[row][col]) \n", + " \n", + "gridNew" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[8, 4, 8, 7], [7, 4, 7, 7], [9, 4, 8, 7], [3, 3, 3, 3]]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "grid # well.. due to the python copy problem..you will need deepcopy to \n", + " # generate a new copy with brand new pointer...\n", + " # ref: https://stackoverflow.com/questions/13783315/sum-of-list-of-lists-returns-sum-list\n", + " # a easier way here is to calculate total_init at the begining." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "57 92\n" + ] + }, + { + "data": { + "text/plain": [ + "35" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total_new = sum([sum(content) for content in gridNew])\n", + "print(total_init, total_new)\n", + "total_increase = total_new - total_init\n", + "total_increase" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "# put into a function:\n", + "class Solution(object):\n", + " def maxIncreaseKeepingSkyline(self, grid):\n", + " \"\"\"\n", + " :type grid: List[List[int]]\n", + " :rtype: int\n", + " \"\"\"\n", + " total_init = sum([sum(content) for content in grid])\n", + " max_col = [0] * len(grid)\n", + " # iterate through colum, bcz max(list) is easy to call\n", + " for col in range(len(grid)):\n", + " for row in range(len(grid)):\n", + " if grid[row][col] > max_col[col]:\n", + " max_col[col] = grid[row][col]\n", + " \n", + " gridNew = grid[:]\n", + " for row in range(len(grid)):\n", + " for col in range(len(grid)):\n", + " # new grid is bounded by max in col and max in row\n", + " gridNew[row][col] = min(max_col[col], max(grid[row]))\n", + " \n", + " total_new = sum([sum(content) for content in gridNew])\n", + " total_increase = total_new - total_init \n", + " return total_increase\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "35" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "grid = [ [3, 0, 8, 4], \n", + " [2, 4, 5, 7],\n", + " [9, 2, 6, 3],\n", + " [0, 3, 1, 0] ]\n", + "\n", + "Solution().maxIncreaseKeepingSkyline(grid)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "35" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# note:\n", + "# there are many place we can improve from this brutal approach,\n", + "# for example, we don't really need to create the girdNew, but \n", + "# instead, we only need to accumulate the difference between\n", + "# (height at current cell, possible max height). \n", + "# e.g. we know the possible max height at cell(0,0) is \n", + "# min(9, 8) = 8. So the difference = 8-3 = 5\n", + "# this will save both time and space, and it won't modify the original\n", + "# grid input.\n", + "\n", + "class Solution2(object):\n", + " def maxIncreaseKeepingSkyline(self, grid):\n", + " \"\"\"\n", + " :type grid: List[List[int]]\n", + " :rtype: int\n", + " \"\"\"\n", + " total_init = sum([sum(content) for content in grid])\n", + " max_col = [0] * len(grid)\n", + " # iterate through colum, bcz max(list) is easy to call\n", + " for col in range(len(grid)):\n", + " for row in range(len(grid)):\n", + " if grid[row][col] > max_col[col]:\n", + " max_col[col] = grid[row][col]\n", + " \n", + " output = 0\n", + " for row in range(len(grid)):\n", + " for col in range(len(grid)):\n", + " possible_local_max = min(max_col[col], max(grid[row]))\n", + " output += possible_local_max - grid[row][col]\n", + " \n", + " return output\n", + " \n", + "grid = [ [3, 0, 8, 4], \n", + " [2, 4, 5, 7],\n", + " [9, 2, 6, 3],\n", + " [0, 3, 1, 0] ]\n", + "Solution2().maxIncreaseKeepingSkyline(grid)" + ] + }, + { + "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.6.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/824.Goat_Latin/824. Goat Latin.ipynb b/824. Goat_Latin/824. Goat Latin.ipynb similarity index 100% rename from 824.Goat_Latin/824. Goat Latin.ipynb rename to 824. Goat_Latin/824. Goat Latin.ipynb diff --git a/83. Remove Duplicates from Sorted List.py b/83. Remove Duplicates from Sorted List.py new file mode 100644 index 0000000..dd4c53f --- /dev/null +++ b/83. Remove Duplicates from Sorted List.py @@ -0,0 +1,37 @@ +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val = val + self.next = next + +class Solution: + # time: O(n) + # space: O(n) + def deleteDuplicates(self, head: ListNode) -> ListNode: + if not head: + return head + seen = [head.val] + cur = head + while cur.next: + if cur.next.val in seen: + cur.next = cur.next.next + else: + seen.append(cur.next.val) + cur = cur.next + + + return head +# comment: since the input ListNode is sorted, so we don't actually need a cache to save seen nodes. + + +class Solution: + # time: O(n) + # space: O(1) + def deleteDuplicates(self, head: ListNode) -> ListNode: + cur = head + while cur and cur.next: + if cur.val == cur.next.val: + cur.next = cur.next.next + else: + cur = cur.next + return head \ No newline at end of file diff --git a/835.ImageOverlap/Solution.py b/835.ImageOverlap/Solution.py new file mode 100644 index 0000000..ae5a630 --- /dev/null +++ b/835.ImageOverlap/Solution.py @@ -0,0 +1,29 @@ +class Solution: + def find_all_ones(self, grid): + # given a list of list of int, return the locations where + # element == 1 + tmp_out = [] + if grid: + for i in range(len(grid[0])): + for j in range(len(grid)): + if grid[i][j] == 1: + tmp_out.append((i,j)) + return tmp_out + + def largestOverlap(self, A: List[List[int]], B: List[List[int]]) -> int: + + onesA = self.find_all_ones(A) + onesB = self.find_all_ones(B) + cache = defaultdict(int) + max_count = 0 + + for (x_a, y_a) in onesA: + for (x_b, y_b) in onesB: + vector = (x_b - x_a, y_b - y_a) + cache[vector] += 1 + max_count = max(max_count, cache[vector]) + # print(x_a, y_a, x_b, y_b) + # break + return max_count + + \ No newline at end of file diff --git a/875. Koko Eating Bananas.py b/875. Koko Eating Bananas.py new file mode 100644 index 0000000..f96a458 --- /dev/null +++ b/875. Koko Eating Bananas.py @@ -0,0 +1,36 @@ +from typing import List +import math + + +def minEatingSpeed(piles: List[int], h: int) -> int: + def findTimeNeeded(piles: List[int], speed: int) -> int: + if speed == 0: + return math.inf + ret = 0 + for pile in piles: + ret += math.ceil(pile / speed) + return ret + + l, r = 1, max(piles) # speed in banana per hour + while l < r: # find the minimum such that time needed < h + m = l + (r - l) // 2 + time = findTimeNeeded(piles, m) # searching the lower upper bound + if time <= h: + r = m + else: + l = m + 1 + print(l) + return l + # m = l + (r - l) // 2 + # time = findTimeNeeded(piles, m) # searching the lower upper bound + # if time <= h: + # r = m + # else: + # l = m + 1 + + # return False + + +minEatingSpeed([1, 1, 1, 999999999], 10) # 142857143 +minEatingSpeed([30, 11, 23, 4, 20], 5) # 30 +minEatingSpeed([312884470], 312884469) # 2 diff --git a/876_Middle_of_the_Linked_List.py b/876_Middle_of_the_Linked_List.py new file mode 100644 index 0000000..d3a60b3 --- /dev/null +++ b/876_Middle_of_the_Linked_List.py @@ -0,0 +1,20 @@ +# 876. Middle of the Linked List + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def middleNode(self, head: ListNode) -> ListNode: + mid_finder, end_finder = head, head + # while end_finder.next and end_finder.next.next: + # mid_finder = mid_finder.next + # end_finder = end_finder.next.next + # if end_finder.next: + # mid_finder = mid_finder.next + while end_finder and end_finder.next: + mid_finder = mid_finder.next + end_finder = end_finder.next.next + return mid_finder \ No newline at end of file diff --git a/937. Reorder Data in Log Files.ipynb b/937. Reorder Data in Log Files.ipynb new file mode 100644 index 0000000..796af2c --- /dev/null +++ b/937. Reorder Data in Log Files.ipynb @@ -0,0 +1,210 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "a = \"a\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.isdigit()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def is_digitlog(string):\n", + " strs = string.split(\" \")\n", + " for word in strs[1:]:\n", + " if not word.isdigit():\n", + " return False\n", + " return True" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['let1 art can',\n", + " 'let3 art zero',\n", + " 'let2 own kit dig',\n", + " 'dig1 8 1 5 1',\n", + " 'dig2 3 6']" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def reorderLogFiles(logs):\n", + " \"\"\"\n", + " :type logs: List[str]\n", + " :rtype: List[str]\n", + " \"\"\"\n", + " digit_logs = []\n", + " word_logs = []\n", + " for log in logs:\n", + " if is_digitlog(log):\n", + " digit_logs.append(log)\n", + " else:\n", + " # move identifier to the end for sorting\n", + " words_in_log = log.split(\" \")\n", + " log = \" \".join(words_in_log[1:])\n", + " log += \" \" + words_in_log[0]\n", + " word_logs.append(log)\n", + " word_logs = sorted(word_logs)\n", + " # move identifier back to the front\n", + " converted_back_word_logs = []\n", + " for word in word_logs:\n", + " tmp_words = word.split(\" \")\n", + " words = \" \".join(tmp_words[:-1])\n", + " words = tmp_words[-1] + \" \" + words\n", + " converted_back_word_logs.append(words)\n", + " \n", + " return converted_back_word_logs + digit_logs\n", + "\n", + "logs = [\"dig1 8 1 5 1\",\"let1 art can\",\"dig2 3 6\",\"let2 own kit dig\",\"let3 art zero\"]\n", + "reorderLogFiles(logs)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['let1 art can',\n", + " 'let3 art zero',\n", + " 'let2 own kit dig',\n", + " 'dig1 8 1 5 1',\n", + " 'dig2 3 6']" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# better version: use configs in .sort() function:\n", + "def reorderLogFiles(logs):\n", + " \"\"\"\n", + " :type logs: List[str]\n", + " :rtype: List[str]\n", + " \"\"\"\n", + " digit_logs = []\n", + " word_logs = []\n", + " for log in logs:\n", + " if is_digitlog(log):\n", + " digit_logs.append(log)\n", + " else:\n", + " word_logs.append(log)\n", + " \n", + " # sort by identifier first\n", + " word_logs.sort(key=lambda x: x.split()[0])\n", + " word_logs.sort(key=lambda x: x.split()[1:])\n", + " return word_logs + digit_logs\n", + "\n", + "logs = [\"dig1 8 1 5 1\",\"let1 art can\",\"dig2 3 6\",\"let2 own kit dig\",\"let3 art zero\"]\n", + "reorderLogFiles(logs)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['dig1 8 1 5 1',\n", + " 'dig2 3 6',\n", + " 'let1 art can',\n", + " 'let2 own kit dig',\n", + " 'let3 art zero']" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "logs.sort(key=lambda x: x.split(\" \")[0])\n", + "logs" + ] + }, + { + "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.6.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/BFS_jigsaw/.ipynb_checkpoints/773_SlidingPuzzle_BFS_and_Jigsaw-Copy1-checkpoint.ipynb b/BFS_jigsaw/.ipynb_checkpoints/773_SlidingPuzzle_BFS_and_Jigsaw-Copy1-checkpoint.ipynb new file mode 100644 index 0000000..87a44db --- /dev/null +++ b/BFS_jigsaw/.ipynb_checkpoints/773_SlidingPuzzle_BFS_and_Jigsaw-Copy1-checkpoint.ipynb @@ -0,0 +1,606 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1. We implement 773. Sliding Puzzle as a warmup\n", + "On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and an empty square represented by 0. \n", + "\n", + "A move consists of choosing 0 and a 4-directionally adjacent number and swapping it. \n", + "\n", + "The state of the board is solved if and only if the board is [[1,2,3],[4,5,0]]. \n", + "\n", + "Given a puzzle board, return the least number of moves required so that the state of the board is solved. If it is impossible for the state of the board to be solved, return -1." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# def slidingPuzzle(board: List[List[int]]) -> int:\n", + "# pass\n", + "len_x = 1\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0:\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " out_boards.append((new_board, x, y-1))\n", + " if y <= (len_y-1):\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " out_boards.append((new_board, x, y+1))\n", + " if x >0:\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " out_boards.append((new_board, x-1, y))\n", + " if x <= (len_x-1):\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " out_boards.append((new_board, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board, x, y):\n", + " step = 0\n", + " Q = [(board, x, y, step)]\n", + " seen = []\n", + " while len(Q)>0:\n", + "# import pdb; pdb.set_trace()\n", + " to_explore, x, y, step = Q.pop(0)\n", + " print(to_explore, step)\n", + " if to_explore == [[1,2,3], [4,5,0]]:\n", + " print(\"Found! at step: \",step)\n", + " return step\n", + " \n", + " if to_explore in seen:\n", + " continue\n", + " else:\n", + " seen.append(to_explore)\n", + " if 0 in to_explore[0]:\n", + " x = 0\n", + " else:\n", + " x = 1\n", + " y = to_explore[x].index(0)\n", + " \n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, new_x, new_y = new\n", + " Q.append([new_board, new_x, new_y, step+1])\n", + " return -1\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# tests:\n", + "# print(slidingPuzzle([[1,2,3], [4,5,0]]))\n", + "board = [[1,2,3],[4,0,5]]\n", + "print(slidingPuzzle(board, 1, 1)) # 1\n", + "board = [[4,1,2],[5,0,3]]\n", + "print(slidingPuzzle(board, 1, 1)) # 5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = [[3,2,4],[1,5,0]]\n", + "print(slidingPuzzle(board, 1, 2)) # 14" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tmp = [[1,2,3], [4,5,0]]\n", + "# tmp[1].index(0)\n", + "# if 0 in tmp[0]: x = 0, \n", + "# else: x = 1\n", + "# new_tmp = tmp.copy()\n", + "import copy\n", + "new_tmp = copy.deepcopy(tmp)\n", + "print(tmp, new_tmp)\n", + "tmp[0][0], tmp[0][1] = tmp[0][1], tmp[0][0]\n", + "print(tmp, new_tmp)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tmp = [[[[1,2,3], [4,5,0]], 0, 0, 1]]\n", + "tmp.append([[[[1,2,6], [4,5,0]], 1, 0, 2]])\n", + "tmp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.1 A tree version\n", + "Well. We did solve the 773 above. However, we also want a road map to the min solution. \n", + "And it seems only possible with a tree structure (that way you get a hold of the last node, find the parent, then the parent's parent, etc.)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from anytree import Node, RenderTree" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# def slidingPuzzle(board: List[List[int]]) -> int:\n", + "# pass\n", + "len_x = 1\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0:\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y-1))\n", + " if y <= (len_y-1):\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y+1))\n", + " if x >0:\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x-1, y))\n", + " if x <= (len_x-1):\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board, x, y):\n", + " step = 0\n", + " Q = [(board, x, y, step)]\n", + " seen = []\n", + " while len(Q)>0:\n", + " to_explore, x, y, step = Q.pop(0)\n", + " if to_explore.name == [[1,2,3], [4,5,0]]:\n", + " return to_explore.depth\n", + " \n", + " if to_explore.name in seen:\n", + " continue\n", + " else:\n", + " seen.append(to_explore.name)\n", + " if 0 in to_explore.name[0]:\n", + " x = 0\n", + " else:\n", + " x = 1\n", + " y = to_explore.name[x].index(0)\n", + " \n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, new_x, new_y = new\n", + " Q.append([new_board, new_x, new_y, step+1])\n", + " return -1\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[1,2,3],[4,0,5]])\n", + "print(slidingPuzzle(board, 1, 1))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[4,1,2],[5,0,3]])\n", + "print(slidingPuzzle(board, 1, 1))\n", + "for pre, fill, node in RenderTree(board):\n", + " print(\"%s%s\" % (pre, node.name))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[3,2,4],[1,5,0]])\n", + "print(slidingPuzzle(board, 1, 2)) # 14" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# dir(board)\n", + "# ??Node" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. We use BFS to solve the jigsaw problem.\n", + "Problem: Given a 3x3 list with non repeating numbers, \n", + "(e.g. [[5, 0, 3], [1, 2, 6], [8, 7, 9]]) \n", + "each time you can swap two adjacent numbers (up, down, left, right.) \n", + "search through the possible space to find the minimum steps required to sort it, \n", + "and print out the road map.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len_x = 2\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0: # left\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y-1))\n", + " if y <= (len_y-1): #right\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y+1))\n", + " if x >0: # up\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x-1, y))\n", + " if x <= (len_x-1): # down\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board):\n", + " Q = []\n", + " for x in range(3):\n", + " for y in range(3):\n", + " Q.append(board)\n", + "# Q.append((board, x, y))\n", + " seen = []\n", + " while len(Q)>0:\n", + "# import pdb; pdb.set_trace()\n", + "# to_explore, x, y = Q.pop(0)\n", + "# print(to_explore.name, to_explore.depth)\n", + " to_explore = Q.pop(0)\n", + " if len(seen)%100 == 0:\n", + " print(len(seen), to_explore.depth)\n", + " if to_explore.name == [[1,2,3], [4,5,6], [7,8,9]]:\n", + " return to_explore.depth, to_explore\n", + " for x in range(3):\n", + " for y in range(3):\n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, _, _ = new\n", + " if new_board.name not in seen:\n", + " seen.append(new_board.name)\n", + " Q.append(new_board)\n", + " return -1, None" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# test\n", + "board = Node([[1,2,3],[4,5,6], [7,8,9]])\n", + "%time print(slidingPuzzle(board)) # 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "board = Node([[1,2,3],[4,5,6], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "board = Node([[1,2,3],[4,6,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[1,2,3],[6,4,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[1,6,3],[4,2,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[4,6,3],[7,2,5], [1,9,8]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # 5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[5,4,6],[9,7,2], [8,1,3]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # ghost examiner" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "ERROR:root:Internal Python error in the inspect module.\n", + "Below is the traceback from this internal error.\n", + "\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Traceback (most recent call last):\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/magics/execution.py\", line 1310, in time\n", + " exec(code, glob, local_ns)\n", + " File \"\", line 1, in \n", + " File \"\", line 52, in slidingPuzzle\n", + " if new_board.name not in seen:\n", + "KeyboardInterrupt\n", + "\n", + "During handling of the above exception, another exception occurred:\n", + "\n", + "Traceback (most recent call last):\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/interactiveshell.py\", line 2039, in showtraceback\n", + " stb = value._render_traceback_()\n", + "AttributeError: 'KeyboardInterrupt' object has no attribute '_render_traceback_'\n", + "\n", + "During handling of the above exception, another exception occurred:\n", + "\n", + "Traceback (most recent call last):\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/ultratb.py\", line 1101, in get_records\n", + " return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/ultratb.py\", line 319, in wrapped\n", + " return f(*args, **kwargs)\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/ultratb.py\", line 353, in _fixed_getinnerframes\n", + " records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))\n", + " File \"/Users/toby/anaconda3/envs/py36/lib/python3.6/inspect.py\", line 1490, in getinnerframes\n", + " frameinfo = (tb.tb_frame,) + getframeinfo(tb, context)\n", + " File \"/Users/toby/anaconda3/envs/py36/lib/python3.6/inspect.py\", line 1452, in getframeinfo\n", + " lines, lnum = findsource(frame)\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/ultratb.py\", line 185, in findsource\n", + " lines = linecache.getlines(file, globals_dict)\n", + " File \"/Users/toby/anaconda3/envs/py36/lib/python3.6/linecache.py\", line 47, in getlines\n", + " return updatecache(filename, module_globals)\n", + " File \"/Users/toby/anaconda3/envs/py36/lib/python3.6/linecache.py\", line 137, in updatecache\n", + " lines = fp.readlines()\n", + " File \"/Users/toby/anaconda3/envs/py36/lib/python3.6/codecs.py\", line 318, in decode\n", + " def decode(self, input, final=False):\n", + "KeyboardInterrupt\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "KeyboardInterrupt\n", + "\n" + ] + } + ], + "source": [ + "board = Node([[6,7,9],[2,3,8], [4,1,5]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # human examiner" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[7,5,1],[6,2,9], [4,3,8]])\n", + "%time tmp2 = slidingPuzzle(board)\n", + "print(tmp2) # fairy examiner" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + "# if direction=='left' and y > 0:\n", + "# board[x][y], board[x][y-1] = board[x][y-1], board[x][y]\n", + "# if direction=='right' and to_explore.name, x, yy <= (len_y-1):\n", + "# board[x][y], board[x][y+1] = board[x][y+1], board[x][y]\n", + "# if direction=='up' and x >0:\n", + "# board[x][y], board[x-1][y] = board[x-1][y], board[x][y]\n", + "# if direction=='down' and x <= (len_x-1):\n", + "# board[x][y], board[x+1][y] = board[x+1][y], board[x][y]\n", + "# return board\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# from anytree import Node, RenderTree\n", + "\n", + "# udo = Node(\"Udo\")\n", + "# marc = Node(\"Marc\", parent=udo)\n", + "# lian = Node(\"Lian\", parent=marc)\n", + "# dan = Node(\"Dan\", parent=udo)\n", + "# jet = Node(\"Jet\", parent=dan)\n", + "# jan = Node(\"Jan\", parent=dan)\n", + "# joe = Node(\"Joe\", parent=dan)\n", + "\n", + "# print(udo)\n", + "# Node('/Udo')\n", + "# print(joe)\n", + "# Node('/Udo/Dan/Joe')\n", + "\n", + "# for pre, fill, node in RenderTree(udo):\n", + "# print(\"%s%s\" % (pre, node.name))\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/BFS_jigsaw/.ipynb_checkpoints/773_SlidingPuzzle_BFS_and_Jigsaw-checkpoint.ipynb b/BFS_jigsaw/.ipynb_checkpoints/773_SlidingPuzzle_BFS_and_Jigsaw-checkpoint.ipynb new file mode 100644 index 0000000..108aad3 --- /dev/null +++ b/BFS_jigsaw/.ipynb_checkpoints/773_SlidingPuzzle_BFS_and_Jigsaw-checkpoint.ipynb @@ -0,0 +1,1224 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1. We implement 773. Sliding Puzzle as a warmup\n", + "On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and an empty square represented by 0. \n", + "\n", + "A move consists of choosing 0 and a 4-directionally adjacent number and swapping it. \n", + "\n", + "The state of the board is solved if and only if the board is [[1,2,3],[4,5,0]]. \n", + "\n", + "Given a puzzle board, return the least number of moves required so that the state of the board is solved. If it is impossible for the state of the board to be solved, return -1." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "import math\n", + "\n", + "from anytree import Node, RenderTree" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [], + "source": [ + "# def slidingPuzzle(board: List[List[int]]) -> int:\n", + "# pass\n", + "len_x = 1\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0:\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " out_boards.append((new_board, x, y-1))\n", + " if y <= (len_y-1):\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " out_boards.append((new_board, x, y+1))\n", + " if x >0:\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " out_boards.append((new_board, x-1, y))\n", + " if x <= (len_x-1):\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " out_boards.append((new_board, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board, x, y):\n", + " step = 0\n", + " Q = [(board, x, y, step)]\n", + " seen = []\n", + " while len(Q)>0:\n", + "# import pdb; pdb.set_trace()\n", + " to_explore, x, y, step = Q.pop(0)\n", + " print(to_explore, step)\n", + " if to_explore == [[1,2,3], [4,5,0]]:\n", + " print(\"Found! at step: \",step)\n", + " return step\n", + " \n", + " if to_explore in seen:\n", + " continue\n", + " else:\n", + " seen.append(to_explore)\n", + " if 0 in to_explore[0]:\n", + " x = 0\n", + " else:\n", + " x = 1\n", + " y = to_explore[x].index(0)\n", + " \n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, new_x, new_y = new\n", + " Q.append([new_board, new_x, new_y, step+1])\n", + " return -1\n" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 2, 3], [4, 0, 5]] 0\n", + "[[1, 2, 3], [0, 4, 5]] 1\n", + "[[1, 2, 3], [4, 5, 0]] 1\n", + "Found! at step: 1\n", + "1\n", + "[[4, 1, 2], [5, 0, 3]] 0\n", + "[[4, 1, 2], [0, 5, 3]] 1\n", + "[[4, 1, 2], [5, 3, 0]] 1\n", + "[[4, 0, 2], [5, 1, 3]] 1\n", + "[[4, 1, 2], [5, 0, 3]] 2\n", + "[[0, 1, 2], [4, 5, 3]] 2\n", + "[[4, 1, 2], [5, 0, 3]] 2\n", + "[[4, 1, 0], [5, 3, 2]] 2\n", + "[[0, 4, 2], [5, 1, 3]] 2\n", + "[[4, 2, 0], [5, 1, 3]] 2\n", + "[[4, 1, 2], [5, 0, 3]] 2\n", + "[[1, 0, 2], [4, 5, 3]] 3\n", + "[[4, 1, 2], [0, 5, 3]] 3\n", + "[[4, 0, 1], [5, 3, 2]] 3\n", + "[[4, 1, 2], [5, 3, 0]] 3\n", + "[[4, 0, 2], [5, 1, 3]] 3\n", + "[[5, 4, 2], [0, 1, 3]] 3\n", + "[[4, 0, 2], [5, 1, 3]] 3\n", + "[[4, 2, 3], [5, 1, 0]] 3\n", + "[[0, 1, 2], [4, 5, 3]] 4\n", + "[[1, 2, 0], [4, 5, 3]] 4\n", + "[[1, 5, 2], [4, 0, 3]] 4\n", + "[[0, 4, 1], [5, 3, 2]] 4\n", + "[[4, 1, 0], [5, 3, 2]] 4\n", + "[[4, 3, 1], [5, 0, 2]] 4\n", + "[[5, 4, 2], [1, 0, 3]] 4\n", + "[[0, 4, 2], [5, 1, 3]] 4\n", + "[[4, 2, 3], [5, 0, 1]] 4\n", + "[[4, 2, 0], [5, 1, 3]] 4\n", + "[[1, 0, 2], [4, 5, 3]] 5\n", + "[[1, 2, 3], [4, 5, 0]] 5\n", + "Found! at step: 5\n", + "5\n" + ] + } + ], + "source": [ + "# tests:\n", + "# print(slidingPuzzle([[1,2,3], [4,5,0]]))\n", + "board = [[1,2,3],[4,0,5]]\n", + "print(slidingPuzzle(board, 1, 1)) # 1\n", + "board = [[4,1,2],[5,0,3]]\n", + "print(slidingPuzzle(board, 1, 1)) # 5" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[3, 2, 4], [1, 5, 0]] 0\n", + "[[3, 2, 4], [1, 0, 5]] 1\n", + "[[3, 2, 0], [1, 5, 4]] 1\n", + "[[3, 2, 4], [0, 1, 5]] 2\n", + "[[3, 2, 4], [1, 5, 0]] 2\n", + "[[3, 0, 4], [1, 2, 5]] 2\n", + "[[3, 0, 2], [1, 5, 4]] 2\n", + "[[3, 2, 4], [1, 5, 0]] 2\n", + "[[3, 2, 4], [1, 0, 5]] 3\n", + "[[0, 2, 4], [3, 1, 5]] 3\n", + "[[0, 3, 4], [1, 2, 5]] 3\n", + "[[3, 4, 0], [1, 2, 5]] 3\n", + "[[3, 2, 4], [1, 0, 5]] 3\n", + "[[0, 3, 2], [1, 5, 4]] 3\n", + "[[3, 2, 0], [1, 5, 4]] 3\n", + "[[3, 5, 2], [1, 0, 4]] 3\n", + "[[2, 0, 4], [3, 1, 5]] 4\n", + "[[3, 2, 4], [0, 1, 5]] 4\n", + "[[3, 0, 4], [1, 2, 5]] 4\n", + "[[1, 3, 4], [0, 2, 5]] 4\n", + "[[3, 0, 4], [1, 2, 5]] 4\n", + "[[3, 4, 5], [1, 2, 0]] 4\n", + "[[3, 0, 2], [1, 5, 4]] 4\n", + "[[1, 3, 2], [0, 5, 4]] 4\n", + "[[3, 5, 2], [0, 1, 4]] 4\n", + "[[3, 5, 2], [1, 4, 0]] 4\n", + "[[3, 0, 2], [1, 5, 4]] 4\n", + "[[0, 2, 4], [3, 1, 5]] 5\n", + "[[2, 4, 0], [3, 1, 5]] 5\n", + "[[2, 1, 4], [3, 0, 5]] 5\n", + "[[1, 3, 4], [2, 0, 5]] 5\n", + "[[0, 3, 4], [1, 2, 5]] 5\n", + "[[3, 4, 5], [1, 0, 2]] 5\n", + "[[3, 4, 0], [1, 2, 5]] 5\n", + "[[1, 3, 2], [5, 0, 4]] 5\n", + "[[0, 3, 2], [1, 5, 4]] 5\n", + "[[3, 5, 2], [1, 0, 4]] 5\n", + "[[0, 5, 2], [3, 1, 4]] 5\n", + "[[3, 5, 2], [1, 0, 4]] 5\n", + "[[3, 5, 0], [1, 4, 2]] 5\n", + "[[2, 0, 4], [3, 1, 5]] 6\n", + "[[2, 4, 5], [3, 1, 0]] 6\n", + "[[2, 1, 4], [0, 3, 5]] 6\n", + "[[2, 1, 4], [3, 5, 0]] 6\n", + "[[2, 0, 4], [3, 1, 5]] 6\n", + "[[1, 3, 4], [0, 2, 5]] 6\n", + "[[1, 3, 4], [2, 5, 0]] 6\n", + "[[1, 0, 4], [2, 3, 5]] 6\n", + "[[3, 4, 5], [0, 1, 2]] 6\n", + "[[3, 4, 5], [1, 2, 0]] 6\n", + "[[3, 0, 5], [1, 4, 2]] 6\n", + "[[1, 3, 2], [0, 5, 4]] 6\n", + "[[1, 3, 2], [5, 4, 0]] 6\n", + "[[1, 0, 2], [5, 3, 4]] 6\n", + "[[5, 0, 2], [3, 1, 4]] 6\n", + "[[3, 5, 2], [0, 1, 4]] 6\n", + "[[3, 0, 5], [1, 4, 2]] 6\n", + "[[3, 5, 2], [1, 4, 0]] 6\n", + "[[2, 4, 5], [3, 0, 1]] 7\n", + "[[2, 4, 0], [3, 1, 5]] 7\n", + "[[2, 1, 4], [3, 0, 5]] 7\n", + "[[0, 1, 4], [2, 3, 5]] 7\n", + "[[2, 1, 4], [3, 0, 5]] 7\n", + "[[2, 1, 0], [3, 5, 4]] 7\n", + "[[1, 3, 4], [2, 0, 5]] 7\n", + "[[1, 3, 0], [2, 5, 4]] 7\n", + "[[0, 1, 4], [2, 3, 5]] 7\n", + "[[1, 4, 0], [2, 3, 5]] 7\n", + "[[1, 3, 4], [2, 0, 5]] 7\n", + "[[3, 4, 5], [1, 0, 2]] 7\n", + "[[0, 4, 5], [3, 1, 2]] 7\n", + "[[0, 3, 5], [1, 4, 2]] 7\n", + "[[3, 5, 0], [1, 4, 2]] 7\n", + "[[3, 4, 5], [1, 0, 2]] 7\n", + "[[1, 3, 2], [5, 0, 4]] 7\n", + "[[1, 3, 0], [5, 4, 2]] 7\n", + "[[0, 1, 2], [5, 3, 4]] 7\n", + "[[1, 2, 0], [5, 3, 4]] 7\n", + "[[1, 3, 2], [5, 0, 4]] 7\n", + "[[0, 5, 2], [3, 1, 4]] 7\n", + "[[5, 2, 0], [3, 1, 4]] 7\n", + "[[5, 1, 2], [3, 0, 4]] 7\n", + "[[2, 4, 5], [0, 3, 1]] 8\n", + "[[2, 4, 5], [3, 1, 0]] 8\n", + "[[2, 0, 5], [3, 4, 1]] 8\n", + "[[1, 0, 4], [2, 3, 5]] 8\n", + "[[2, 1, 4], [0, 3, 5]] 8\n", + "[[2, 0, 1], [3, 5, 4]] 8\n", + "[[2, 1, 4], [3, 5, 0]] 8\n", + "[[1, 0, 3], [2, 5, 4]] 8\n", + "[[1, 3, 4], [2, 5, 0]] 8\n", + "[[1, 0, 4], [2, 3, 5]] 8\n", + "[[1, 4, 5], [2, 3, 0]] 8\n", + "[[4, 0, 5], [3, 1, 2]] 8\n", + "[[3, 4, 5], [0, 1, 2]] 8\n", + "[[3, 0, 5], [1, 4, 2]] 8\n", + "[[1, 3, 5], [0, 4, 2]] 8\n", + "[[1, 0, 3], [5, 4, 2]] 8\n", + "[[1, 3, 2], [5, 4, 0]] 8\n", + "[[1, 0, 2], [5, 3, 4]] 8\n", + "[[5, 1, 2], [0, 3, 4]] 8\n", + "[[1, 0, 2], [5, 3, 4]] 8\n", + "[[1, 2, 4], [5, 3, 0]] 8\n", + "[[5, 0, 2], [3, 1, 4]] 8\n", + "[[5, 2, 4], [3, 1, 0]] 8\n", + "[[5, 1, 2], [0, 3, 4]] 8\n", + "[[5, 1, 2], [3, 4, 0]] 8\n", + "[[5, 0, 2], [3, 1, 4]] 8\n", + "[[2, 4, 5], [3, 0, 1]] 9\n", + "[[0, 4, 5], [2, 3, 1]] 9\n", + "[[0, 2, 5], [3, 4, 1]] 9\n", + "[[2, 5, 0], [3, 4, 1]] 9\n", + "[[2, 4, 5], [3, 0, 1]] 9\n", + "[[0, 2, 1], [3, 5, 4]] 9\n", + "[[2, 1, 0], [3, 5, 4]] 9\n", + "[[2, 5, 1], [3, 0, 4]] 9\n", + "[[0, 1, 3], [2, 5, 4]] 9\n", + "[[1, 3, 0], [2, 5, 4]] 9\n", + "[[1, 5, 3], [2, 0, 4]] 9\n", + "[[1, 4, 5], [2, 0, 3]] 9\n", + "[[1, 4, 0], [2, 3, 5]] 9\n", + "[[0, 4, 5], [3, 1, 2]] 9\n", + "[[4, 5, 0], [3, 1, 2]] 9\n", + "[[4, 1, 5], [3, 0, 2]] 9\n", + "[[1, 3, 5], [4, 0, 2]] 9\n", + "[[0, 3, 5], [1, 4, 2]] 9\n", + "[[0, 1, 3], [5, 4, 2]] 9\n", + "[[1, 3, 0], [5, 4, 2]] 9\n", + "[[1, 4, 3], [5, 0, 2]] 9\n", + "[[5, 1, 2], [3, 0, 4]] 9\n", + "[[0, 1, 2], [5, 3, 4]] 9\n", + "[[1, 2, 4], [5, 0, 3]] 9\n", + "[[1, 2, 0], [5, 3, 4]] 9\n", + "[[5, 2, 4], [3, 0, 1]] 9\n", + "[[5, 2, 0], [3, 1, 4]] 9\n", + "[[5, 1, 2], [3, 0, 4]] 9\n", + "[[5, 1, 0], [3, 4, 2]] 9\n", + "[[4, 0, 5], [2, 3, 1]] 10\n", + "[[2, 4, 5], [0, 3, 1]] 10\n", + "[[2, 0, 5], [3, 4, 1]] 10\n", + "[[3, 2, 5], [0, 4, 1]] 10\n", + "[[2, 0, 5], [3, 4, 1]] 10\n", + "[[2, 5, 1], [3, 4, 0]] 10\n", + "[[2, 0, 1], [3, 5, 4]] 10\n", + "[[3, 2, 1], [0, 5, 4]] 10\n", + "[[2, 5, 1], [0, 3, 4]] 10\n", + "[[2, 5, 1], [3, 4, 0]] 10\n", + "[[2, 0, 1], [3, 5, 4]] 10\n", + "[[1, 0, 3], [2, 5, 4]] 10\n", + "[[2, 1, 3], [0, 5, 4]] 10\n", + "[[1, 5, 3], [0, 2, 4]] 10\n", + "[[1, 5, 3], [2, 4, 0]] 10\n", + "[[1, 0, 3], [2, 5, 4]] 10\n", + "[[1, 4, 5], [0, 2, 3]] 10\n", + "[[1, 4, 5], [2, 3, 0]] 10\n", + "[[1, 0, 5], [2, 4, 3]] 10\n", + "[[4, 0, 5], [3, 1, 2]] 10\n", + "[[4, 5, 2], [3, 1, 0]] 10\n", + "[[4, 1, 5], [0, 3, 2]] 10\n", + "[[4, 1, 5], [3, 2, 0]] 10\n", + "[[4, 0, 5], [3, 1, 2]] 10\n", + "[[1, 3, 5], [0, 4, 2]] 10\n", + "[[1, 3, 5], [4, 2, 0]] 10\n", + "[[1, 0, 5], [4, 3, 2]] 10\n", + "[[1, 0, 3], [5, 4, 2]] 10\n", + "[[5, 1, 3], [0, 4, 2]] 10\n", + "[[1, 4, 3], [0, 5, 2]] 10\n", + "[[1, 4, 3], [5, 2, 0]] 10\n", + "[[1, 0, 3], [5, 4, 2]] 10\n", + "[[1, 2, 4], [0, 5, 3]] 10\n", + "[[1, 2, 4], [5, 3, 0]] 10\n", + "[[1, 0, 4], [5, 2, 3]] 10\n", + "[[5, 2, 4], [0, 3, 1]] 10\n", + "[[5, 2, 4], [3, 1, 0]] 10\n", + "[[5, 0, 4], [3, 2, 1]] 10\n", + "[[5, 0, 1], [3, 4, 2]] 10\n", + "[[5, 1, 2], [3, 4, 0]] 10\n", + "[[0, 4, 5], [2, 3, 1]] 11\n", + "[[4, 5, 0], [2, 3, 1]] 11\n", + "[[4, 3, 5], [2, 0, 1]] 11\n", + "[[3, 2, 5], [4, 0, 1]] 11\n", + "[[0, 2, 5], [3, 4, 1]] 11\n", + "[[2, 5, 1], [3, 0, 4]] 11\n", + "[[2, 5, 0], [3, 4, 1]] 11\n", + "[[3, 2, 1], [5, 0, 4]] 11\n", + "[[0, 2, 1], [3, 5, 4]] 11\n", + "[[2, 5, 1], [3, 0, 4]] 11\n", + "[[0, 5, 1], [2, 3, 4]] 11\n", + "[[2, 1, 3], [5, 0, 4]] 11\n", + "[[0, 1, 3], [2, 5, 4]] 11\n", + "[[1, 5, 3], [2, 0, 4]] 11\n", + "[[0, 5, 3], [1, 2, 4]] 11\n", + "[[1, 5, 3], [2, 0, 4]] 11\n", + "[[1, 5, 0], [2, 4, 3]] 11\n", + "[[1, 4, 5], [2, 0, 3]] 11\n", + "[[0, 4, 5], [1, 2, 3]] 11\n", + "[[0, 1, 5], [2, 4, 3]] 11\n", + "[[1, 5, 0], [2, 4, 3]] 11\n", + "[[1, 4, 5], [2, 0, 3]] 11\n", + "[[4, 5, 2], [3, 0, 1]] 11\n", + "[[4, 5, 0], [3, 1, 2]] 11\n", + "[[4, 1, 5], [3, 0, 2]] 11\n", + "[[0, 1, 5], [4, 3, 2]] 11\n", + "[[4, 1, 5], [3, 0, 2]] 11\n", + "[[4, 1, 0], [3, 2, 5]] 11\n", + "[[1, 3, 5], [4, 0, 2]] 11\n", + "[[1, 3, 0], [4, 2, 5]] 11\n", + "[[0, 1, 5], [4, 3, 2]] 11\n", + "[[1, 5, 0], [4, 3, 2]] 11\n", + "[[1, 3, 5], [4, 0, 2]] 11\n", + "[[5, 1, 3], [4, 0, 2]] 11\n", + "[[0, 1, 3], [5, 4, 2]] 11\n", + "[[1, 4, 3], [5, 0, 2]] 11\n", + "[[0, 4, 3], [1, 5, 2]] 11\n", + "[[1, 4, 3], [5, 0, 2]] 11\n", + "[[1, 4, 0], [5, 2, 3]] 11\n", + "[[1, 2, 4], [5, 0, 3]] 11\n", + "[[0, 2, 4], [1, 5, 3]] 11\n", + "[[0, 1, 4], [5, 2, 3]] 11\n", + "[[1, 4, 0], [5, 2, 3]] 11\n", + "[[1, 2, 4], [5, 0, 3]] 11\n", + "[[5, 2, 4], [3, 0, 1]] 11\n", + "[[0, 2, 4], [5, 3, 1]] 11\n", + "[[0, 5, 4], [3, 2, 1]] 11\n", + "[[5, 4, 0], [3, 2, 1]] 11\n", + "[[5, 2, 4], [3, 0, 1]] 11\n", + "[[0, 5, 1], [3, 4, 2]] 11\n", + "[[5, 1, 0], [3, 4, 2]] 11\n", + "[[5, 4, 1], [3, 0, 2]] 11\n", + "[[4, 0, 5], [2, 3, 1]] 12\n", + "[[4, 5, 1], [2, 3, 0]] 12\n", + "[[4, 3, 5], [0, 2, 1]] 12\n", + "[[4, 3, 5], [2, 1, 0]] 12\n", + "[[4, 0, 5], [2, 3, 1]] 12\n", + "[[3, 2, 5], [0, 4, 1]] 12\n", + "[[3, 2, 5], [4, 1, 0]] 12\n", + "[[3, 0, 5], [4, 2, 1]] 12\n", + "[[3, 2, 1], [0, 5, 4]] 12\n", + "[[3, 2, 1], [5, 4, 0]] 12\n", + "[[3, 0, 1], [5, 2, 4]] 12\n", + "[[5, 0, 1], [2, 3, 4]] 12\n", + "[[2, 5, 1], [0, 3, 4]] 12\n", + "[[2, 1, 3], [0, 5, 4]] 12\n", + "[[2, 1, 3], [5, 4, 0]] 12\n", + "[[2, 0, 3], [5, 1, 4]] 12\n", + "[[5, 0, 3], [1, 2, 4]] 12\n", + "[[1, 5, 3], [0, 2, 4]] 12\n", + "[[1, 0, 5], [2, 4, 3]] 12\n", + "[[1, 5, 3], [2, 4, 0]] 12\n", + "[[4, 0, 5], [1, 2, 3]] 12\n", + "[[1, 4, 5], [0, 2, 3]] 12\n", + "[[1, 0, 5], [2, 4, 3]] 12\n", + "[[2, 1, 5], [0, 4, 3]] 12\n", + "[[4, 5, 2], [0, 3, 1]] 12\n", + "[[4, 5, 2], [3, 1, 0]] 12\n", + "[[4, 0, 2], [3, 5, 1]] 12\n", + "[[1, 0, 5], [4, 3, 2]] 12\n", + "[[4, 1, 5], [0, 3, 2]] 12\n", + "[[4, 0, 1], [3, 2, 5]] 12\n", + "[[4, 1, 5], [3, 2, 0]] 12\n", + "[[1, 0, 3], [4, 2, 5]] 12\n", + "[[1, 3, 5], [4, 2, 0]] 12\n", + "[[1, 0, 5], [4, 3, 2]] 12\n", + "[[1, 5, 2], [4, 3, 0]] 12\n", + "[[5, 1, 3], [0, 4, 2]] 12\n", + "[[5, 1, 3], [4, 2, 0]] 12\n", + "[[5, 0, 3], [4, 1, 2]] 12\n", + "[[4, 0, 3], [1, 5, 2]] 12\n", + "[[1, 4, 3], [0, 5, 2]] 12\n", + "[[1, 0, 4], [5, 2, 3]] 12\n", + "[[1, 4, 3], [5, 2, 0]] 12\n", + "[[2, 0, 4], [1, 5, 3]] 12\n", + "[[1, 2, 4], [0, 5, 3]] 12\n", + "[[1, 0, 4], [5, 2, 3]] 12\n", + "[[5, 1, 4], [0, 2, 3]] 12\n", + "[[2, 0, 4], [5, 3, 1]] 12\n", + "[[5, 2, 4], [0, 3, 1]] 12\n", + "[[5, 0, 4], [3, 2, 1]] 12\n", + "[[3, 5, 4], [0, 2, 1]] 12\n", + "[[5, 0, 4], [3, 2, 1]] 12\n", + "[[5, 4, 1], [3, 2, 0]] 12\n", + "[[5, 0, 1], [3, 4, 2]] 12\n", + "[[3, 5, 1], [0, 4, 2]] 12\n", + "[[5, 4, 1], [0, 3, 2]] 12\n", + "[[5, 4, 1], [3, 2, 0]] 12\n", + "[[5, 0, 1], [3, 4, 2]] 12\n", + "[[4, 5, 1], [2, 0, 3]] 13\n", + "[[4, 5, 0], [2, 3, 1]] 13\n", + "[[4, 3, 5], [2, 0, 1]] 13\n", + "[[0, 3, 5], [4, 2, 1]] 13\n", + "[[4, 3, 5], [2, 0, 1]] 13\n", + "[[4, 3, 0], [2, 1, 5]] 13\n", + "[[3, 2, 5], [4, 0, 1]] 13\n", + "[[3, 2, 0], [4, 1, 5]] 13\n", + "[[0, 3, 5], [4, 2, 1]] 13\n", + "[[3, 5, 0], [4, 2, 1]] 13\n", + "[[3, 2, 5], [4, 0, 1]] 13\n", + "[[3, 2, 1], [5, 0, 4]] 13\n", + "[[3, 2, 0], [5, 4, 1]] 13\n", + "[[0, 3, 1], [5, 2, 4]] 13\n", + "[[3, 1, 0], [5, 2, 4]] 13\n", + "[[3, 2, 1], [5, 0, 4]] 13\n", + "[[0, 5, 1], [2, 3, 4]] 13\n", + "[[5, 1, 0], [2, 3, 4]] 13\n", + "[[5, 3, 1], [2, 0, 4]] 13\n", + "[[2, 1, 3], [5, 0, 4]] 13\n", + "[[2, 1, 0], [5, 4, 3]] 13\n", + "[[0, 2, 3], [5, 1, 4]] 13\n", + "[[2, 3, 0], [5, 1, 4]] 13\n", + "[[2, 1, 3], [5, 0, 4]] 13\n", + "[[0, 5, 3], [1, 2, 4]] 13\n", + "[[5, 3, 0], [1, 2, 4]] 13\n", + "[[5, 2, 3], [1, 0, 4]] 13\n", + "[[0, 4, 5], [1, 2, 3]] 13\n", + "[[4, 5, 0], [1, 2, 3]] 13\n", + "[[4, 2, 5], [1, 0, 3]] 13\n", + "[[2, 1, 5], [4, 0, 3]] 13\n", + "[[0, 1, 5], [2, 4, 3]] 13\n", + "[[4, 5, 2], [3, 0, 1]] 13\n", + "[[0, 5, 2], [4, 3, 1]] 13\n", + "[[0, 4, 2], [3, 5, 1]] 13\n", + "[[4, 2, 0], [3, 5, 1]] 13\n", + "[[4, 5, 2], [3, 0, 1]] 13\n", + "[[0, 4, 1], [3, 2, 5]] 13\n", + "[[4, 1, 0], [3, 2, 5]] 13\n", + "[[4, 2, 1], [3, 0, 5]] 13\n", + "[[0, 1, 3], [4, 2, 5]] 13\n", + "[[1, 3, 0], [4, 2, 5]] 13\n", + "[[1, 2, 3], [4, 0, 5]] 13\n", + "[[1, 5, 2], [4, 0, 3]] 13\n", + "[[1, 5, 0], [4, 3, 2]] 13\n", + "[[5, 1, 3], [4, 0, 2]] 13\n", + "[[5, 1, 0], [4, 2, 3]] 13\n", + "[[0, 5, 3], [4, 1, 2]] 13\n", + "[[5, 3, 0], [4, 1, 2]] 13\n", + "[[5, 1, 3], [4, 0, 2]] 13\n", + "[[0, 4, 3], [1, 5, 2]] 13\n", + "[[4, 3, 0], [1, 5, 2]] 13\n", + "[[4, 5, 3], [1, 0, 2]] 13\n", + "[[0, 2, 4], [1, 5, 3]] 13\n", + "[[2, 4, 0], [1, 5, 3]] 13\n", + "[[2, 5, 4], [1, 0, 3]] 13\n", + "[[5, 1, 4], [2, 0, 3]] 13\n", + "[[0, 1, 4], [5, 2, 3]] 13\n", + "[[0, 2, 4], [5, 3, 1]] 13\n", + "[[2, 4, 0], [5, 3, 1]] 13\n", + "[[2, 3, 4], [5, 0, 1]] 13\n", + "[[3, 5, 4], [2, 0, 1]] 13\n", + "[[0, 5, 4], [3, 2, 1]] 13\n", + "[[5, 4, 1], [3, 0, 2]] 13\n", + "[[5, 4, 0], [3, 2, 1]] 13\n", + "[[3, 5, 1], [4, 0, 2]] 13\n", + "[[0, 5, 1], [3, 4, 2]] 13\n", + "[[5, 4, 1], [3, 0, 2]] 13\n", + "[[0, 4, 1], [5, 3, 2]] 13\n", + "[[4, 5, 1], [0, 2, 3]] 14\n", + "[[4, 5, 1], [2, 3, 0]] 14\n", + "[[4, 0, 1], [2, 5, 3]] 14\n", + "[[3, 0, 5], [4, 2, 1]] 14\n", + "[[4, 3, 5], [0, 2, 1]] 14\n", + "[[4, 0, 3], [2, 1, 5]] 14\n", + "[[4, 3, 5], [2, 1, 0]] 14\n", + "[[3, 0, 2], [4, 1, 5]] 14\n", + "[[3, 2, 5], [4, 1, 0]] 14\n", + "[[3, 0, 5], [4, 2, 1]] 14\n", + "[[3, 5, 1], [4, 2, 0]] 14\n", + "[[3, 0, 2], [5, 4, 1]] 14\n", + "[[3, 2, 1], [5, 4, 0]] 14\n", + "[[3, 0, 1], [5, 2, 4]] 14\n", + "[[5, 3, 1], [0, 2, 4]] 14\n", + "[[3, 0, 1], [5, 2, 4]] 14\n", + "[[3, 1, 4], [5, 2, 0]] 14\n", + "[[5, 0, 1], [2, 3, 4]] 14\n", + "[[5, 1, 4], [2, 3, 0]] 14\n", + "[[5, 3, 1], [0, 2, 4]] 14\n", + "[[5, 3, 1], [2, 4, 0]] 14\n", + "[[5, 0, 1], [2, 3, 4]] 14\n", + "[[2, 0, 1], [5, 4, 3]] 14\n", + "[[2, 1, 3], [5, 4, 0]] 14\n", + "[[2, 0, 3], [5, 1, 4]] 14\n", + "[[5, 2, 3], [0, 1, 4]] 14\n", + "[[2, 0, 3], [5, 1, 4]] 14\n", + "[[2, 3, 4], [5, 1, 0]] 14\n", + "[[5, 0, 3], [1, 2, 4]] 14\n", + "[[5, 3, 4], [1, 2, 0]] 14\n", + "[[5, 2, 3], [0, 1, 4]] 14\n", + "[[5, 2, 3], [1, 4, 0]] 14\n", + "[[5, 0, 3], [1, 2, 4]] 14\n", + "[[4, 0, 5], [1, 2, 3]] 14\n", + "[[4, 5, 3], [1, 2, 0]] 14\n", + "[[4, 2, 5], [0, 1, 3]] 14\n", + "[[4, 2, 5], [1, 3, 0]] 14\n", + "[[4, 0, 5], [1, 2, 3]] 14\n", + "[[2, 1, 5], [0, 4, 3]] 14\n", + "[[2, 1, 5], [4, 3, 0]] 14\n", + "[[2, 0, 5], [4, 1, 3]] 14\n", + "[[5, 0, 2], [4, 3, 1]] 14\n", + "[[4, 5, 2], [0, 3, 1]] 14\n", + "[[4, 0, 2], [3, 5, 1]] 14\n", + "[[3, 4, 2], [0, 5, 1]] 14\n", + "[[4, 0, 2], [3, 5, 1]] 14\n", + "[[4, 2, 1], [3, 5, 0]] 14\n", + "[[4, 0, 1], [3, 2, 5]] 14\n", + "[[3, 4, 1], [0, 2, 5]] 14\n", + "[[4, 2, 1], [0, 3, 5]] 14\n", + "[[4, 2, 1], [3, 5, 0]] 14\n", + "[[4, 0, 1], [3, 2, 5]] 14\n", + "[[1, 0, 3], [4, 2, 5]] 14\n", + "[[4, 1, 3], [0, 2, 5]] 14\n", + "[[1, 2, 3], [0, 4, 5]] 14\n", + "[[1, 2, 3], [4, 5, 0]] 14\n", + "Found! at step: 14\n", + "14\n" + ] + } + ], + "source": [ + "board = [[3,2,4],[1,5,0]]\n", + "print(slidingPuzzle(board, 1, 2)) # 14" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 2, 3], [4, 5, 0]] [[1, 2, 3], [4, 5, 0]]\n", + "[[2, 1, 3], [4, 5, 0]] [[1, 2, 3], [4, 5, 0]]\n" + ] + } + ], + "source": [ + "tmp = [[1,2,3], [4,5,0]]\n", + "# tmp[1].index(0)\n", + "# if 0 in tmp[0]: x = 0, \n", + "# else: x = 1\n", + "# new_tmp = tmp.copy()\n", + "import copy\n", + "new_tmp = copy.deepcopy(tmp)\n", + "print(tmp, new_tmp)\n", + "tmp[0][0], tmp[0][1] = tmp[0][1], tmp[0][0]\n", + "print(tmp, new_tmp)" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[[[1, 2, 3], [4, 5, 0]], 0, 0, 1], [[[[1, 2, 6], [4, 5, 0]], 1, 0, 2]]]" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tmp = [[[[1,2,3], [4,5,0]], 0, 0, 1]]\n", + "tmp.append([[[[1,2,6], [4,5,0]], 1, 0, 2]])\n", + "tmp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.1 A tree version\n", + "Well. We did solve the 773 above. However, we also want a road map to the min solution. \n", + "And it seems only possible with a tree structure (that way you get a hold of the last node, find the parent, then the parent's parent, etc.)" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": {}, + "outputs": [], + "source": [ + "# def slidingPuzzle(board: List[List[int]]) -> int:\n", + "# pass\n", + "len_x = 1\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0:\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y-1))\n", + " if y <= (len_y-1):\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y+1))\n", + " if x >0:\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x-1, y))\n", + " if x <= (len_x-1):\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board, x, y):\n", + " step = 0\n", + " Q = [(board, x, y, step)]\n", + " seen = []\n", + " while len(Q)>0:\n", + " to_explore, x, y, step = Q.pop(0)\n", + " if to_explore.name == [[1,2,3], [4,5,0]]:\n", + " return to_explore.depth\n", + " \n", + " if to_explore.name in seen:\n", + " continue\n", + " else:\n", + " seen.append(to_explore.name)\n", + " if 0 in to_explore.name[0]:\n", + " x = 0\n", + " else:\n", + " x = 1\n", + " y = to_explore.name[x].index(0)\n", + " \n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, new_x, new_y = new\n", + " Q.append([new_board, new_x, new_y, step+1])\n", + " return -1\n" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n" + ] + } + ], + "source": [ + "board = Node([[1,2,3],[4,0,5]])\n", + "print(slidingPuzzle(board, 1, 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n", + "[[4, 1, 2], [5, 0, 3]]\n", + "├── [[4, 1, 2], [0, 5, 3]]\n", + "│ ├── [[4, 1, 2], [5, 0, 3]]\n", + "│ └── [[0, 1, 2], [4, 5, 3]]\n", + "│ ├── [[1, 0, 2], [4, 5, 3]]\n", + "│ │ ├── [[0, 1, 2], [4, 5, 3]]\n", + "│ │ ├── [[1, 2, 0], [4, 5, 3]]\n", + "│ │ │ ├── [[1, 0, 2], [4, 5, 3]]\n", + "│ │ │ └── [[1, 2, 3], [4, 5, 0]]\n", + "│ │ └── [[1, 5, 2], [4, 0, 3]]\n", + "│ │ ├── [[1, 5, 2], [0, 4, 3]]\n", + "│ │ ├── [[1, 5, 2], [4, 3, 0]]\n", + "│ │ └── [[1, 0, 2], [4, 5, 3]]\n", + "│ └── [[4, 1, 2], [0, 5, 3]]\n", + "├── [[4, 1, 2], [5, 3, 0]]\n", + "│ ├── [[4, 1, 2], [5, 0, 3]]\n", + "│ └── [[4, 1, 0], [5, 3, 2]]\n", + "│ ├── [[4, 0, 1], [5, 3, 2]]\n", + "│ │ ├── [[0, 4, 1], [5, 3, 2]]\n", + "│ │ │ ├── [[4, 0, 1], [5, 3, 2]]\n", + "│ │ │ └── [[5, 4, 1], [0, 3, 2]]\n", + "│ │ ├── [[4, 1, 0], [5, 3, 2]]\n", + "│ │ └── [[4, 3, 1], [5, 0, 2]]\n", + "│ │ ├── [[4, 3, 1], [0, 5, 2]]\n", + "│ │ ├── [[4, 3, 1], [5, 2, 0]]\n", + "│ │ └── [[4, 0, 1], [5, 3, 2]]\n", + "│ └── [[4, 1, 2], [5, 3, 0]]\n", + "└── [[4, 0, 2], [5, 1, 3]]\n", + " ├── [[0, 4, 2], [5, 1, 3]]\n", + " │ ├── [[4, 0, 2], [5, 1, 3]]\n", + " │ └── [[5, 4, 2], [0, 1, 3]]\n", + " │ ├── [[5, 4, 2], [1, 0, 3]]\n", + " │ │ ├── [[5, 4, 2], [0, 1, 3]]\n", + " │ │ ├── [[5, 4, 2], [1, 3, 0]]\n", + " │ │ └── [[5, 0, 2], [1, 4, 3]]\n", + " │ └── [[0, 4, 2], [5, 1, 3]]\n", + " ├── [[4, 2, 0], [5, 1, 3]]\n", + " │ ├── [[4, 0, 2], [5, 1, 3]]\n", + " │ └── [[4, 2, 3], [5, 1, 0]]\n", + " │ ├── [[4, 2, 3], [5, 0, 1]]\n", + " │ │ ├── [[4, 2, 3], [0, 5, 1]]\n", + " │ │ ├── [[4, 2, 3], [5, 1, 0]]\n", + " │ │ └── [[4, 0, 3], [5, 2, 1]]\n", + " │ └── [[4, 2, 0], [5, 1, 3]]\n", + " └── [[4, 1, 2], [5, 0, 3]]\n" + ] + } + ], + "source": [ + "board = Node([[4,1,2],[5,0,3]])\n", + "print(slidingPuzzle(board, 1, 1))\n", + "for pre, fill, node in RenderTree(board):\n", + " print(\"%s%s\" % (pre, node.name))" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "14\n" + ] + } + ], + "source": [ + "board = Node([[3,2,4],[1,5,0]])\n", + "print(slidingPuzzle(board, 1, 2)) # 14" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# dir(board)\n", + "# ??Node" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. We use BFS to solve the jigsaw problem.\n", + "Problem: Given a 3x3 list with non repeating numbers, \n", + "(e.g. [[5, 0, 3], [1, 2, 6], [8, 7, 9]]) \n", + "each time you can swap two adjacent numbers (up, down, left, right.) \n", + "search through the possible space to find the minimum steps required to sort it, \n", + "and print out the road map.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 230, + "metadata": {}, + "outputs": [], + "source": [ + "len_x = 2\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0: # left\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y-1))\n", + " if y <= (len_y-1): #right\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y+1))\n", + " if x >0: # up\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x-1, y))\n", + " if x <= (len_x-1): # down\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board):\n", + " Q = []\n", + " for x in range(3):\n", + " for y in range(3):\n", + " Q.append(board)\n", + "# Q.append((board, x, y))\n", + " seen = []\n", + " while len(Q)>0:\n", + "# import pdb; pdb.set_trace()\n", + "# to_explore, x, y = Q.pop(0)\n", + "# print(to_explore.name, to_explore.depth)\n", + " to_explore = Q.pop(0)\n", + " if len(seen)%100 == 0:\n", + " print(len(seen), to_explore.depth)\n", + " if to_explore.name == [[1,2,3], [4,5,6], [7,8,9]]:\n", + " return to_explore.depth, to_explore\n", + " for x in range(3):\n", + " for y in range(3):\n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, _, _ = new\n", + " if new_board.name not in seen:\n", + " seen.append(new_board.name)\n", + " Q.append(new_board)\n", + " return -1, None" + ] + }, + { + "cell_type": "code", + "execution_count": 224, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, Node('/[[1, 2, 3], [4, 5, 6], [7, 8, 9]]'))\n", + "CPU times: user 108 µs, sys: 29 µs, total: 137 µs\n", + "Wall time: 125 µs\n" + ] + } + ], + "source": [ + "# test\n", + "board = Node([[1,2,3],[4,5,6], [7,8,9]])\n", + "%time print(slidingPuzzle(board)) # 0" + ] + }, + { + "cell_type": "code", + "execution_count": 222, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, Node('/[[1, 2, 3], [4, 5, 6], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 8, 9]]'))\n", + "CPU times: user 11 ms, sys: 935 µs, total: 11.9 ms\n", + "Wall time: 11.1 ms\n" + ] + } + ], + "source": [ + "board = Node([[1,2,3],[4,5,6], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 1" + ] + }, + { + "cell_type": "code", + "execution_count": 223, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(2, Node('/[[1, 2, 3], [4, 6, 5], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 8, 9]]'))\n", + "CPU times: user 405 ms, sys: 16.3 ms, total: 421 ms\n", + "Wall time: 421 ms\n" + ] + } + ], + "source": [ + "board = Node([[1,2,3],[4,6,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 2" + ] + }, + { + "cell_type": "code", + "execution_count": 225, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3, Node('/[[1, 2, 3], [6, 4, 5], [7, 9, 8]]/[[1, 2, 3], [4, 6, 5], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 8, 9]]'))\n", + "CPU times: user 758 ms, sys: 4.87 ms, total: 763 ms\n", + "Wall time: 766 ms\n" + ] + } + ], + "source": [ + "board = Node([[1,2,3],[6,4,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 3" + ] + }, + { + "cell_type": "code", + "execution_count": 226, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3, Node('/[[1, 6, 3], [4, 2, 5], [7, 9, 8]]/[[1, 2, 3], [4, 6, 5], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 8, 9]]'))\n", + "CPU times: user 586 ms, sys: 4.77 ms, total: 591 ms\n", + "Wall time: 592 ms\n" + ] + } + ], + "source": [ + "board = Node([[1,6,3],[4,2,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 3" + ] + }, + { + "cell_type": "code", + "execution_count": 228, + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mslidingPuzzle\u001b[0;34m(board)\u001b[0m\n\u001b[1;32m 50\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_possibilities\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 52\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 53\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 54\u001b[0m \u001b[0mQ\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[[1, 2, 3], [4, 5, 0]], 0, 0, 1], [[[[1, 2, 6], [4, 5, 0]], 1, 0, 2]]]\n" + ] + } + ], + "source": [ + "board = Node([[4,6,3],[7,2,5], [1,9,8]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # 5" + ] + }, + { + "cell_type": "code", + "execution_count": 229, + "metadata": {}, + "outputs": [ + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mslidingPuzzle\u001b[0;34m(board)\u001b[0m\n\u001b[1;32m 50\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_possibilities\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 52\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 53\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 54\u001b[0m \u001b[0mQ\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[[1, 2, 3], [4, 5, 0]], 0, 0, 1], [[[[1, 2, 6], [4, 5, 0]], 1, 0, 2]]]\n" + ] + } + ], + "source": [ + "board = Node([[5,4,6],[9,7,2], [8,1,3]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # ghost examiner" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 231, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 0\n", + "500 2\n", + "900 3\n", + "1000 3\n", + "1800 3\n", + "2400 3\n", + "2500 3\n", + "3600 4\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mslidingPuzzle\u001b[0;34m(board)\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_possibilities\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 53\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 54\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 55\u001b[0m \u001b[0mQ\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[[1, 2, 3], [4, 5, 0]], 0, 0, 1], [[[[1, 2, 6], [4, 5, 0]], 1, 0, 2]]]\n" + ] + } + ], + "source": [ + "board = Node([[9,5,8],[2,4,1], [3,6,7]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # monster examiner" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + "# if direction=='left' and y > 0:\n", + "# board[x][y], board[x][y-1] = board[x][y-1], board[x][y]\n", + "# if direction=='right' and to_explore.name, x, yy <= (len_y-1):\n", + "# board[x][y], board[x][y+1] = board[x][y+1], board[x][y]\n", + "# if direction=='up' and x >0:\n", + "# board[x][y], board[x-1][y] = board[x-1][y], board[x][y]\n", + "# if direction=='down' and x <= (len_x-1):\n", + "# board[x][y], board[x+1][y] = board[x+1][y], board[x][y]\n", + "# return board\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# from anytree import Node, RenderTree\n", + "\n", + "# udo = Node(\"Udo\")\n", + "# marc = Node(\"Marc\", parent=udo)\n", + "# lian = Node(\"Lian\", parent=marc)\n", + "# dan = Node(\"Dan\", parent=udo)\n", + "# jet = Node(\"Jet\", parent=dan)\n", + "# jan = Node(\"Jan\", parent=dan)\n", + "# joe = Node(\"Joe\", parent=dan)\n", + "\n", + "# print(udo)\n", + "# Node('/Udo')\n", + "# print(joe)\n", + "# Node('/Udo/Dan/Joe')\n", + "\n", + "# for pre, fill, node in RenderTree(udo):\n", + "# print(\"%s%s\" % (pre, node.name))\n" + ] + } + ], + "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.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/BFS_jigsaw/773_SlidingPuzzle_BFS_and_Jigsaw-Copy1.ipynb b/BFS_jigsaw/773_SlidingPuzzle_BFS_and_Jigsaw-Copy1.ipynb new file mode 100644 index 0000000..a5219a9 --- /dev/null +++ b/BFS_jigsaw/773_SlidingPuzzle_BFS_and_Jigsaw-Copy1.ipynb @@ -0,0 +1,762 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1. We implement 773. Sliding Puzzle as a warmup\n", + "On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and an empty square represented by 0. \n", + "\n", + "A move consists of choosing 0 and a 4-directionally adjacent number and swapping it. \n", + "\n", + "The state of the board is solved if and only if the board is [[1,2,3],[4,5,0]]. \n", + "\n", + "Given a puzzle board, return the least number of moves required so that the state of the board is solved. If it is impossible for the state of the board to be solved, return -1." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# def slidingPuzzle(board: List[List[int]]) -> int:\n", + "# pass\n", + "len_x = 1\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0:\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " out_boards.append((new_board, x, y-1))\n", + " if y <= (len_y-1):\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " out_boards.append((new_board, x, y+1))\n", + " if x >0:\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " out_boards.append((new_board, x-1, y))\n", + " if x <= (len_x-1):\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " out_boards.append((new_board, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board, x, y):\n", + " step = 0\n", + " Q = [(board, x, y, step)]\n", + " seen = []\n", + " while len(Q)>0:\n", + "# import pdb; pdb.set_trace()\n", + " to_explore, x, y, step = Q.pop(0)\n", + " print(to_explore, step)\n", + " if to_explore == [[1,2,3], [4,5,0]]:\n", + " print(\"Found! at step: \",step)\n", + " return step\n", + " \n", + " if to_explore in seen:\n", + " continue\n", + " else:\n", + " seen.append(to_explore)\n", + " if 0 in to_explore[0]:\n", + " x = 0\n", + " else:\n", + " x = 1\n", + " y = to_explore[x].index(0)\n", + " \n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, new_x, new_y = new\n", + " Q.append([new_board, new_x, new_y, step+1])\n", + " return -1\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# tests:\n", + "# print(slidingPuzzle([[1,2,3], [4,5,0]]))\n", + "board = [[1,2,3],[4,0,5]]\n", + "print(slidingPuzzle(board, 1, 1)) # 1\n", + "board = [[4,1,2],[5,0,3]]\n", + "print(slidingPuzzle(board, 1, 1)) # 5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = [[3,2,4],[1,5,0]]\n", + "print(slidingPuzzle(board, 1, 2)) # 14" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tmp = [[1,2,3], [4,5,0]]\n", + "# tmp[1].index(0)\n", + "# if 0 in tmp[0]: x = 0, \n", + "# else: x = 1\n", + "# new_tmp = tmp.copy()\n", + "import copy\n", + "new_tmp = copy.deepcopy(tmp)\n", + "print(tmp, new_tmp)\n", + "tmp[0][0], tmp[0][1] = tmp[0][1], tmp[0][0]\n", + "print(tmp, new_tmp)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tmp = [[[[1,2,3], [4,5,0]], 0, 0, 1]]\n", + "tmp.append([[[[1,2,6], [4,5,0]], 1, 0, 2]])\n", + "tmp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.1 A tree version\n", + "Well. We did solve the 773 above. However, we also want a road map to the min solution. \n", + "And it seems only possible with a tree structure (that way you get a hold of the last node, find the parent, then the parent's parent, etc.)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from anytree import Node, RenderTree" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# def slidingPuzzle(board: List[List[int]]) -> int:\n", + "# pass\n", + "len_x = 1\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0:\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y-1))\n", + " if y <= (len_y-1):\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y+1))\n", + " if x >0:\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x-1, y))\n", + " if x <= (len_x-1):\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board, x, y):\n", + " step = 0\n", + " Q = [(board, x, y, step)]\n", + " seen = []\n", + " while len(Q)>0:\n", + " to_explore, x, y, step = Q.pop(0)\n", + " if to_explore.name == [[1,2,3], [4,5,0]]:\n", + " return to_explore.depth\n", + " \n", + " if to_explore.name in seen:\n", + " continue\n", + " else:\n", + " seen.append(to_explore.name)\n", + " if 0 in to_explore.name[0]:\n", + " x = 0\n", + " else:\n", + " x = 1\n", + " y = to_explore.name[x].index(0)\n", + " \n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, new_x, new_y = new\n", + " Q.append([new_board, new_x, new_y, step+1])\n", + " return -1\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[1,2,3],[4,0,5]])\n", + "print(slidingPuzzle(board, 1, 1))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[4,1,2],[5,0,3]])\n", + "print(slidingPuzzle(board, 1, 1))\n", + "for pre, fill, node in RenderTree(board):\n", + " print(\"%s%s\" % (pre, node.name))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[3,2,4],[1,5,0]])\n", + "print(slidingPuzzle(board, 1, 2)) # 14" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# dir(board)\n", + "# ??Node" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. We use BFS to solve the jigsaw problem.\n", + "Problem: Given a 3x3 list with non repeating numbers, \n", + "(e.g. [[5, 0, 3], [1, 2, 6], [8, 7, 9]]) \n", + "each time you can swap two adjacent numbers (up, down, left, right.) \n", + "search through the possible space to find the minimum steps required to sort it, \n", + "and print out the road map.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "len_x = 2\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0: # left\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y-1))\n", + " if y <= (len_y-1): #right\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y+1))\n", + " if x >0: # up\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x-1, y))\n", + " if x <= (len_x-1): # down\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board):\n", + " Q = []\n", + " for x in range(3):\n", + " for y in range(3):\n", + " Q.append(board)\n", + "# Q.append((board, x, y))\n", + " seen = []\n", + " while len(Q)>0:\n", + "# import pdb; pdb.set_trace()\n", + "# to_explore, x, y = Q.pop(0)\n", + "# print(to_explore.name, to_explore.depth)\n", + " to_explore = Q.pop(0)\n", + " if len(seen)%100 == 0:\n", + " print(len(seen), to_explore.depth)\n", + " if to_explore.name == [[1,2,3], [4,5,6], [7,8,9]]:\n", + " return to_explore.depth, to_explore\n", + " for x in range(3):\n", + " for y in range(3):\n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, _, _ = new\n", + " if new_board.name not in seen:\n", + " seen.append(new_board.name)\n", + " Q.append(new_board)\n", + " return -1, None" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# test\n", + "board = Node([[1,2,3],[4,5,6], [7,8,9]])\n", + "%time print(slidingPuzzle(board)) # 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "board = Node([[1,2,3],[4,5,6], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "board = Node([[1,2,3],[4,6,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[1,2,3],[6,4,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[1,6,3],[4,2,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[4,6,3],[7,2,5], [1,9,8]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # 5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[5,4,6],[9,7,2], [8,1,3]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # ghost examiner" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "ERROR:root:Internal Python error in the inspect module.\n", + "Below is the traceback from this internal error.\n", + "\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Traceback (most recent call last):\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/magics/execution.py\", line 1310, in time\n", + " exec(code, glob, local_ns)\n", + " File \"\", line 1, in \n", + " File \"\", line 52, in slidingPuzzle\n", + " if new_board.name not in seen:\n", + "KeyboardInterrupt\n", + "\n", + "During handling of the above exception, another exception occurred:\n", + "\n", + "Traceback (most recent call last):\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/interactiveshell.py\", line 2039, in showtraceback\n", + " stb = value._render_traceback_()\n", + "AttributeError: 'KeyboardInterrupt' object has no attribute '_render_traceback_'\n", + "\n", + "During handling of the above exception, another exception occurred:\n", + "\n", + "Traceback (most recent call last):\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/ultratb.py\", line 1101, in get_records\n", + " return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/ultratb.py\", line 319, in wrapped\n", + " return f(*args, **kwargs)\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/ultratb.py\", line 353, in _fixed_getinnerframes\n", + " records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))\n", + " File \"/Users/toby/anaconda3/envs/py36/lib/python3.6/inspect.py\", line 1490, in getinnerframes\n", + " frameinfo = (tb.tb_frame,) + getframeinfo(tb, context)\n", + " File \"/Users/toby/anaconda3/envs/py36/lib/python3.6/inspect.py\", line 1452, in getframeinfo\n", + " lines, lnum = findsource(frame)\n", + " File \"/Users/toby/.local/lib/python3.6/site-packages/IPython/core/ultratb.py\", line 185, in findsource\n", + " lines = linecache.getlines(file, globals_dict)\n", + " File \"/Users/toby/anaconda3/envs/py36/lib/python3.6/linecache.py\", line 47, in getlines\n", + " return updatecache(filename, module_globals)\n", + " File \"/Users/toby/anaconda3/envs/py36/lib/python3.6/linecache.py\", line 137, in updatecache\n", + " lines = fp.readlines()\n", + " File \"/Users/toby/anaconda3/envs/py36/lib/python3.6/codecs.py\", line 318, in decode\n", + " def decode(self, input, final=False):\n", + "KeyboardInterrupt\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "KeyboardInterrupt\n", + "\n" + ] + } + ], + "source": [ + "board = Node([[6,7,9],[2,3,8], [4,1,5]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # human examiner" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "board = Node([[7,5,1],[6,2,9], [4,3,8]])\n", + "%time tmp2 = slidingPuzzle(board)\n", + "print(tmp2) # fairy examiner" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + "# if direction=='left' and y > 0:\n", + "# board[x][y], board[x][y-1] = board[x][y-1], board[x][y]\n", + "# if direction=='right' and to_explore.name, x, yy <= (len_y-1):\n", + "# board[x][y], board[x][y+1] = board[x][y+1], board[x][y]\n", + "# if direction=='up' and x >0:\n", + "# board[x][y], board[x-1][y] = board[x-1][y], board[x][y]\n", + "# if direction=='down' and x <= (len_x-1):\n", + "# board[x][y], board[x+1][y] = board[x+1][y], board[x][y]\n", + "# return board\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# from anytree import Node, RenderTree\n", + "\n", + "# udo = Node(\"Udo\")\n", + "# marc = Node(\"Marc\", parent=udo)\n", + "# lian = Node(\"Lian\", parent=marc)\n", + "# dan = Node(\"Dan\", parent=udo)\n", + "# jet = Node(\"Jet\", parent=dan)\n", + "# jan = Node(\"Jan\", parent=dan)\n", + "# joe = Node(\"Joe\", parent=dan)\n", + "\n", + "# print(udo)\n", + "# Node('/Udo')\n", + "# print(joe)\n", + "# Node('/Udo/Dan/Joe')\n", + "\n", + "# for pre, fill, node in RenderTree(udo):\n", + "# print(\"%s%s\" % (pre, node.name))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Using TensorFlow backend.\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "from keras.preprocessing.text import Tokenizer\n", + "from keras.preprocessing.sequence import pad_sequences\n", + "\n", + "from keras.layers import Input, Embedding, Activation, Flatten, Dense\n", + "from keras.layers import Conv1D, MaxPooling1D, Dropout\n", + "from keras.models import Model" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "tk = Tokenizer(num_words=None, char_level=True, oov_token='UNK')\n", + "alphabet = \"abcdefghijklmnopqrstuvwxyz0123456789,;.!?:'\\\"/\\\\|_@#$%^&*~`+-=<>()[]{}\"\n", + "char_dict = {}\n", + "for i, char in enumerate(alphabet):\n", + " char_dict[char] = i + 1\n", + "\n", + "# # Use char_dict to replace the tk.word_index\n", + "tk.word_index = char_dict.copy()\n", + "# # Add 'UNK' to the vocabulary\n", + "tk.word_index[tk.oov_token] = max(char_dict.values()) + 1" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[9,\n", + " 43,\n", + " 13,\n", + " 69,\n", + " 10,\n", + " 21,\n", + " 19,\n", + " 20,\n", + " 69,\n", + " 1,\n", + " 69,\n", + " 20,\n", + " 5,\n", + " 19,\n", + " 20,\n", + " 9,\n", + " 14,\n", + " 7,\n", + " 69,\n", + " 19,\n", + " 20,\n", + " 18,\n", + " 9,\n", + " 14,\n", + " 7],\n", + " [1, 16, 16, 12, 5]]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "train_texts = [\"i'm just a testing string\", \"apple\"]\n", + "tk.texts_to_sequences(train_texts)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[258, 115, 101, 101, 109, 115, 259]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "word = \"seems\"\n", + "ELMO_PAD_CHAR = 260\n", + "ELMO_BOW_CHAR = 258\n", + "ELMO_EOW_CHAR = 259\n", + "chars = []\n", + "if len(word) > 0:\n", + " chars += [ELMO_BOW_CHAR]\n", + " chars += list(word.encode('utf-8', errors='ignore'))\n", + " chars += [ELMO_EOW_CHAR]\n", + "chars" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "str.encode??" + ] + }, + { + "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.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/BFS_jigsaw/773_SlidingPuzzle_BFS_and_Jigsaw.ipynb b/BFS_jigsaw/773_SlidingPuzzle_BFS_and_Jigsaw.ipynb new file mode 100644 index 0000000..108aad3 --- /dev/null +++ b/BFS_jigsaw/773_SlidingPuzzle_BFS_and_Jigsaw.ipynb @@ -0,0 +1,1224 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1. We implement 773. Sliding Puzzle as a warmup\n", + "On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and an empty square represented by 0. \n", + "\n", + "A move consists of choosing 0 and a 4-directionally adjacent number and swapping it. \n", + "\n", + "The state of the board is solved if and only if the board is [[1,2,3],[4,5,0]]. \n", + "\n", + "Given a puzzle board, return the least number of moves required so that the state of the board is solved. If it is impossible for the state of the board to be solved, return -1." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "import math\n", + "\n", + "from anytree import Node, RenderTree" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [], + "source": [ + "# def slidingPuzzle(board: List[List[int]]) -> int:\n", + "# pass\n", + "len_x = 1\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0:\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " out_boards.append((new_board, x, y-1))\n", + " if y <= (len_y-1):\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " out_boards.append((new_board, x, y+1))\n", + " if x >0:\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " out_boards.append((new_board, x-1, y))\n", + " if x <= (len_x-1):\n", + " new_board = copy.deepcopy(board)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " out_boards.append((new_board, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board, x, y):\n", + " step = 0\n", + " Q = [(board, x, y, step)]\n", + " seen = []\n", + " while len(Q)>0:\n", + "# import pdb; pdb.set_trace()\n", + " to_explore, x, y, step = Q.pop(0)\n", + " print(to_explore, step)\n", + " if to_explore == [[1,2,3], [4,5,0]]:\n", + " print(\"Found! at step: \",step)\n", + " return step\n", + " \n", + " if to_explore in seen:\n", + " continue\n", + " else:\n", + " seen.append(to_explore)\n", + " if 0 in to_explore[0]:\n", + " x = 0\n", + " else:\n", + " x = 1\n", + " y = to_explore[x].index(0)\n", + " \n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, new_x, new_y = new\n", + " Q.append([new_board, new_x, new_y, step+1])\n", + " return -1\n" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 2, 3], [4, 0, 5]] 0\n", + "[[1, 2, 3], [0, 4, 5]] 1\n", + "[[1, 2, 3], [4, 5, 0]] 1\n", + "Found! at step: 1\n", + "1\n", + "[[4, 1, 2], [5, 0, 3]] 0\n", + "[[4, 1, 2], [0, 5, 3]] 1\n", + "[[4, 1, 2], [5, 3, 0]] 1\n", + "[[4, 0, 2], [5, 1, 3]] 1\n", + "[[4, 1, 2], [5, 0, 3]] 2\n", + "[[0, 1, 2], [4, 5, 3]] 2\n", + "[[4, 1, 2], [5, 0, 3]] 2\n", + "[[4, 1, 0], [5, 3, 2]] 2\n", + "[[0, 4, 2], [5, 1, 3]] 2\n", + "[[4, 2, 0], [5, 1, 3]] 2\n", + "[[4, 1, 2], [5, 0, 3]] 2\n", + "[[1, 0, 2], [4, 5, 3]] 3\n", + "[[4, 1, 2], [0, 5, 3]] 3\n", + "[[4, 0, 1], [5, 3, 2]] 3\n", + "[[4, 1, 2], [5, 3, 0]] 3\n", + "[[4, 0, 2], [5, 1, 3]] 3\n", + "[[5, 4, 2], [0, 1, 3]] 3\n", + "[[4, 0, 2], [5, 1, 3]] 3\n", + "[[4, 2, 3], [5, 1, 0]] 3\n", + "[[0, 1, 2], [4, 5, 3]] 4\n", + "[[1, 2, 0], [4, 5, 3]] 4\n", + "[[1, 5, 2], [4, 0, 3]] 4\n", + "[[0, 4, 1], [5, 3, 2]] 4\n", + "[[4, 1, 0], [5, 3, 2]] 4\n", + "[[4, 3, 1], [5, 0, 2]] 4\n", + "[[5, 4, 2], [1, 0, 3]] 4\n", + "[[0, 4, 2], [5, 1, 3]] 4\n", + "[[4, 2, 3], [5, 0, 1]] 4\n", + "[[4, 2, 0], [5, 1, 3]] 4\n", + "[[1, 0, 2], [4, 5, 3]] 5\n", + "[[1, 2, 3], [4, 5, 0]] 5\n", + "Found! at step: 5\n", + "5\n" + ] + } + ], + "source": [ + "# tests:\n", + "# print(slidingPuzzle([[1,2,3], [4,5,0]]))\n", + "board = [[1,2,3],[4,0,5]]\n", + "print(slidingPuzzle(board, 1, 1)) # 1\n", + "board = [[4,1,2],[5,0,3]]\n", + "print(slidingPuzzle(board, 1, 1)) # 5" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[3, 2, 4], [1, 5, 0]] 0\n", + "[[3, 2, 4], [1, 0, 5]] 1\n", + "[[3, 2, 0], [1, 5, 4]] 1\n", + "[[3, 2, 4], [0, 1, 5]] 2\n", + "[[3, 2, 4], [1, 5, 0]] 2\n", + "[[3, 0, 4], [1, 2, 5]] 2\n", + "[[3, 0, 2], [1, 5, 4]] 2\n", + "[[3, 2, 4], [1, 5, 0]] 2\n", + "[[3, 2, 4], [1, 0, 5]] 3\n", + "[[0, 2, 4], [3, 1, 5]] 3\n", + "[[0, 3, 4], [1, 2, 5]] 3\n", + "[[3, 4, 0], [1, 2, 5]] 3\n", + "[[3, 2, 4], [1, 0, 5]] 3\n", + "[[0, 3, 2], [1, 5, 4]] 3\n", + "[[3, 2, 0], [1, 5, 4]] 3\n", + "[[3, 5, 2], [1, 0, 4]] 3\n", + "[[2, 0, 4], [3, 1, 5]] 4\n", + "[[3, 2, 4], [0, 1, 5]] 4\n", + "[[3, 0, 4], [1, 2, 5]] 4\n", + "[[1, 3, 4], [0, 2, 5]] 4\n", + "[[3, 0, 4], [1, 2, 5]] 4\n", + "[[3, 4, 5], [1, 2, 0]] 4\n", + "[[3, 0, 2], [1, 5, 4]] 4\n", + "[[1, 3, 2], [0, 5, 4]] 4\n", + "[[3, 5, 2], [0, 1, 4]] 4\n", + "[[3, 5, 2], [1, 4, 0]] 4\n", + "[[3, 0, 2], [1, 5, 4]] 4\n", + "[[0, 2, 4], [3, 1, 5]] 5\n", + "[[2, 4, 0], [3, 1, 5]] 5\n", + "[[2, 1, 4], [3, 0, 5]] 5\n", + "[[1, 3, 4], [2, 0, 5]] 5\n", + "[[0, 3, 4], [1, 2, 5]] 5\n", + "[[3, 4, 5], [1, 0, 2]] 5\n", + "[[3, 4, 0], [1, 2, 5]] 5\n", + "[[1, 3, 2], [5, 0, 4]] 5\n", + "[[0, 3, 2], [1, 5, 4]] 5\n", + "[[3, 5, 2], [1, 0, 4]] 5\n", + "[[0, 5, 2], [3, 1, 4]] 5\n", + "[[3, 5, 2], [1, 0, 4]] 5\n", + "[[3, 5, 0], [1, 4, 2]] 5\n", + "[[2, 0, 4], [3, 1, 5]] 6\n", + "[[2, 4, 5], [3, 1, 0]] 6\n", + "[[2, 1, 4], [0, 3, 5]] 6\n", + "[[2, 1, 4], [3, 5, 0]] 6\n", + "[[2, 0, 4], [3, 1, 5]] 6\n", + "[[1, 3, 4], [0, 2, 5]] 6\n", + "[[1, 3, 4], [2, 5, 0]] 6\n", + "[[1, 0, 4], [2, 3, 5]] 6\n", + "[[3, 4, 5], [0, 1, 2]] 6\n", + "[[3, 4, 5], [1, 2, 0]] 6\n", + "[[3, 0, 5], [1, 4, 2]] 6\n", + "[[1, 3, 2], [0, 5, 4]] 6\n", + "[[1, 3, 2], [5, 4, 0]] 6\n", + "[[1, 0, 2], [5, 3, 4]] 6\n", + "[[5, 0, 2], [3, 1, 4]] 6\n", + "[[3, 5, 2], [0, 1, 4]] 6\n", + "[[3, 0, 5], [1, 4, 2]] 6\n", + "[[3, 5, 2], [1, 4, 0]] 6\n", + "[[2, 4, 5], [3, 0, 1]] 7\n", + "[[2, 4, 0], [3, 1, 5]] 7\n", + "[[2, 1, 4], [3, 0, 5]] 7\n", + "[[0, 1, 4], [2, 3, 5]] 7\n", + "[[2, 1, 4], [3, 0, 5]] 7\n", + "[[2, 1, 0], [3, 5, 4]] 7\n", + "[[1, 3, 4], [2, 0, 5]] 7\n", + "[[1, 3, 0], [2, 5, 4]] 7\n", + "[[0, 1, 4], [2, 3, 5]] 7\n", + "[[1, 4, 0], [2, 3, 5]] 7\n", + "[[1, 3, 4], [2, 0, 5]] 7\n", + "[[3, 4, 5], [1, 0, 2]] 7\n", + "[[0, 4, 5], [3, 1, 2]] 7\n", + "[[0, 3, 5], [1, 4, 2]] 7\n", + "[[3, 5, 0], [1, 4, 2]] 7\n", + "[[3, 4, 5], [1, 0, 2]] 7\n", + "[[1, 3, 2], [5, 0, 4]] 7\n", + "[[1, 3, 0], [5, 4, 2]] 7\n", + "[[0, 1, 2], [5, 3, 4]] 7\n", + "[[1, 2, 0], [5, 3, 4]] 7\n", + "[[1, 3, 2], [5, 0, 4]] 7\n", + "[[0, 5, 2], [3, 1, 4]] 7\n", + "[[5, 2, 0], [3, 1, 4]] 7\n", + "[[5, 1, 2], [3, 0, 4]] 7\n", + "[[2, 4, 5], [0, 3, 1]] 8\n", + "[[2, 4, 5], [3, 1, 0]] 8\n", + "[[2, 0, 5], [3, 4, 1]] 8\n", + "[[1, 0, 4], [2, 3, 5]] 8\n", + "[[2, 1, 4], [0, 3, 5]] 8\n", + "[[2, 0, 1], [3, 5, 4]] 8\n", + "[[2, 1, 4], [3, 5, 0]] 8\n", + "[[1, 0, 3], [2, 5, 4]] 8\n", + "[[1, 3, 4], [2, 5, 0]] 8\n", + "[[1, 0, 4], [2, 3, 5]] 8\n", + "[[1, 4, 5], [2, 3, 0]] 8\n", + "[[4, 0, 5], [3, 1, 2]] 8\n", + "[[3, 4, 5], [0, 1, 2]] 8\n", + "[[3, 0, 5], [1, 4, 2]] 8\n", + "[[1, 3, 5], [0, 4, 2]] 8\n", + "[[1, 0, 3], [5, 4, 2]] 8\n", + "[[1, 3, 2], [5, 4, 0]] 8\n", + "[[1, 0, 2], [5, 3, 4]] 8\n", + "[[5, 1, 2], [0, 3, 4]] 8\n", + "[[1, 0, 2], [5, 3, 4]] 8\n", + "[[1, 2, 4], [5, 3, 0]] 8\n", + "[[5, 0, 2], [3, 1, 4]] 8\n", + "[[5, 2, 4], [3, 1, 0]] 8\n", + "[[5, 1, 2], [0, 3, 4]] 8\n", + "[[5, 1, 2], [3, 4, 0]] 8\n", + "[[5, 0, 2], [3, 1, 4]] 8\n", + "[[2, 4, 5], [3, 0, 1]] 9\n", + "[[0, 4, 5], [2, 3, 1]] 9\n", + "[[0, 2, 5], [3, 4, 1]] 9\n", + "[[2, 5, 0], [3, 4, 1]] 9\n", + "[[2, 4, 5], [3, 0, 1]] 9\n", + "[[0, 2, 1], [3, 5, 4]] 9\n", + "[[2, 1, 0], [3, 5, 4]] 9\n", + "[[2, 5, 1], [3, 0, 4]] 9\n", + "[[0, 1, 3], [2, 5, 4]] 9\n", + "[[1, 3, 0], [2, 5, 4]] 9\n", + "[[1, 5, 3], [2, 0, 4]] 9\n", + "[[1, 4, 5], [2, 0, 3]] 9\n", + "[[1, 4, 0], [2, 3, 5]] 9\n", + "[[0, 4, 5], [3, 1, 2]] 9\n", + "[[4, 5, 0], [3, 1, 2]] 9\n", + "[[4, 1, 5], [3, 0, 2]] 9\n", + "[[1, 3, 5], [4, 0, 2]] 9\n", + "[[0, 3, 5], [1, 4, 2]] 9\n", + "[[0, 1, 3], [5, 4, 2]] 9\n", + "[[1, 3, 0], [5, 4, 2]] 9\n", + "[[1, 4, 3], [5, 0, 2]] 9\n", + "[[5, 1, 2], [3, 0, 4]] 9\n", + "[[0, 1, 2], [5, 3, 4]] 9\n", + "[[1, 2, 4], [5, 0, 3]] 9\n", + "[[1, 2, 0], [5, 3, 4]] 9\n", + "[[5, 2, 4], [3, 0, 1]] 9\n", + "[[5, 2, 0], [3, 1, 4]] 9\n", + "[[5, 1, 2], [3, 0, 4]] 9\n", + "[[5, 1, 0], [3, 4, 2]] 9\n", + "[[4, 0, 5], [2, 3, 1]] 10\n", + "[[2, 4, 5], [0, 3, 1]] 10\n", + "[[2, 0, 5], [3, 4, 1]] 10\n", + "[[3, 2, 5], [0, 4, 1]] 10\n", + "[[2, 0, 5], [3, 4, 1]] 10\n", + "[[2, 5, 1], [3, 4, 0]] 10\n", + "[[2, 0, 1], [3, 5, 4]] 10\n", + "[[3, 2, 1], [0, 5, 4]] 10\n", + "[[2, 5, 1], [0, 3, 4]] 10\n", + "[[2, 5, 1], [3, 4, 0]] 10\n", + "[[2, 0, 1], [3, 5, 4]] 10\n", + "[[1, 0, 3], [2, 5, 4]] 10\n", + "[[2, 1, 3], [0, 5, 4]] 10\n", + "[[1, 5, 3], [0, 2, 4]] 10\n", + "[[1, 5, 3], [2, 4, 0]] 10\n", + "[[1, 0, 3], [2, 5, 4]] 10\n", + "[[1, 4, 5], [0, 2, 3]] 10\n", + "[[1, 4, 5], [2, 3, 0]] 10\n", + "[[1, 0, 5], [2, 4, 3]] 10\n", + "[[4, 0, 5], [3, 1, 2]] 10\n", + "[[4, 5, 2], [3, 1, 0]] 10\n", + "[[4, 1, 5], [0, 3, 2]] 10\n", + "[[4, 1, 5], [3, 2, 0]] 10\n", + "[[4, 0, 5], [3, 1, 2]] 10\n", + "[[1, 3, 5], [0, 4, 2]] 10\n", + "[[1, 3, 5], [4, 2, 0]] 10\n", + "[[1, 0, 5], [4, 3, 2]] 10\n", + "[[1, 0, 3], [5, 4, 2]] 10\n", + "[[5, 1, 3], [0, 4, 2]] 10\n", + "[[1, 4, 3], [0, 5, 2]] 10\n", + "[[1, 4, 3], [5, 2, 0]] 10\n", + "[[1, 0, 3], [5, 4, 2]] 10\n", + "[[1, 2, 4], [0, 5, 3]] 10\n", + "[[1, 2, 4], [5, 3, 0]] 10\n", + "[[1, 0, 4], [5, 2, 3]] 10\n", + "[[5, 2, 4], [0, 3, 1]] 10\n", + "[[5, 2, 4], [3, 1, 0]] 10\n", + "[[5, 0, 4], [3, 2, 1]] 10\n", + "[[5, 0, 1], [3, 4, 2]] 10\n", + "[[5, 1, 2], [3, 4, 0]] 10\n", + "[[0, 4, 5], [2, 3, 1]] 11\n", + "[[4, 5, 0], [2, 3, 1]] 11\n", + "[[4, 3, 5], [2, 0, 1]] 11\n", + "[[3, 2, 5], [4, 0, 1]] 11\n", + "[[0, 2, 5], [3, 4, 1]] 11\n", + "[[2, 5, 1], [3, 0, 4]] 11\n", + "[[2, 5, 0], [3, 4, 1]] 11\n", + "[[3, 2, 1], [5, 0, 4]] 11\n", + "[[0, 2, 1], [3, 5, 4]] 11\n", + "[[2, 5, 1], [3, 0, 4]] 11\n", + "[[0, 5, 1], [2, 3, 4]] 11\n", + "[[2, 1, 3], [5, 0, 4]] 11\n", + "[[0, 1, 3], [2, 5, 4]] 11\n", + "[[1, 5, 3], [2, 0, 4]] 11\n", + "[[0, 5, 3], [1, 2, 4]] 11\n", + "[[1, 5, 3], [2, 0, 4]] 11\n", + "[[1, 5, 0], [2, 4, 3]] 11\n", + "[[1, 4, 5], [2, 0, 3]] 11\n", + "[[0, 4, 5], [1, 2, 3]] 11\n", + "[[0, 1, 5], [2, 4, 3]] 11\n", + "[[1, 5, 0], [2, 4, 3]] 11\n", + "[[1, 4, 5], [2, 0, 3]] 11\n", + "[[4, 5, 2], [3, 0, 1]] 11\n", + "[[4, 5, 0], [3, 1, 2]] 11\n", + "[[4, 1, 5], [3, 0, 2]] 11\n", + "[[0, 1, 5], [4, 3, 2]] 11\n", + "[[4, 1, 5], [3, 0, 2]] 11\n", + "[[4, 1, 0], [3, 2, 5]] 11\n", + "[[1, 3, 5], [4, 0, 2]] 11\n", + "[[1, 3, 0], [4, 2, 5]] 11\n", + "[[0, 1, 5], [4, 3, 2]] 11\n", + "[[1, 5, 0], [4, 3, 2]] 11\n", + "[[1, 3, 5], [4, 0, 2]] 11\n", + "[[5, 1, 3], [4, 0, 2]] 11\n", + "[[0, 1, 3], [5, 4, 2]] 11\n", + "[[1, 4, 3], [5, 0, 2]] 11\n", + "[[0, 4, 3], [1, 5, 2]] 11\n", + "[[1, 4, 3], [5, 0, 2]] 11\n", + "[[1, 4, 0], [5, 2, 3]] 11\n", + "[[1, 2, 4], [5, 0, 3]] 11\n", + "[[0, 2, 4], [1, 5, 3]] 11\n", + "[[0, 1, 4], [5, 2, 3]] 11\n", + "[[1, 4, 0], [5, 2, 3]] 11\n", + "[[1, 2, 4], [5, 0, 3]] 11\n", + "[[5, 2, 4], [3, 0, 1]] 11\n", + "[[0, 2, 4], [5, 3, 1]] 11\n", + "[[0, 5, 4], [3, 2, 1]] 11\n", + "[[5, 4, 0], [3, 2, 1]] 11\n", + "[[5, 2, 4], [3, 0, 1]] 11\n", + "[[0, 5, 1], [3, 4, 2]] 11\n", + "[[5, 1, 0], [3, 4, 2]] 11\n", + "[[5, 4, 1], [3, 0, 2]] 11\n", + "[[4, 0, 5], [2, 3, 1]] 12\n", + "[[4, 5, 1], [2, 3, 0]] 12\n", + "[[4, 3, 5], [0, 2, 1]] 12\n", + "[[4, 3, 5], [2, 1, 0]] 12\n", + "[[4, 0, 5], [2, 3, 1]] 12\n", + "[[3, 2, 5], [0, 4, 1]] 12\n", + "[[3, 2, 5], [4, 1, 0]] 12\n", + "[[3, 0, 5], [4, 2, 1]] 12\n", + "[[3, 2, 1], [0, 5, 4]] 12\n", + "[[3, 2, 1], [5, 4, 0]] 12\n", + "[[3, 0, 1], [5, 2, 4]] 12\n", + "[[5, 0, 1], [2, 3, 4]] 12\n", + "[[2, 5, 1], [0, 3, 4]] 12\n", + "[[2, 1, 3], [0, 5, 4]] 12\n", + "[[2, 1, 3], [5, 4, 0]] 12\n", + "[[2, 0, 3], [5, 1, 4]] 12\n", + "[[5, 0, 3], [1, 2, 4]] 12\n", + "[[1, 5, 3], [0, 2, 4]] 12\n", + "[[1, 0, 5], [2, 4, 3]] 12\n", + "[[1, 5, 3], [2, 4, 0]] 12\n", + "[[4, 0, 5], [1, 2, 3]] 12\n", + "[[1, 4, 5], [0, 2, 3]] 12\n", + "[[1, 0, 5], [2, 4, 3]] 12\n", + "[[2, 1, 5], [0, 4, 3]] 12\n", + "[[4, 5, 2], [0, 3, 1]] 12\n", + "[[4, 5, 2], [3, 1, 0]] 12\n", + "[[4, 0, 2], [3, 5, 1]] 12\n", + "[[1, 0, 5], [4, 3, 2]] 12\n", + "[[4, 1, 5], [0, 3, 2]] 12\n", + "[[4, 0, 1], [3, 2, 5]] 12\n", + "[[4, 1, 5], [3, 2, 0]] 12\n", + "[[1, 0, 3], [4, 2, 5]] 12\n", + "[[1, 3, 5], [4, 2, 0]] 12\n", + "[[1, 0, 5], [4, 3, 2]] 12\n", + "[[1, 5, 2], [4, 3, 0]] 12\n", + "[[5, 1, 3], [0, 4, 2]] 12\n", + "[[5, 1, 3], [4, 2, 0]] 12\n", + "[[5, 0, 3], [4, 1, 2]] 12\n", + "[[4, 0, 3], [1, 5, 2]] 12\n", + "[[1, 4, 3], [0, 5, 2]] 12\n", + "[[1, 0, 4], [5, 2, 3]] 12\n", + "[[1, 4, 3], [5, 2, 0]] 12\n", + "[[2, 0, 4], [1, 5, 3]] 12\n", + "[[1, 2, 4], [0, 5, 3]] 12\n", + "[[1, 0, 4], [5, 2, 3]] 12\n", + "[[5, 1, 4], [0, 2, 3]] 12\n", + "[[2, 0, 4], [5, 3, 1]] 12\n", + "[[5, 2, 4], [0, 3, 1]] 12\n", + "[[5, 0, 4], [3, 2, 1]] 12\n", + "[[3, 5, 4], [0, 2, 1]] 12\n", + "[[5, 0, 4], [3, 2, 1]] 12\n", + "[[5, 4, 1], [3, 2, 0]] 12\n", + "[[5, 0, 1], [3, 4, 2]] 12\n", + "[[3, 5, 1], [0, 4, 2]] 12\n", + "[[5, 4, 1], [0, 3, 2]] 12\n", + "[[5, 4, 1], [3, 2, 0]] 12\n", + "[[5, 0, 1], [3, 4, 2]] 12\n", + "[[4, 5, 1], [2, 0, 3]] 13\n", + "[[4, 5, 0], [2, 3, 1]] 13\n", + "[[4, 3, 5], [2, 0, 1]] 13\n", + "[[0, 3, 5], [4, 2, 1]] 13\n", + "[[4, 3, 5], [2, 0, 1]] 13\n", + "[[4, 3, 0], [2, 1, 5]] 13\n", + "[[3, 2, 5], [4, 0, 1]] 13\n", + "[[3, 2, 0], [4, 1, 5]] 13\n", + "[[0, 3, 5], [4, 2, 1]] 13\n", + "[[3, 5, 0], [4, 2, 1]] 13\n", + "[[3, 2, 5], [4, 0, 1]] 13\n", + "[[3, 2, 1], [5, 0, 4]] 13\n", + "[[3, 2, 0], [5, 4, 1]] 13\n", + "[[0, 3, 1], [5, 2, 4]] 13\n", + "[[3, 1, 0], [5, 2, 4]] 13\n", + "[[3, 2, 1], [5, 0, 4]] 13\n", + "[[0, 5, 1], [2, 3, 4]] 13\n", + "[[5, 1, 0], [2, 3, 4]] 13\n", + "[[5, 3, 1], [2, 0, 4]] 13\n", + "[[2, 1, 3], [5, 0, 4]] 13\n", + "[[2, 1, 0], [5, 4, 3]] 13\n", + "[[0, 2, 3], [5, 1, 4]] 13\n", + "[[2, 3, 0], [5, 1, 4]] 13\n", + "[[2, 1, 3], [5, 0, 4]] 13\n", + "[[0, 5, 3], [1, 2, 4]] 13\n", + "[[5, 3, 0], [1, 2, 4]] 13\n", + "[[5, 2, 3], [1, 0, 4]] 13\n", + "[[0, 4, 5], [1, 2, 3]] 13\n", + "[[4, 5, 0], [1, 2, 3]] 13\n", + "[[4, 2, 5], [1, 0, 3]] 13\n", + "[[2, 1, 5], [4, 0, 3]] 13\n", + "[[0, 1, 5], [2, 4, 3]] 13\n", + "[[4, 5, 2], [3, 0, 1]] 13\n", + "[[0, 5, 2], [4, 3, 1]] 13\n", + "[[0, 4, 2], [3, 5, 1]] 13\n", + "[[4, 2, 0], [3, 5, 1]] 13\n", + "[[4, 5, 2], [3, 0, 1]] 13\n", + "[[0, 4, 1], [3, 2, 5]] 13\n", + "[[4, 1, 0], [3, 2, 5]] 13\n", + "[[4, 2, 1], [3, 0, 5]] 13\n", + "[[0, 1, 3], [4, 2, 5]] 13\n", + "[[1, 3, 0], [4, 2, 5]] 13\n", + "[[1, 2, 3], [4, 0, 5]] 13\n", + "[[1, 5, 2], [4, 0, 3]] 13\n", + "[[1, 5, 0], [4, 3, 2]] 13\n", + "[[5, 1, 3], [4, 0, 2]] 13\n", + "[[5, 1, 0], [4, 2, 3]] 13\n", + "[[0, 5, 3], [4, 1, 2]] 13\n", + "[[5, 3, 0], [4, 1, 2]] 13\n", + "[[5, 1, 3], [4, 0, 2]] 13\n", + "[[0, 4, 3], [1, 5, 2]] 13\n", + "[[4, 3, 0], [1, 5, 2]] 13\n", + "[[4, 5, 3], [1, 0, 2]] 13\n", + "[[0, 2, 4], [1, 5, 3]] 13\n", + "[[2, 4, 0], [1, 5, 3]] 13\n", + "[[2, 5, 4], [1, 0, 3]] 13\n", + "[[5, 1, 4], [2, 0, 3]] 13\n", + "[[0, 1, 4], [5, 2, 3]] 13\n", + "[[0, 2, 4], [5, 3, 1]] 13\n", + "[[2, 4, 0], [5, 3, 1]] 13\n", + "[[2, 3, 4], [5, 0, 1]] 13\n", + "[[3, 5, 4], [2, 0, 1]] 13\n", + "[[0, 5, 4], [3, 2, 1]] 13\n", + "[[5, 4, 1], [3, 0, 2]] 13\n", + "[[5, 4, 0], [3, 2, 1]] 13\n", + "[[3, 5, 1], [4, 0, 2]] 13\n", + "[[0, 5, 1], [3, 4, 2]] 13\n", + "[[5, 4, 1], [3, 0, 2]] 13\n", + "[[0, 4, 1], [5, 3, 2]] 13\n", + "[[4, 5, 1], [0, 2, 3]] 14\n", + "[[4, 5, 1], [2, 3, 0]] 14\n", + "[[4, 0, 1], [2, 5, 3]] 14\n", + "[[3, 0, 5], [4, 2, 1]] 14\n", + "[[4, 3, 5], [0, 2, 1]] 14\n", + "[[4, 0, 3], [2, 1, 5]] 14\n", + "[[4, 3, 5], [2, 1, 0]] 14\n", + "[[3, 0, 2], [4, 1, 5]] 14\n", + "[[3, 2, 5], [4, 1, 0]] 14\n", + "[[3, 0, 5], [4, 2, 1]] 14\n", + "[[3, 5, 1], [4, 2, 0]] 14\n", + "[[3, 0, 2], [5, 4, 1]] 14\n", + "[[3, 2, 1], [5, 4, 0]] 14\n", + "[[3, 0, 1], [5, 2, 4]] 14\n", + "[[5, 3, 1], [0, 2, 4]] 14\n", + "[[3, 0, 1], [5, 2, 4]] 14\n", + "[[3, 1, 4], [5, 2, 0]] 14\n", + "[[5, 0, 1], [2, 3, 4]] 14\n", + "[[5, 1, 4], [2, 3, 0]] 14\n", + "[[5, 3, 1], [0, 2, 4]] 14\n", + "[[5, 3, 1], [2, 4, 0]] 14\n", + "[[5, 0, 1], [2, 3, 4]] 14\n", + "[[2, 0, 1], [5, 4, 3]] 14\n", + "[[2, 1, 3], [5, 4, 0]] 14\n", + "[[2, 0, 3], [5, 1, 4]] 14\n", + "[[5, 2, 3], [0, 1, 4]] 14\n", + "[[2, 0, 3], [5, 1, 4]] 14\n", + "[[2, 3, 4], [5, 1, 0]] 14\n", + "[[5, 0, 3], [1, 2, 4]] 14\n", + "[[5, 3, 4], [1, 2, 0]] 14\n", + "[[5, 2, 3], [0, 1, 4]] 14\n", + "[[5, 2, 3], [1, 4, 0]] 14\n", + "[[5, 0, 3], [1, 2, 4]] 14\n", + "[[4, 0, 5], [1, 2, 3]] 14\n", + "[[4, 5, 3], [1, 2, 0]] 14\n", + "[[4, 2, 5], [0, 1, 3]] 14\n", + "[[4, 2, 5], [1, 3, 0]] 14\n", + "[[4, 0, 5], [1, 2, 3]] 14\n", + "[[2, 1, 5], [0, 4, 3]] 14\n", + "[[2, 1, 5], [4, 3, 0]] 14\n", + "[[2, 0, 5], [4, 1, 3]] 14\n", + "[[5, 0, 2], [4, 3, 1]] 14\n", + "[[4, 5, 2], [0, 3, 1]] 14\n", + "[[4, 0, 2], [3, 5, 1]] 14\n", + "[[3, 4, 2], [0, 5, 1]] 14\n", + "[[4, 0, 2], [3, 5, 1]] 14\n", + "[[4, 2, 1], [3, 5, 0]] 14\n", + "[[4, 0, 1], [3, 2, 5]] 14\n", + "[[3, 4, 1], [0, 2, 5]] 14\n", + "[[4, 2, 1], [0, 3, 5]] 14\n", + "[[4, 2, 1], [3, 5, 0]] 14\n", + "[[4, 0, 1], [3, 2, 5]] 14\n", + "[[1, 0, 3], [4, 2, 5]] 14\n", + "[[4, 1, 3], [0, 2, 5]] 14\n", + "[[1, 2, 3], [0, 4, 5]] 14\n", + "[[1, 2, 3], [4, 5, 0]] 14\n", + "Found! at step: 14\n", + "14\n" + ] + } + ], + "source": [ + "board = [[3,2,4],[1,5,0]]\n", + "print(slidingPuzzle(board, 1, 2)) # 14" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 2, 3], [4, 5, 0]] [[1, 2, 3], [4, 5, 0]]\n", + "[[2, 1, 3], [4, 5, 0]] [[1, 2, 3], [4, 5, 0]]\n" + ] + } + ], + "source": [ + "tmp = [[1,2,3], [4,5,0]]\n", + "# tmp[1].index(0)\n", + "# if 0 in tmp[0]: x = 0, \n", + "# else: x = 1\n", + "# new_tmp = tmp.copy()\n", + "import copy\n", + "new_tmp = copy.deepcopy(tmp)\n", + "print(tmp, new_tmp)\n", + "tmp[0][0], tmp[0][1] = tmp[0][1], tmp[0][0]\n", + "print(tmp, new_tmp)" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[[[1, 2, 3], [4, 5, 0]], 0, 0, 1], [[[[1, 2, 6], [4, 5, 0]], 1, 0, 2]]]" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tmp = [[[[1,2,3], [4,5,0]], 0, 0, 1]]\n", + "tmp.append([[[[1,2,6], [4,5,0]], 1, 0, 2]])\n", + "tmp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.1 A tree version\n", + "Well. We did solve the 773 above. However, we also want a road map to the min solution. \n", + "And it seems only possible with a tree structure (that way you get a hold of the last node, find the parent, then the parent's parent, etc.)" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": {}, + "outputs": [], + "source": [ + "# def slidingPuzzle(board: List[List[int]]) -> int:\n", + "# pass\n", + "len_x = 1\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0:\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y-1))\n", + " if y <= (len_y-1):\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y+1))\n", + " if x >0:\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x-1, y))\n", + " if x <= (len_x-1):\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board, x, y):\n", + " step = 0\n", + " Q = [(board, x, y, step)]\n", + " seen = []\n", + " while len(Q)>0:\n", + " to_explore, x, y, step = Q.pop(0)\n", + " if to_explore.name == [[1,2,3], [4,5,0]]:\n", + " return to_explore.depth\n", + " \n", + " if to_explore.name in seen:\n", + " continue\n", + " else:\n", + " seen.append(to_explore.name)\n", + " if 0 in to_explore.name[0]:\n", + " x = 0\n", + " else:\n", + " x = 1\n", + " y = to_explore.name[x].index(0)\n", + " \n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, new_x, new_y = new\n", + " Q.append([new_board, new_x, new_y, step+1])\n", + " return -1\n" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n" + ] + } + ], + "source": [ + "board = Node([[1,2,3],[4,0,5]])\n", + "print(slidingPuzzle(board, 1, 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n", + "[[4, 1, 2], [5, 0, 3]]\n", + "├── [[4, 1, 2], [0, 5, 3]]\n", + "│ ├── [[4, 1, 2], [5, 0, 3]]\n", + "│ └── [[0, 1, 2], [4, 5, 3]]\n", + "│ ├── [[1, 0, 2], [4, 5, 3]]\n", + "│ │ ├── [[0, 1, 2], [4, 5, 3]]\n", + "│ │ ├── [[1, 2, 0], [4, 5, 3]]\n", + "│ │ │ ├── [[1, 0, 2], [4, 5, 3]]\n", + "│ │ │ └── [[1, 2, 3], [4, 5, 0]]\n", + "│ │ └── [[1, 5, 2], [4, 0, 3]]\n", + "│ │ ├── [[1, 5, 2], [0, 4, 3]]\n", + "│ │ ├── [[1, 5, 2], [4, 3, 0]]\n", + "│ │ └── [[1, 0, 2], [4, 5, 3]]\n", + "│ └── [[4, 1, 2], [0, 5, 3]]\n", + "├── [[4, 1, 2], [5, 3, 0]]\n", + "│ ├── [[4, 1, 2], [5, 0, 3]]\n", + "│ └── [[4, 1, 0], [5, 3, 2]]\n", + "│ ├── [[4, 0, 1], [5, 3, 2]]\n", + "│ │ ├── [[0, 4, 1], [5, 3, 2]]\n", + "│ │ │ ├── [[4, 0, 1], [5, 3, 2]]\n", + "│ │ │ └── [[5, 4, 1], [0, 3, 2]]\n", + "│ │ ├── [[4, 1, 0], [5, 3, 2]]\n", + "│ │ └── [[4, 3, 1], [5, 0, 2]]\n", + "│ │ ├── [[4, 3, 1], [0, 5, 2]]\n", + "│ │ ├── [[4, 3, 1], [5, 2, 0]]\n", + "│ │ └── [[4, 0, 1], [5, 3, 2]]\n", + "│ └── [[4, 1, 2], [5, 3, 0]]\n", + "└── [[4, 0, 2], [5, 1, 3]]\n", + " ├── [[0, 4, 2], [5, 1, 3]]\n", + " │ ├── [[4, 0, 2], [5, 1, 3]]\n", + " │ └── [[5, 4, 2], [0, 1, 3]]\n", + " │ ├── [[5, 4, 2], [1, 0, 3]]\n", + " │ │ ├── [[5, 4, 2], [0, 1, 3]]\n", + " │ │ ├── [[5, 4, 2], [1, 3, 0]]\n", + " │ │ └── [[5, 0, 2], [1, 4, 3]]\n", + " │ └── [[0, 4, 2], [5, 1, 3]]\n", + " ├── [[4, 2, 0], [5, 1, 3]]\n", + " │ ├── [[4, 0, 2], [5, 1, 3]]\n", + " │ └── [[4, 2, 3], [5, 1, 0]]\n", + " │ ├── [[4, 2, 3], [5, 0, 1]]\n", + " │ │ ├── [[4, 2, 3], [0, 5, 1]]\n", + " │ │ ├── [[4, 2, 3], [5, 1, 0]]\n", + " │ │ └── [[4, 0, 3], [5, 2, 1]]\n", + " │ └── [[4, 2, 0], [5, 1, 3]]\n", + " └── [[4, 1, 2], [5, 0, 3]]\n" + ] + } + ], + "source": [ + "board = Node([[4,1,2],[5,0,3]])\n", + "print(slidingPuzzle(board, 1, 1))\n", + "for pre, fill, node in RenderTree(board):\n", + " print(\"%s%s\" % (pre, node.name))" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "14\n" + ] + } + ], + "source": [ + "board = Node([[3,2,4],[1,5,0]])\n", + "print(slidingPuzzle(board, 1, 2)) # 14" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# dir(board)\n", + "# ??Node" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. We use BFS to solve the jigsaw problem.\n", + "Problem: Given a 3x3 list with non repeating numbers, \n", + "(e.g. [[5, 0, 3], [1, 2, 6], [8, 7, 9]]) \n", + "each time you can swap two adjacent numbers (up, down, left, right.) \n", + "search through the possible space to find the minimum steps required to sort it, \n", + "and print out the road map.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 230, + "metadata": {}, + "outputs": [], + "source": [ + "len_x = 2\n", + "len_y = 2\n", + "def search_board(board, start_pos):\n", + " \"\"\"Given a board and starting position and moving direction,\n", + " make the move and return a new board.\n", + " e.g. [[1,2,3], [4,5,0]], start_pos=1, 2 (which is 0), dir=left,\n", + " return [[1,2,3], [4,0,5]]\"\"\"\n", + " x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + " out_boards = []\n", + " if y > 0: # left\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y-1] = new_board[x][y-1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y-1))\n", + " if y <= (len_y-1): #right\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x][y+1] = new_board[x][y+1], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x, y+1))\n", + " if x >0: # up\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x-1][y] = new_board[x-1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x-1, y))\n", + " if x <= (len_x-1): # down\n", + " new_board = copy.deepcopy(board.name)\n", + " new_board[x][y], new_board[x+1][y] = new_board[x+1][y], new_board[x][y]\n", + " new_node = Node(new_board, parent=board)\n", + " out_boards.append((new_node, x+1, y))\n", + " return out_boards\n", + "\n", + "def slidingPuzzle(board):\n", + " Q = []\n", + " for x in range(3):\n", + " for y in range(3):\n", + " Q.append(board)\n", + "# Q.append((board, x, y))\n", + " seen = []\n", + " while len(Q)>0:\n", + "# import pdb; pdb.set_trace()\n", + "# to_explore, x, y = Q.pop(0)\n", + "# print(to_explore.name, to_explore.depth)\n", + " to_explore = Q.pop(0)\n", + " if len(seen)%100 == 0:\n", + " print(len(seen), to_explore.depth)\n", + " if to_explore.name == [[1,2,3], [4,5,6], [7,8,9]]:\n", + " return to_explore.depth, to_explore\n", + " for x in range(3):\n", + " for y in range(3):\n", + " new_possibilities = search_board(board=to_explore, start_pos=(x,y))\n", + " for index, new in enumerate(new_possibilities):\n", + " new_board, _, _ = new\n", + " if new_board.name not in seen:\n", + " seen.append(new_board.name)\n", + " Q.append(new_board)\n", + " return -1, None" + ] + }, + { + "cell_type": "code", + "execution_count": 224, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, Node('/[[1, 2, 3], [4, 5, 6], [7, 8, 9]]'))\n", + "CPU times: user 108 µs, sys: 29 µs, total: 137 µs\n", + "Wall time: 125 µs\n" + ] + } + ], + "source": [ + "# test\n", + "board = Node([[1,2,3],[4,5,6], [7,8,9]])\n", + "%time print(slidingPuzzle(board)) # 0" + ] + }, + { + "cell_type": "code", + "execution_count": 222, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, Node('/[[1, 2, 3], [4, 5, 6], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 8, 9]]'))\n", + "CPU times: user 11 ms, sys: 935 µs, total: 11.9 ms\n", + "Wall time: 11.1 ms\n" + ] + } + ], + "source": [ + "board = Node([[1,2,3],[4,5,6], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 1" + ] + }, + { + "cell_type": "code", + "execution_count": 223, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(2, Node('/[[1, 2, 3], [4, 6, 5], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 8, 9]]'))\n", + "CPU times: user 405 ms, sys: 16.3 ms, total: 421 ms\n", + "Wall time: 421 ms\n" + ] + } + ], + "source": [ + "board = Node([[1,2,3],[4,6,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 2" + ] + }, + { + "cell_type": "code", + "execution_count": 225, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3, Node('/[[1, 2, 3], [6, 4, 5], [7, 9, 8]]/[[1, 2, 3], [4, 6, 5], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 8, 9]]'))\n", + "CPU times: user 758 ms, sys: 4.87 ms, total: 763 ms\n", + "Wall time: 766 ms\n" + ] + } + ], + "source": [ + "board = Node([[1,2,3],[6,4,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 3" + ] + }, + { + "cell_type": "code", + "execution_count": 226, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3, Node('/[[1, 6, 3], [4, 2, 5], [7, 9, 8]]/[[1, 2, 3], [4, 6, 5], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 9, 8]]/[[1, 2, 3], [4, 5, 6], [7, 8, 9]]'))\n", + "CPU times: user 586 ms, sys: 4.77 ms, total: 591 ms\n", + "Wall time: 592 ms\n" + ] + } + ], + "source": [ + "board = Node([[1,6,3],[4,2,5], [7,9,8]])\n", + "%time print(slidingPuzzle(board)) # 3" + ] + }, + { + "cell_type": "code", + "execution_count": 228, + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mslidingPuzzle\u001b[0;34m(board)\u001b[0m\n\u001b[1;32m 50\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_possibilities\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 52\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 53\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 54\u001b[0m \u001b[0mQ\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[[1, 2, 3], [4, 5, 0]], 0, 0, 1], [[[[1, 2, 6], [4, 5, 0]], 1, 0, 2]]]\n" + ] + } + ], + "source": [ + "board = Node([[4,6,3],[7,2,5], [1,9,8]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # 5" + ] + }, + { + "cell_type": "code", + "execution_count": 229, + "metadata": {}, + "outputs": [ + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mslidingPuzzle\u001b[0;34m(board)\u001b[0m\n\u001b[1;32m 50\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_possibilities\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 52\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 53\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 54\u001b[0m \u001b[0mQ\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[[1, 2, 3], [4, 5, 0]], 0, 0, 1], [[[[1, 2, 6], [4, 5, 0]], 1, 0, 2]]]\n" + ] + } + ], + "source": [ + "board = Node([[5,4,6],[9,7,2], [8,1,3]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # ghost examiner" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 231, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 0\n", + "500 2\n", + "900 3\n", + "1000 3\n", + "1800 3\n", + "2400 3\n", + "2500 3\n", + "3600 4\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mslidingPuzzle\u001b[0;34m(board)\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_possibilities\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 52\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 53\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 54\u001b[0m \u001b[0mseen\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 55\u001b[0m \u001b[0mQ\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew_board\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[[1, 2, 3], [4, 5, 0]], 0, 0, 1], [[[[1, 2, 6], [4, 5, 0]], 1, 0, 2]]]\n" + ] + } + ], + "source": [ + "board = Node([[9,5,8],[2,4,1], [3,6,7]])\n", + "%time tmp = slidingPuzzle(board)\n", + "print(tmp) # monster examiner" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# x, y = start_pos # pack it in a tuple (x,y) fashion.\n", + "# if direction=='left' and y > 0:\n", + "# board[x][y], board[x][y-1] = board[x][y-1], board[x][y]\n", + "# if direction=='right' and to_explore.name, x, yy <= (len_y-1):\n", + "# board[x][y], board[x][y+1] = board[x][y+1], board[x][y]\n", + "# if direction=='up' and x >0:\n", + "# board[x][y], board[x-1][y] = board[x-1][y], board[x][y]\n", + "# if direction=='down' and x <= (len_x-1):\n", + "# board[x][y], board[x+1][y] = board[x+1][y], board[x][y]\n", + "# return board\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# from anytree import Node, RenderTree\n", + "\n", + "# udo = Node(\"Udo\")\n", + "# marc = Node(\"Marc\", parent=udo)\n", + "# lian = Node(\"Lian\", parent=marc)\n", + "# dan = Node(\"Dan\", parent=udo)\n", + "# jet = Node(\"Jet\", parent=dan)\n", + "# jan = Node(\"Jan\", parent=dan)\n", + "# joe = Node(\"Joe\", parent=dan)\n", + "\n", + "# print(udo)\n", + "# Node('/Udo')\n", + "# print(joe)\n", + "# Node('/Udo/Dan/Joe')\n", + "\n", + "# for pre, fill, node in RenderTree(udo):\n", + "# print(\"%s%s\" % (pre, node.name))\n" + ] + } + ], + "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.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/BasicCsharp_List.cs b/BasicCsharp_List.cs new file mode 100644 index 0000000..8dd49d8 --- /dev/null +++ b/BasicCsharp_List.cs @@ -0,0 +1,47 @@ +// 1. Init different data structures +using System; +using System.Collections.Generic; + +class Program +{ + static void Main() + { + // 1.1 Init List with input content + List list1 = new List() + { + "carrot", + "fox", + "exploer" + }; + + var list2 = new List() + { + "carrot", + "fox", + "exploer" + }; + + // 1.2 Init List with array as input + string[] array = {"carrot", "fox", "exploer"}; + List list3 = new List(array); + + // 1.3 Init List with capacity + List list4 = new List(3); + list4.Add(null); + list4.Add(null); + list4.Add(null); + list4[0] = "carrot"; + list4[1] = "fox"; + list4[2] = "exploer"; + + // 1.4 use Add method with unspecified pre condi + List list5 = new List(); + list5.Add("carrot"); + list5.Add("fox"); + list5.Add("exploer"); + + + // 2. Dictionary with Tuple + public Dictionary, int> store = new Dictionary, int>(); + } +} \ No newline at end of file diff --git a/BasicCsharp_functions.cs b/BasicCsharp_functions.cs new file mode 100644 index 0000000..b5d24f1 --- /dev/null +++ b/BasicCsharp_functions.cs @@ -0,0 +1,15 @@ + + + + + // 1. in order traverse of a tree function, + // !! a function without return (change in place) + // !! pass in a list as function parameter + public void inOrder(TreeNode node, List list){ + if (node != null) + { + inOrder(node.left, list); + list.Add(node.val); + inOrder(node.right, list); + } + } \ No newline at end of file diff --git a/LinkedList.py b/LinkedList.py new file mode 100644 index 0000000..b3f86d9 --- /dev/null +++ b/LinkedList.py @@ -0,0 +1,40 @@ +class ListNode(object): + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + def __repr__(self): + out = "LinkedList Node: " + str(self.val) + cur = self.next + while cur: + out += "->" + str(cur.val) + cur = cur.next + out += " [end]" + return out + + def __str__(self): + out = "LinkedList Node: " + str(self.val) + cur = self.next + while cur: + out += "->" + str(cur.val) + cur = cur.next + out += " [end]" + return out + + def insert(self, val=0, next=None): + if self.next is None: + self.next = ListNode(val=val, next=next) + else: + cur = self.next + while cur.next: + cur = cur.next + cur.next = ListNode(val=val, next=next) + + +class LinkedList(object): + def __init__(self, head): + # head = ListNode + self.head = head + + def __repr__(self): + pass diff --git a/Linked_list_related.ipynb b/Linked_list_related.ipynb new file mode 100644 index 0000000..1a713c3 --- /dev/null +++ b/Linked_list_related.ipynb @@ -0,0 +1,582 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "class ListNode(object):\n", + " def __init__(self, val=0, next=None):\n", + " self.val = val\n", + " self.next = next" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "LN1 = ListNode(2, ListNode(4, ListNode(3)))\n", + "LN2 = ListNode(5, ListNode(6, ListNode(4)))\n", + "LN3 = ListNode(5, ListNode(6, ListNode(4, ListNode(1))))" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "num1=2, num2=5, tmp_num=7, total_num=7\n", + "num1=4, num2=6, tmp_num=100, total_num=107\n", + "num1=3, num2=4, tmp_num=700, total_num=807\n" + ] + } + ], + "source": [ + "def addTwoNumbers(l1, l2):\n", + " \"\"\"\n", + " :type l1: ListNode\n", + " :type l2: ListNode\n", + " :rtype: ListNode\n", + " \"\"\"\n", + " digit = 0\n", + " total_num = 0\n", + " while l1 and l2:\n", + " num1 = l1.val\n", + " num2 = l2.val\n", + " tmp_num = (num1+num2)*(10**digit)\n", + " total_num += tmp_num\n", + " print(f\"num1={num1}, num2={num2}, tmp_num={tmp_num}, total_num={total_num}\")\n", + " l1 = l1.next\n", + " l2 = l2.next\n", + " digit += 1\n", + "\n", + " while l1: #l2 exhausted\n", + " num1 = l1.val\n", + " tmp_num = num1 * (10**digit)\n", + " total_num += tmp_num\n", + " print(f\"num1={num1}, num2={num2}, tmp_num={tmp_num}, total_num={total_num}\")\n", + " l1 = l1.next\n", + " digit += 1\n", + "\n", + " while l2:\n", + " num2 = l2.val\n", + " tmp_num = num2 * (10**digit)\n", + " total_num += tmp_num\n", + " print(f\"num1={num1}, num2={num2}, tmp_num={tmp_num}, total_num={total_num}\")\n", + " l2 = l2.next\n", + " digit += 1\n", + " \n", + "# out = ListNode(0,ListNode())\n", + "# tmp = out.next\n", + "# for i in list(str(total_num))[::-1]:\n", + "# # print(i)\n", + "# tmp.val = int(i)\n", + "# tmp.next = ListNode()\n", + "# tmp = tmp.next\n", + "# return out.next\n", + " return total_num\n", + "\n", + "\n", + "total_num = addTwoNumbers(LN1, LN2) #807" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "num1=2, num2=5, tmp_num=7, total_num=7\n", + "num1=4, num2=6, tmp_num=100, total_num=107\n", + "num1=3, num2=4, tmp_num=700, total_num=807\n", + "num1=3, num2=1, tmp_num=1000, total_num=1807\n" + ] + }, + { + "data": { + "text/plain": [ + "1807" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total_num = addTwoNumbers(LN1, LN3) #1807\n", + "total_num" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "num1=0, num2=1, tmp_num=1, total_num=1\n" + ] + }, + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total_num = addTwoNumbers(ListNode(0), ListNode(1))\n", + "total_num" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [], + "source": [ + "if len(str(total_num)) <= 1:\n", + " return ListNode(total_num)\n", + "\n", + "out = ListNode(0,ListNode())\n", + "tmp = out.next\n", + "out_nums = [int(_) for _ in list(str(total_num))][::-1]\n", + "for i in range(len(out_nums)-1):\n", + " print(i, out_nums[i])\n", + " tmp.val = out_nums[i]\n", + " tmp.next = ListNode(out_nums[i+1])\n", + " tmp = tmp.next\n", + "tmp=None\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'NoneType' object has no attribute 'val'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mout\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mval\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'NoneType' object has no attribute 'val'" + ] + } + ], + "source": [ + "out.next.next.next.val" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 64, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "out.val" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 1\n", + "1 -3\n", + "2 -3\n", + "3 9\n", + "4 -1\n", + "5 -2\n", + "6 5\n" + ] + } + ], + "source": [ + "nums = [-2,1,-3, -3, 9,-1, -2, 5]\n", + "for i, n in enumerate(nums[1:]):\n", + " print(i,n)" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "i=0, num=-2, cur_sum=-2, max_sum=-2\n", + "i=1, num=1, cur_sum=1, max_sum=1\n", + "i=2, num=-3, cur_sum=-2, max_sum=1\n", + "i=3, num=-3, cur_sum=-3, max_sum=1\n", + "i=4, num=9, cur_sum=9, max_sum=9\n", + "i=5, num=-1, cur_sum=8, max_sum=9\n", + "i=6, num=-2, cur_sum=6, max_sum=9\n", + "i=7, num=5, cur_sum=11, max_sum=11\n" + ] + }, + { + "data": { + "text/plain": [ + "11" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def maxSubArray(nums: 'List[int]') -> 'int':\n", + " n = len(nums)\n", + " curr_sum = max_sum = nums[0]\n", + " print(f\"i={0}, num={nums[0]}, cur_sum={curr_sum}, max_sum={max_sum}\")\n", + " for i in range(1, n):\n", + " curr_sum = max(nums[i], curr_sum + nums[i])\n", + " max_sum = max(max_sum, curr_sum)\n", + " print(f\"i={i}, num={nums[i]}, cur_sum={curr_sum}, max_sum={max_sum}\")\n", + " return max_sum\n", + "\n", + "maxSubArray(nums)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from collections import defaultdict\n", + "words = " + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 0\n", + "0 1\n", + "0 3\n", + "1 0\n", + "1 1\n", + "1 3\n", + "2 0\n", + "2 1\n", + "2 3\n", + "3 0\n", + "3 1\n", + "3 3\n", + "4 0\n", + "4 1\n", + "4 3\n" + ] + } + ], + "source": [ + "for i in range(5):\n", + " for j in range(4):\n", + " if j == 2:\n", + " continue\n", + " print(i,j)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "defaultdict(.()>,\n", + " {'l': 1, 'e': 2, 't': 1})" + ] + }, + "execution_count": 91, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def count_str_to_dict(string):\n", + " # given a string, count number of characters into a dict\n", + " from collections import defaultdict\n", + " outD = defaultdict(lambda: 0)\n", + " for s in string:\n", + " outD[s] += 1\n", + " return outD\n", + "\n", + "count_str_to_dict(\"leet\")" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'abc'" + ] + }, + "execution_count": 93, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\".join(sorted(\"cba\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from LinkedList import ListNode" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "LinkedList Node: 2->3 [end]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tmp = ListNode(2, ListNode(3))\n", + "tmp" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "tmp.insert(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "LinkedList Node: 2->3->1 [end]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tmp" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "LinkedList Node: 0->1 [end]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tmp = ListNode()\n", + "tmp.insert(1)\n", + "tmp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [], + "source": [ + "S = \"ababcbacadefegdehijhklij\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 8 ['b', 'c'] ['d', 'e', 'f', 'e', 'g', 'd', 'e', 'h', 'i', 'j', 'h', 'k', 'l', 'i', 'j']\n", + "9 15 ['g', 'f', 'e'] ['h', 'i', 'j', 'h', 'k', 'l', 'i', 'j']\n", + "16 23 ['i', 'j', 'l', 'k'] []\n" + ] + } + ], + "source": [ + "start_index = 0\n", + "# search_index = 1\n", + "out = []\n", + "while start_index < len(S):\n", + " # start with first letter, find the last apperance of this letter\n", + " # and save all the seen letters within\n", + " start_word = S[start_index]\n", + " words_within = []\n", + " tmp_words = []\n", + " for search_index in range(start_index, len(S)):\n", + " if S[search_index] == start_word or S[search_index] in words_within:\n", + " words_within.extend(list(set(tmp_words)))\n", + " tmp_words = []\n", + " end_index = search_index\n", + " else:\n", + " tmp_words.append(S[search_index])\n", + " print(start_index, end_index, words_within, tmp_words)\n", + " out.append(end_index+1-start_index)\n", + " start_index = end_index+1\n", + " \n", + "# break\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[9, 7, 8]" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "out" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "end_index" + ] + }, + { + "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.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Untitled.ipynb b/Untitled.ipynb deleted file mode 100644 index 6d8f65f..0000000 --- a/Untitled.ipynb +++ /dev/null @@ -1,52 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0, 1]\n", - "[2, 3, 4, 5, 6]\n" - ] - } - ], - "source": [ - "a = [0,1,2,3,4,5,6]\n", - "print(a[:2])\n", - "print(a[2:])" - ] - }, - { - "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.6.7" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/__pycache__/LinkedList.cpython-36.pyc b/__pycache__/LinkedList.cpython-36.pyc new file mode 100644 index 0000000..1f72448 Binary files /dev/null and b/__pycache__/LinkedList.cpython-36.pyc differ diff --git a/akuna.py b/akuna.py index 8ab523b..bde79e1 100644 --- a/akuna.py +++ b/akuna.py @@ -30,6 +30,7 @@ def unusual_sort(numbers): #%% +def whatever(n, intList): delta = n # initalize the int to store difference between sum and n if sum(intList) < n: return False #impossible diff --git a/plot_directed.py b/plot_directed.py new file mode 100644 index 0000000..d664430 --- /dev/null +++ b/plot_directed.py @@ -0,0 +1,53 @@ +""" +============== +Directed Graph +============== + +Draw a graph with directed edges using a colormap and different node sizes. + +Edges have different colors and alphas (opacity). Drawn using matplotlib. +""" + +import matplotlib as mpl +import matplotlib.pyplot as plt +import networkx as nx + +testFLights = [[10, 14, 43], [1, 12, 62], [4, 2, 62], [14, 10, 49], [9, 5, 29], [13, 7, 53], [4, 12, 90], [14, 9, 38], [11, 2, 64], [2, 13, 92], [11, 5, 42], [10, 1, 89], [14, 0, 32], [9, 4, 81], [3, 6, 97], [7, 13, 35], [11, 9, 63], [5, 7, 82], [13, 6, 57], [4, 5, 100], [2, 9, 34], [11, 13, 1], [14, 8, 1], [12, 10, 42], [2, 4, 41], [0, 6, 55], [ + 5, 12, 1], [13, 3, 67], [3, 13, 36], [3, 12, 73], [7, 5, 72], [5, 6, 100], [7, 6, 52], [4, 7, 43], [6, 3, 67], [3, 1, 66], [8, 12, 30], [8, 3, 42], [9, 3, 57], [12, 6, 31], [2, 7, 10], [14, 4, 91], [2, 3, 29], [8, 9, 29], [2, 11, 65], [3, 8, 49], [6, 14, 22], [4, 6, 38], [13, 0, 78], [1, 10, 97], [8, 14, 40], [7, 9, 3], [14, 6, 4], [4, 8, 75], [1, 6, 56]] + +seed = 13648 # Seed random number generators for reproducibility +# G = nx.random_k_out_graph(10, 3, 0.5, seed=seed) +G = nx.DiGraph() +for source, destination, weight in testFLights: + G.add_edge(str(source), str(destination), weight=weight) + +pos = nx.spring_layout(G, seed=seed) + +node_sizes = [3 + 10 * i for i in range(len(G))] +M = G.number_of_edges() +edge_colors = range(2, M + 2) +edge_alphas = [(5 + i) / (M + 4) for i in range(M)] +cmap = plt.cm.plasma + +nodes = nx.draw_networkx_nodes(G, pos, node_size=node_sizes, node_color="indigo") +edges = nx.draw_networkx_edges( + G, + pos, + node_size=node_sizes, + arrowstyle="->", + arrowsize=10, + edge_color=edge_colors, + edge_cmap=cmap, + width=2, +) +# set alpha value for each edge +# for i in range(M): +# edges[i].set_alpha(edge_alphas[i]) + +# pc = mpl.collections.PatchCollection(edges, cmap=cmap) +# pc.set_array(edge_colors) + +ax = plt.gca() +ax.set_axis_off() +# plt.colorbar(pc, ax=ax) +plt.show() diff --git a/tmp.py b/tmp.py new file mode 100644 index 0000000..c5f3628 --- /dev/null +++ b/tmp.py @@ -0,0 +1,58 @@ +# import math + +# N = 1000 +# table = [None for _ in range(N + 2)] # p_i (0) +# table[2], table[3] = 1, 2 +# index = 4 + +# while index <= N: +# table[index] = (index - 1) * (table[index - 1] + table[index - 2]) +# index += 1 + +# print(table[N] / math.factorial(N)) + +# def bubble_sort(a): +# for i in range(n, 0, -1): # i = n, n - 1, ..., 1 +# for j in range(1, i): # j = 1, 2, ..., i - 1 +# if a[j] > a[j + 1]: +# a[j], a[j + 1] = a[j + 1], a[j] # swap +# return a + + +# # def rec(n): +# # if n == 2: +# # return 2 +# # return 2 * rec(n // 2) + n + + +# # print(rec(2048)) + + +# total = 0 +# for i in range(1, 12): +# top = i * 2 ** (i - 1) +# total += top +# print(f"i = {i}, top = {top}, total = {total}") + + +array = [4, 6, 10, 8, 2, 1] +m = 3 + +start = 0 +end = m + +maxSum = sum(array[start:end]) +print("maxSum = ", maxSum) +cur = maxSum + +while end < len(array) - 1: + cur -= array[start] + start += 1 + cur += array[end] + end += 1 + maxSum = max(maxSum, cur) + print("maxSum = ", maxSum) + +result = sum(array) - maxSum + +print(result) diff --git "a/\350\203\214\346\235\277-\345\215\225\350\260\203\346\240\210-monoStack.py" "b/\350\203\214\346\235\277-\345\215\225\350\260\203\346\240\210-monoStack.py" new file mode 100644 index 0000000..bc5a17b --- /dev/null +++ "b/\350\203\214\346\235\277-\345\215\225\350\260\203\346\240\210-monoStack.py" @@ -0,0 +1,31 @@ +""" +monotonic stack is a super useful tool in many code challenges, +such as 84. Largest Rectangle in Histogram, 1950.Maximum-of-Minimum-Values-in-All-Subarrays, etc. +find more in https://github.com/wisdompeak/LeetCode (and search for monotonic stack key word) + +Here is one basic way of realizing it. +""" +heights = [] # input list + +n = len(heights) + +stack = [] +nextSmaller = [n] * n +for i in range(n): + while stack and height[stack[-1]] > height[i]: + nextSmaller[stack.pop(-1)] = i + stack.append(i) + +stack = [] +prevSmaller = [-1] * n +for i in range(n, -1, -1): + while stack and height[stack[-1]] > height[i]: + prevSmaller[stack.pop(-1)] = i + stack.append(i) + +# for example in the 84. histogram area question +ret = 0 +for i in range(n): + area = heights[i] * (nextSmaller[i] - prevSmaller[i] - 1) + ret = max(ret, area) +return ret