├── Binary Search ├── binary_search_template.py ├── first_bad_version.py ├── peak_finding.py ├── problems.py └── search_in_rotated_sorted_array.py ├── Common Sense guide to DS ├── Dijkstra's Algorithm.py ├── Doubly Linked List.py ├── Linear search in an ordered array.py ├── QUICKSELECT.py ├── binary search in an ordered array.py ├── bubble sort.py ├── double linked list.py ├── duplicate value.py ├── graphs.py ├── hash table.py ├── insertion sort.py ├── intersection of arrays.py ├── linked list.py ├── ordered array.py ├── queues.py ├── quick sort.py ├── quicksort and quickselect new.py ├── recursion intro.py ├── selection sort.py ├── stacks.py └── test.py ├── Google Data Structures ├── Binary Trees.py ├── Graph Traversal BFS.py ├── Graph Traversals DFS.py ├── Graphs quiz.py ├── Graphs representation.py ├── Linked List CSDojo.py ├── Linked List Google.py ├── binary search google.py ├── binary search trees.py ├── bubble sort.py ├── hash table.py ├── merge sort.py ├── queue google.py ├── quick sort.py ├── recursion google.py ├── stacks google.py ├── test.py └── venv │ ├── Lib │ ├── site-packages │ │ ├── easy-install.pth │ │ ├── pip-9.0.1-py3.7.egg │ │ │ ├── EGG-INFO │ │ │ │ ├── PKG-INFO │ │ │ │ ├── SOURCES.txt │ │ │ │ ├── dependency_links.txt │ │ │ │ ├── entry_points.txt │ │ │ │ ├── not-zip-safe │ │ │ │ ├── requires.txt │ │ │ │ └── top_level.txt │ │ │ └── pip │ │ │ │ ├── __init__.py │ │ │ │ ├── __main__.py │ │ │ │ ├── _vendor │ │ │ │ ├── __init__.py │ │ │ │ ├── appdirs.py │ │ │ │ ├── cachecontrol │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _cmd.py │ │ │ │ │ ├── adapter.py │ │ │ │ │ ├── cache.py │ │ │ │ │ ├── caches │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── file_cache.py │ │ │ │ │ │ └── redis_cache.py │ │ │ │ │ ├── compat.py │ │ │ │ │ ├── controller.py │ │ │ │ │ ├── filewrapper.py │ │ │ │ │ ├── heuristics.py │ │ │ │ │ ├── serialize.py │ │ │ │ │ └── wrapper.py │ │ │ │ ├── colorama │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── ansi.py │ │ │ │ │ ├── ansitowin32.py │ │ │ │ │ ├── initialise.py │ │ │ │ │ ├── win32.py │ │ │ │ │ └── winterm.py │ │ │ │ ├── distlib │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _backport │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── misc.py │ │ │ │ │ │ ├── shutil.py │ │ │ │ │ │ ├── sysconfig.cfg │ │ │ │ │ │ ├── sysconfig.py │ │ │ │ │ │ └── tarfile.py │ │ │ │ │ ├── compat.py │ │ │ │ │ ├── database.py │ │ │ │ │ ├── index.py │ │ │ │ │ ├── locators.py │ │ │ │ │ ├── manifest.py │ │ │ │ │ ├── markers.py │ │ │ │ │ ├── metadata.py │ │ │ │ │ ├── resources.py │ │ │ │ │ ├── scripts.py │ │ │ │ │ ├── t32.exe │ │ │ │ │ ├── t64.exe │ │ │ │ │ ├── util.py │ │ │ │ │ ├── version.py │ │ │ │ │ ├── w32.exe │ │ │ │ │ ├── w64.exe │ │ │ │ │ └── wheel.py │ │ │ │ ├── distro.py │ │ │ │ ├── html5lib │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _ihatexml.py │ │ │ │ │ ├── _inputstream.py │ │ │ │ │ ├── _tokenizer.py │ │ │ │ │ ├── _trie │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── _base.py │ │ │ │ │ │ ├── datrie.py │ │ │ │ │ │ └── py.py │ │ │ │ │ ├── _utils.py │ │ │ │ │ ├── constants.py │ │ │ │ │ ├── filters │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── alphabeticalattributes.py │ │ │ │ │ │ ├── base.py │ │ │ │ │ │ ├── inject_meta_charset.py │ │ │ │ │ │ ├── lint.py │ │ │ │ │ │ ├── optionaltags.py │ │ │ │ │ │ ├── sanitizer.py │ │ │ │ │ │ └── whitespace.py │ │ │ │ │ ├── html5parser.py │ │ │ │ │ ├── serializer.py │ │ │ │ │ ├── treeadapters │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── genshi.py │ │ │ │ │ │ └── sax.py │ │ │ │ │ ├── treebuilders │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── base.py │ │ │ │ │ │ ├── dom.py │ │ │ │ │ │ ├── etree.py │ │ │ │ │ │ └── etree_lxml.py │ │ │ │ │ └── treewalkers │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── base.py │ │ │ │ │ │ ├── dom.py │ │ │ │ │ │ ├── etree.py │ │ │ │ │ │ ├── etree_lxml.py │ │ │ │ │ │ └── genshi.py │ │ │ │ ├── ipaddress.py │ │ │ │ ├── lockfile │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── linklockfile.py │ │ │ │ │ ├── mkdirlockfile.py │ │ │ │ │ ├── pidlockfile.py │ │ │ │ │ ├── sqlitelockfile.py │ │ │ │ │ └── symlinklockfile.py │ │ │ │ ├── ordereddict.py │ │ │ │ ├── packaging │ │ │ │ │ ├── __about__.py │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── _compat.py │ │ │ │ │ ├── _structures.py │ │ │ │ │ ├── markers.py │ │ │ │ │ ├── requirements.py │ │ │ │ │ ├── specifiers.py │ │ │ │ │ ├── utils.py │ │ │ │ │ └── version.py │ │ │ │ ├── pkg_resources │ │ │ │ │ └── __init__.py │ │ │ │ ├── progress │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── bar.py │ │ │ │ │ ├── counter.py │ │ │ │ │ ├── helpers.py │ │ │ │ │ └── spinner.py │ │ │ │ ├── pyparsing.py │ │ │ │ ├── re-vendor.py │ │ │ │ ├── requests │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── adapters.py │ │ │ │ │ ├── api.py │ │ │ │ │ ├── auth.py │ │ │ │ │ ├── cacert.pem │ │ │ │ │ ├── certs.py │ │ │ │ │ ├── compat.py │ │ │ │ │ ├── cookies.py │ │ │ │ │ ├── exceptions.py │ │ │ │ │ ├── hooks.py │ │ │ │ │ ├── models.py │ │ │ │ │ ├── packages │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── chardet │ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ │ ├── big5freq.py │ │ │ │ │ │ │ ├── big5prober.py │ │ │ │ │ │ │ ├── chardetect.py │ │ │ │ │ │ │ ├── chardistribution.py │ │ │ │ │ │ │ ├── charsetgroupprober.py │ │ │ │ │ │ │ ├── charsetprober.py │ │ │ │ │ │ │ ├── codingstatemachine.py │ │ │ │ │ │ │ ├── compat.py │ │ │ │ │ │ │ ├── constants.py │ │ │ │ │ │ │ ├── cp949prober.py │ │ │ │ │ │ │ ├── escprober.py │ │ │ │ │ │ │ ├── escsm.py │ │ │ │ │ │ │ ├── eucjpprober.py │ │ │ │ │ │ │ ├── euckrfreq.py │ │ │ │ │ │ │ ├── euckrprober.py │ │ │ │ │ │ │ ├── euctwfreq.py │ │ │ │ │ │ │ ├── euctwprober.py │ │ │ │ │ │ │ ├── gb2312freq.py │ │ │ │ │ │ │ ├── gb2312prober.py │ │ │ │ │ │ │ ├── hebrewprober.py │ │ │ │ │ │ │ ├── jisfreq.py │ │ │ │ │ │ │ ├── jpcntx.py │ │ │ │ │ │ │ ├── langbulgarianmodel.py │ │ │ │ │ │ │ ├── langcyrillicmodel.py │ │ │ │ │ │ │ ├── langgreekmodel.py │ │ │ │ │ │ │ ├── langhebrewmodel.py │ │ │ │ │ │ │ ├── langhungarianmodel.py │ │ │ │ │ │ │ ├── langthaimodel.py │ │ │ │ │ │ │ ├── latin1prober.py │ │ │ │ │ │ │ ├── mbcharsetprober.py │ │ │ │ │ │ │ ├── mbcsgroupprober.py │ │ │ │ │ │ │ ├── mbcssm.py │ │ │ │ │ │ │ ├── sbcharsetprober.py │ │ │ │ │ │ │ ├── sbcsgroupprober.py │ │ │ │ │ │ │ ├── sjisprober.py │ │ │ │ │ │ │ ├── universaldetector.py │ │ │ │ │ │ │ └── utf8prober.py │ │ │ │ │ │ └── urllib3 │ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ │ ├── _collections.py │ │ │ │ │ │ │ ├── connection.py │ │ │ │ │ │ │ ├── connectionpool.py │ │ │ │ │ │ │ ├── contrib │ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ │ ├── appengine.py │ │ │ │ │ │ │ ├── ntlmpool.py │ │ │ │ │ │ │ ├── pyopenssl.py │ │ │ │ │ │ │ └── socks.py │ │ │ │ │ │ │ ├── exceptions.py │ │ │ │ │ │ │ ├── fields.py │ │ │ │ │ │ │ ├── filepost.py │ │ │ │ │ │ │ ├── packages │ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ │ ├── ordered_dict.py │ │ │ │ │ │ │ ├── six.py │ │ │ │ │ │ │ └── ssl_match_hostname │ │ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ │ │ └── _implementation.py │ │ │ │ │ │ │ ├── poolmanager.py │ │ │ │ │ │ │ ├── request.py │ │ │ │ │ │ │ ├── response.py │ │ │ │ │ │ │ └── util │ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ │ ├── connection.py │ │ │ │ │ │ │ ├── request.py │ │ │ │ │ │ │ ├── response.py │ │ │ │ │ │ │ ├── retry.py │ │ │ │ │ │ │ ├── ssl_.py │ │ │ │ │ │ │ ├── timeout.py │ │ │ │ │ │ │ └── url.py │ │ │ │ │ ├── sessions.py │ │ │ │ │ ├── status_codes.py │ │ │ │ │ ├── structures.py │ │ │ │ │ └── utils.py │ │ │ │ ├── retrying.py │ │ │ │ ├── six.py │ │ │ │ └── webencodings │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── labels.py │ │ │ │ │ ├── mklabels.py │ │ │ │ │ ├── tests.py │ │ │ │ │ └── x_user_defined.py │ │ │ │ ├── basecommand.py │ │ │ │ ├── baseparser.py │ │ │ │ ├── cmdoptions.py │ │ │ │ ├── commands │ │ │ │ ├── __init__.py │ │ │ │ ├── check.py │ │ │ │ ├── completion.py │ │ │ │ ├── download.py │ │ │ │ ├── freeze.py │ │ │ │ ├── hash.py │ │ │ │ ├── help.py │ │ │ │ ├── install.py │ │ │ │ ├── list.py │ │ │ │ ├── search.py │ │ │ │ ├── show.py │ │ │ │ ├── uninstall.py │ │ │ │ └── wheel.py │ │ │ │ ├── compat │ │ │ │ ├── __init__.py │ │ │ │ └── dictconfig.py │ │ │ │ ├── download.py │ │ │ │ ├── exceptions.py │ │ │ │ ├── index.py │ │ │ │ ├── locations.py │ │ │ │ ├── models │ │ │ │ ├── __init__.py │ │ │ │ └── index.py │ │ │ │ ├── operations │ │ │ │ ├── __init__.py │ │ │ │ ├── check.py │ │ │ │ └── freeze.py │ │ │ │ ├── pep425tags.py │ │ │ │ ├── req │ │ │ │ ├── __init__.py │ │ │ │ ├── req_file.py │ │ │ │ ├── req_install.py │ │ │ │ ├── req_set.py │ │ │ │ └── req_uninstall.py │ │ │ │ ├── status_codes.py │ │ │ │ ├── utils │ │ │ │ ├── __init__.py │ │ │ │ ├── appdirs.py │ │ │ │ ├── build.py │ │ │ │ ├── deprecation.py │ │ │ │ ├── encoding.py │ │ │ │ ├── filesystem.py │ │ │ │ ├── glibc.py │ │ │ │ ├── hashes.py │ │ │ │ ├── logging.py │ │ │ │ ├── outdated.py │ │ │ │ ├── packaging.py │ │ │ │ ├── setuptools_build.py │ │ │ │ └── ui.py │ │ │ │ ├── vcs │ │ │ │ ├── __init__.py │ │ │ │ ├── bazaar.py │ │ │ │ ├── git.py │ │ │ │ ├── mercurial.py │ │ │ │ └── subversion.py │ │ │ │ └── wheel.py │ │ ├── setuptools-28.8.0-py3.7.egg │ │ └── setuptools.pth │ └── tcl8.6 │ │ └── init.tcl │ ├── Scripts │ ├── Activate.ps1 │ ├── _asyncio.pyd │ ├── _bz2.pyd │ ├── _contextvars.pyd │ ├── _ctypes.pyd │ ├── _ctypes_test.pyd │ ├── _decimal.pyd │ ├── _distutils_findvs.pyd │ ├── _elementtree.pyd │ ├── _hashlib.pyd │ ├── _lzma.pyd │ ├── _msi.pyd │ ├── _multiprocessing.pyd │ ├── _overlapped.pyd │ ├── _queue.pyd │ ├── _socket.pyd │ ├── _sqlite3.pyd │ ├── _ssl.pyd │ ├── _testbuffer.pyd │ ├── _testcapi.pyd │ ├── _testconsole.pyd │ ├── _testimportmultiple.pyd │ ├── _testmultiphase.pyd │ ├── _tkinter.pyd │ ├── activate │ ├── activate.bat │ ├── deactivate.bat │ ├── easy_install-3.7-script.py │ ├── easy_install-3.7.exe │ ├── easy_install-script.py │ ├── easy_install.exe │ ├── libcrypto-1_1-x64.dll │ ├── libssl-1_1-x64.dll │ ├── pip-script.py │ ├── pip.exe │ ├── pip3-script.py │ ├── pip3.7-script.py │ ├── pip3.7.exe │ ├── pip3.exe │ ├── pyexpat.pyd │ ├── python.exe │ ├── python3.dll │ ├── python37.dll │ ├── pythonw.exe │ ├── select.pyd │ ├── sqlite3.dll │ ├── tcl86t.dll │ ├── tk86t.dll │ ├── unicodedata.pyd │ ├── vcruntime140.dll │ └── winsound.pyd │ └── pyvenv.cfg ├── Greedy Algorithms ├── activity_selection.py ├── fractional_knapsack.py ├── maximize_reward_matrix.py ├── minimum_energy.py ├── smallest_string.py └── two_city_interview_scheduling.py ├── README.md ├── Sorting ├── bubble_sort.py ├── insertion_sort.py ├── merge_sort.py ├── playground.py ├── quick_sort.py ├── quickselect.py └── selection_sort.py ├── Trees ├── Binary Search Trees │ ├── binary_search_tree.py │ ├── closest_value_in_BST.py │ └── is_valid_bst.py ├── binary_tree_topologies.py ├── construct binary tree with inorder and postorder.py ├── heaps │ ├── heap_sort.py │ ├── max_heap.py │ └── min_heap.py ├── in-order traversal.py ├── invert_binary_tree.py ├── k_distance_nodes_binary_tree.py ├── level-order traversal recursion.py ├── level-order traversal.py ├── lowest common ancestor.py ├── path sum.py ├── populating next pointers.py ├── post-order traversal.py ├── pre-order traversal.py ├── serialize and deserialize a binary tree.py ├── symmetric tree recursion.py └── unique_binary_trees.py ├── amazonOA ├── amazon_prime_air_route.py ├── k_distinct_substrings.py ├── leetcode_problems.py ├── shopping_patterns.py └── turnstile.py ├── arrays ├── addition_with_carry.py ├── intersection of two arrays.py ├── merge_k_sorted_arrays.py ├── playground.py └── sliding window │ ├── fixed_size_max_subarray.py │ ├── important_problems.py │ ├── longest_substring.py │ ├── max_sum_subarray.py │ ├── smallest_subarray_with_given_sum.py │ └── subarray_with_K_distinct_elements.py ├── dynamic-programming ├── 01_knapsack.py ├── bottom_up │ ├── climbing_n_stairs_III.py │ ├── factorial.py │ ├── fibonacci.py │ ├── longest_common_subsequence.py │ ├── max_contiguos_sum.py │ ├── max_contiguous_sum_II.py │ ├── max_contiguous_sum_III.py │ ├── range_sum_query.py │ ├── range_sum_query_2D.py │ └── recurrence_sum.py ├── edit_distance.py ├── fibonacci-dp.py ├── graph.jpg ├── important_problems.py ├── longest_common_subsequence.py ├── longest_contiguos_palindrome.py ├── n_choose_k.py ├── parenthesization.py ├── playground.py ├── shortest-path-dp.py ├── text-justification.py └── text_justification_II.py ├── graphs ├── cableConnections.py ├── captureSurroundedRegions.py ├── cycleDetection.py ├── cycles_of_length_n.py ├── dijkstras.py ├── disjoint_sets_array.py ├── disjoint_sets_tree.py ├── friendsCircles.py ├── graph_rep.py ├── informAllEmployees.py ├── isGraphBipartite.py ├── numberOfIslands.py ├── numberOfIslands_disjointSet.py ├── product_of_length_of_cycles.py ├── removeStones.py ├── rottenOranges.py ├── shortestPathBinaryMatrix.py ├── topological_sort.py └── updateMatrix.py ├── hash table ├── hashMap.py ├── hashSet.py ├── important_problems.py └── playground.py ├── linked lists ├── linked list.py ├── playground.py ├── queues with linked lists.py └── stacks with linked lists.py └── recursion and backtracking ├── backtracking ├── combinations.py ├── combinations_with_repetitions.py ├── important_problems.py ├── k_equal_sum_partitions.py ├── kth_smallest_instructions.py ├── maze.py ├── maze2.py ├── mini-sudoku.py ├── nqueens.py ├── nqueensII.py ├── playground.py ├── string_permutation.py └── sudoku_solver.py └── recursion ├── kth_grammar.py ├── kth_odd_natural_number.py ├── kth_power_of_2.py ├── largestRectangleArea.py ├── merge_two_linked_lists.py ├── n_combinations.py ├── pascals_triangle_nth_row.py ├── pow_x_n.py ├── reverse_linked_list.py ├── search_in_2D_matrix_I.py ├── search_in_BST.py ├── search_in_a_2D_matrix_II.py ├── swap_nodes_in_pairs_linked_list.py └── tower_of_hanoi.py /Binary Search/binary_search_template.py: -------------------------------------------------------------------------------- 1 | def binary_search(arr, target): 2 | i = 0 3 | j = len(arr) 4 | while i < j: 5 | middle_index = (i + j) // 2 6 | if arr[middle_index] == target: 7 | return middle_index 8 | elif arr[middle_index] < target: 9 | i = middle_index + 1 10 | else: 11 | j = middle_index - 1 12 | return False 13 | 14 | def binary_search_recursion(arr, target, start, end): 15 | if start >= end: 16 | return False 17 | middle_index = (start + end) // 2 18 | if arr[middle_index] == target: 19 | return middle_index 20 | elif arr[middle_index] > target: 21 | return binary_search_recursion(arr, target, start, end-1) 22 | else: 23 | return binary_search_recursion(arr, target, start+1, end) 24 | 25 | arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 26 | target = 10 27 | print(binary_search(arr1, target)) 28 | print(binary_search_recursion(arr1, target, 0, len(arr1))) -------------------------------------------------------------------------------- /Binary Search/peak_finding.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Find Peak in 1D and 2D arrays using binary search 3 | ''' 4 | import numpy as np 5 | 6 | def find_peak_1D(arr, start, end): 7 | mid = (start + end) // 2 8 | if mid+1 < len(arr): 9 | if arr[mid] <= arr[mid+1]: 10 | return find_peak_1D(arr, mid+1, end) 11 | if mid-1 >= 0: 12 | if arr[mid] <= arr[mid-1]: 13 | return find_peak_1D(arr, start, mid-1) 14 | return mid 15 | 16 | arr = [1, 2, 4, 5, 6, 3, 2, 1] 17 | print(find_peak_1D(arr, 0, len(arr)-1)) 18 | 19 | def find_peak_2D(matrix, start_col, end_col): 20 | j = (start_col + end_col) // 2 21 | i = np.argmax(matrix[:, j]) 22 | if j + 1 < matrix.shape[1]: 23 | if matrix[i, j] <= matrix[i, j+1]: 24 | return find_peak_2D(matrix, j+1, end_col) 25 | if j - 1 >= 0: 26 | if matrix[i, j] < matrix[i, j-1]: 27 | return find_peak_2D(matrix, start_col, j-1) 28 | return matrix[i, j] 29 | 30 | matrix = np.array([[11, 12, 13, 14], [5, 6, 8, 25], [17, 18, 19, 20]]) 31 | print(find_peak_2D(matrix, 0, matrix.shape[1]-1)) -------------------------------------------------------------------------------- /Binary Search/problems.py: -------------------------------------------------------------------------------- 1 | def binary_search(arr, target): 2 | start = 0 3 | end = len(arr) 4 | while start < end: 5 | middle_index = (start + end) // 2 6 | if arr[middle_index] == target: 7 | return middle_index 8 | elif target > arr[middle_index]: 9 | start = middle_index + 1 10 | else: 11 | end = middle_index - 1 12 | return -1 13 | 14 | def find_first(arr, target): 15 | ''' 16 | Find the index of first element if the element has duplicates 17 | ''' 18 | index = binary_search(arr, target) 19 | if index == -1: 20 | return False 21 | while index >= 0: 22 | if arr[index] != target: 23 | return index + 1 24 | index -= 1 25 | return index + 1 26 | 27 | def find_first_last(arr, target): 28 | ''' 29 | find the start index and end index of the target if it has duplicates 30 | ''' 31 | index = binary_search(arr, target) 32 | if index == -1: 33 | return False 34 | first_index = index 35 | while first_index >= 0: 36 | if arr[first_index] != target: 37 | break 38 | first_index -= 1 39 | first_index += 1 40 | last_index = index 41 | while last_index < len(arr): 42 | if arr[last_index] != target: 43 | break 44 | last_index += 1 45 | last_index -= 1 46 | return [first_index, last_index] 47 | 48 | 49 | 50 | multiple = [1, 1, 3, 5, 7, 7, 7, 8, 11, 12, 12] 51 | target = 1 52 | 53 | 54 | 55 | print(find_first(multiple, target)) 56 | print(find_first_last(multiple, target)) -------------------------------------------------------------------------------- /Binary Search/search_in_rotated_sorted_array.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array which is sorted and rotated, find a target, e.g., [4, 5, 0, 1, 2, 3] 3 | ''' 4 | 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | 8 | def binary_search_recursive(arr, target, start, end): 9 | if start > end: 10 | return -1 11 | mid = (start + end) // 2 12 | # check if we've found the target 13 | if arr[mid] == target: 14 | return mid 15 | # check if mid lies in left sorted part 16 | if arr[start] <= arr[mid]: # left part is sorted 17 | # now lets check if the target lies in the left sorted part 18 | if arr[start] <= target < arr[mid]: 19 | return binary_search_recursive(arr, target, start, mid-1) 20 | else: 21 | return binary_search_recursive(arr, target, mid+1, end) 22 | # check if mid lies on the right sorted part 23 | elif arr[mid] <= arr[end]: 24 | # now check if target lies in the right sorted part 25 | if arr[mid] < target <= arr[end]: 26 | return binary_search_recursive(arr, target, mid+1, end) 27 | else: 28 | return binary_search_recursive(arr, target, start, mid-1) 29 | 30 | arr = [6, 7, 8, 1, 2, 3, 4, 5] 31 | plt.plot(arr) 32 | plt.show() 33 | # look at the above graph to understand how left sorted and right sorted parts look like 34 | target = 1 35 | print(binary_search_recursive(arr, target, 0, len(arr)-1)) -------------------------------------------------------------------------------- /Common Sense guide to DS/Linear search in an ordered array.py: -------------------------------------------------------------------------------- 1 | class Ordered_Array(): 2 | def __init__(self, list): 3 | self.list = sorted(list) 4 | 5 | def append(self, value): 6 | if len(self.list)==0: 7 | self.list.append(value) 8 | else: 9 | index = 0 10 | while(value>=self.list[index]): 11 | index+=1 12 | if index >= len(self.list): 13 | break 14 | self.list.insert(index, value) 15 | 16 | def linear_search(self, value): 17 | index = 0 18 | while(value>=self.list[index]): 19 | if value==self.list[index]: 20 | return index 21 | index+=1 22 | if index >= len(self.list): 23 | break 24 | return False 25 | 26 | def __str__(self): 27 | return str(self.list) 28 | 29 | arr1 = Ordered_Array([]) 30 | arr1.append(2) 31 | arr1.append(3) 32 | arr1.append(7) 33 | arr1.append(6) 34 | arr1.append(4) 35 | arr1.append(13) 36 | arr1.append(12) 37 | arr1.append(10) 38 | 39 | print(arr1) 40 | print(arr1.linear_search(8)) -------------------------------------------------------------------------------- /Common Sense guide to DS/bubble sort.py: -------------------------------------------------------------------------------- 1 | 2 | def bubble_sort(array): 3 | unsorted_till_index = len(array)-1 4 | while True: 5 | swaps = 0 6 | for i in range(unsorted_till_index): 7 | # swap if condition 8 | if array[i]>array[i+1]: 9 | # swap 10 | array[i], array[i+1] = array[i+1], array[i] 11 | swaps+=1 12 | unsorted_till_index -=1 13 | # if no swaps, break the loop 14 | if swaps==0: 15 | break 16 | 17 | arr1 = [4, 2, 7, 1, 3] 18 | bubble_sort(arr1) 19 | print(arr1) 20 | 21 | -------------------------------------------------------------------------------- /Common Sense guide to DS/duplicate value.py: -------------------------------------------------------------------------------- 1 | 2 | # this function is used to check for duplicate values in linear time 3 | 4 | def isDuplicate(array): 5 | # Let's initialize a very large empty array 6 | existingNumbers = [None]*10000 7 | '''So basically, we will iterate through the array once, and we will consider the values of input array 8 | as the indices of the existingNumbers array(hence we initialized a very large existingNumbers Array). 9 | Let's discuss through an example: 10 | Consider the array [4, 2, 7, 3, 4, 1] 11 | So initially, in the existingNumbers Array, 12 | the values in the indices: 4, 2, 7, 3 will be initialized as 1 13 | but when it encounters the value 4 again (after 7), since 4 is already filled with 7, it returns True 14 | There's only one for loop (Iterates through the array only once) and hence it's time complexity is O(N) 15 | ''' 16 | for i in range(len(array)): 17 | if not existingNumbers[array[i]]: 18 | existingNumbers[array[i]]=1 19 | else: 20 | return True 21 | return False 22 | 23 | print(isDuplicate([4, 2, 3])) 24 | -------------------------------------------------------------------------------- /Common Sense guide to DS/graphs.py: -------------------------------------------------------------------------------- 1 | 2 | # let's create a graph data structure 3 | # it shows relationships of people 4 | 5 | # this is an example of a directed graph. based off twitter 6 | 7 | class Person: 8 | def __init__(self, name): 9 | self.name = name 10 | self.friends = [] 11 | 12 | def add_friend(self, name): 13 | '''adds a friend to the person''' 14 | 15 | self.friends.append(name) 16 | 17 | def show_friends(self): 18 | '''prints all the friends''' 19 | 20 | print(self.friends) 21 | 22 | 23 | john = Person("john") 24 | john.add_friend("katy") 25 | john.add_friend("halsey") 26 | john.add_friend("poker") 27 | 28 | john.show_friends() 29 | print(john.name) -------------------------------------------------------------------------------- /Common Sense guide to DS/hash table.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # my version 4 | 5 | class HashTable(): 6 | def __init__(self): 7 | self.table = [None]*10000 8 | 9 | def HashFunction(self, string): 10 | string = string.upper() 11 | code = {chr(i): i - 64 for i in range(65, (65 + 26))} 12 | hashValue = sum([code[i] for i in string]) 13 | return hashValue 14 | 15 | def store(self, string): 16 | hv = self.HashFunction(string) 17 | if self.table[hv]: 18 | self.table[hv].append(string) 19 | else: 20 | self.table[hv] = [string] 21 | 22 | def lookup(self, string): 23 | hv = self.HashFunction(string) 24 | if self.table[hv]: 25 | if string in self.table[hv]: 26 | return True 27 | return False 28 | 29 | def __repr__(self): 30 | return str(self.table) 31 | 32 | x = HashTable() 33 | x.store("ABC") 34 | x.store("CAB") 35 | print(x.lookup("ABC")) 36 | 37 | -------------------------------------------------------------------------------- /Common Sense guide to DS/insertion sort.py: -------------------------------------------------------------------------------- 1 | 2 | def insertion_sort(array): 3 | for i in range(1, len(array)): 4 | temp_index = i 5 | temp_value = array[i] 6 | while temp_index>0 and array[temp_index-1]>temp_value: 7 | array[temp_index] = array[temp_index-1] 8 | temp_index = temp_index-1 9 | array[temp_index] = temp_value 10 | 11 | 12 | arr1 = [4, 2, 7, 1, 3] 13 | insertion_sort(arr1) 14 | print(arr1) 15 | arr2 = [3, 7, 1, 8, 9] 16 | print(arr2) -------------------------------------------------------------------------------- /Common Sense guide to DS/intersection of arrays.py: -------------------------------------------------------------------------------- 1 | 2 | # function which returns the intersection between two arrays 3 | 4 | def intersection(array1, array2): 5 | itn = [] 6 | for i in range(len(array1)): 7 | for j in range(len(array2)): 8 | if array1[i] == array2[j]: 9 | itn.append(array2[j]) 10 | break 11 | return itn 12 | 13 | arr1 = [1, 3, 5, 7, 34] 14 | arr2 = [3, 1, 22, 23, 12] 15 | 16 | print(intersection(arr1, arr2)) 17 | -------------------------------------------------------------------------------- /Common Sense guide to DS/ordered array.py: -------------------------------------------------------------------------------- 1 | 2 | # in an ordered array, everything is sorted 3 | # It sorts as soon as we append 4 | 5 | class Ordered_Array(): 6 | def __init__(self, list): 7 | self.list = sorted(list) 8 | 9 | def append(self, value): 10 | if len(self.list)==0: 11 | self.list.append(value) 12 | else: 13 | index = 0 14 | while(value>=self.list[index]): 15 | index+=1 16 | if index >= len(self.list): 17 | break 18 | self.list.insert(index, value) 19 | 20 | def __str__(self): 21 | return str(self.list) 22 | 23 | arr1 = Ordered_Array([]) 24 | arr1.append(2) 25 | arr1.append(3) 26 | arr1.append(7) 27 | arr1.append(6) 28 | arr1.append(4) 29 | 30 | print(arr1) 31 | 32 | -------------------------------------------------------------------------------- /Common Sense guide to DS/queues.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | '''To implement a queue, use collections.deque which was designed to have fast appends and pops from both ends.''' 4 | 5 | from collections import deque 6 | 7 | # Let's implement the code of a printing machine with help of a queue 8 | 9 | class PrintingMachine(): 10 | def __init__(self): 11 | self.document = deque([]) 12 | 13 | def insert_paper(self, paper): 14 | self.document.append(paper) 15 | 16 | def start_printing(self): 17 | while self.document: 18 | print("Printing {}...".format(self.document.popleft())) 19 | if not self.document: 20 | print("Completed") 21 | 22 | # let's define the document to be printed 23 | nitwMag = PrintingMachine() 24 | 25 | # let's add the papers 26 | nitwMag.insert_paper("Cover Page front") 27 | nitwMag.insert_paper("Acknowledgement") 28 | nitwMag.insert_paper("Words of Appraisal") 29 | nitwMag.insert_paper("Meet the Team") 30 | nitwMag.insert_paper("Index") 31 | nitwMag.insert_paper("Content") 32 | nitwMag.insert_paper("Cover page back") 33 | 34 | # Let's starts printing 35 | nitwMag.start_printing() 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Common Sense guide to DS/recursion intro.py: -------------------------------------------------------------------------------- 1 | 2 | # let's implement a simple countdown using recursion 3 | 4 | def countdown(time): 5 | print(time) 6 | if time==0: 7 | return 8 | else: 9 | return countdown(time-1) 10 | countdown(10) -------------------------------------------------------------------------------- /Common Sense guide to DS/selection sort.py: -------------------------------------------------------------------------------- 1 | 2 | def selection_sort(array): 3 | for i in range(len(array)): 4 | lowest_so_far = i 5 | print("The new array is {}".format(arr1)) 6 | print("lowest_so_far is {}".format(array[lowest_so_far])) 7 | for j in range(i+1, len(array)): 8 | if array[j]middle_element: 27 | input_list = input_list[(middle_index+1):] 28 | print("{} > {}".format(value, middle_element)) 29 | print("New array is {}".format(input_list), "\n") 30 | first_index=index+1 31 | i+=1 32 | elif valueinput_array[j+1]: 11 | temp = input_array[j+1] 12 | input_array[j+1] = input_array[j] 13 | input_array[j]=temp 14 | print("The new array is {}".format(input_array)) 15 | return input_array 16 | 17 | arr1 = [12, 23, 343, 21, 67,55 , 3, 67] 18 | 19 | print(bubble_sort(arr1)) -------------------------------------------------------------------------------- /Google Data Structures/hash table.py: -------------------------------------------------------------------------------- 1 | """Write a HashTable class that stores strings 2 | in a hash table, where keys are calculated 3 | using the first two letters of the string.""" 4 | 5 | 6 | class HashTable(object): 7 | def __init__(self): 8 | self.table = [None]*10000 9 | 10 | def store(self, string): 11 | hv = self.calculate_hash_value(string) 12 | if hv != -1: 13 | # if value is already present in that index, store both values 14 | if self.table[hv] != None: 15 | self.table[hv].append(string) 16 | # if value is not present in that index, then store it 17 | else: 18 | self.table[hv] = [string] 19 | 20 | def lookup(self, string): 21 | hv = self.calculate_hash_value(string) 22 | if hv != -1: 23 | if self.table[hv] != None: 24 | if string in self.table[hv]: 25 | return hv 26 | return -1 27 | 28 | def calculate_hash_value(self, string): 29 | value = ord(string[0])*100 + ord(string[1]) 30 | return value 31 | 32 | # Setup 33 | hash_table = HashTable() 34 | 35 | # Test calculate_hash_value 36 | # Should be 8568 37 | print(hash_table.calculate_hash_value('UDACITY')) 38 | 39 | # Test lookup edge case 40 | # Should be -1 41 | print(hash_table.lookup('UDACITY')) 42 | 43 | # Test store 44 | hash_table.store('UDACITY') 45 | # Should be 8568 46 | print(hash_table.lookup('UDACITY')) 47 | 48 | # Test store edge case 49 | hash_table.store('UDACIOUS') 50 | # Should be 8568 51 | print(hash_table.lookup('UDACIOUS')) 52 | 53 | print(hash_table.table[8568]) 54 | -------------------------------------------------------------------------------- /Google Data Structures/merge sort.py: -------------------------------------------------------------------------------- 1 | def mergeSort(alist): 2 | # splitting 3 | print("Splitting the list: ",alist) 4 | if len(alist)>1: 5 | mid = len(alist)//2 6 | lefthalf = alist[:mid] 7 | righthalf = alist[mid:] 8 | print("The left half is: ", lefthalf) 9 | print("the right half is: ", righthalf) 10 | print() 11 | 12 | mergeSort(lefthalf) 13 | mergeSort(righthalf) 14 | 15 | i=0 16 | j=0 17 | k=0 18 | 19 | # merging the list 20 | while i < len(lefthalf) and j < len(righthalf): 21 | if lefthalf[i] < righthalf[j]: 22 | alist[k]=lefthalf[i] 23 | i=i+1 24 | else: 25 | alist[k]=righthalf[j] 26 | j=j+1 27 | k=k+1 28 | 29 | while i < len(lefthalf): 30 | alist[k]=lefthalf[i] 31 | i=i+1 32 | k=k+1 33 | 34 | while j < len(righthalf): 35 | alist[k]=righthalf[j] 36 | j=j+1 37 | k=k+1 38 | print("Merging the list: ",alist) 39 | 40 | alist = [21, 4, 1, 3, 9, 20, 25] 41 | mergeSort(alist) 42 | print(alist) 43 | -------------------------------------------------------------------------------- /Google Data Structures/queue google.py: -------------------------------------------------------------------------------- 1 | 2 | class Queue: 3 | def __init__(self, head=None): 4 | self.storage = [head] 5 | 6 | # add an element at the end of the queue 7 | def enqueue(self, new_element): 8 | self.storage.append(new_element) 9 | 10 | def peek(self): 11 | return self.storage[0] 12 | 13 | def dequeue(self): 14 | return self.storage.pop(0) 15 | 16 | def __str__(self): 17 | return str(self.storage) 18 | 19 | q = Queue(1) 20 | q.enqueue(2) 21 | q.enqueue(3) 22 | print(q) 23 | print(q.dequeue()) 24 | print(q) 25 | print(q.peek()) -------------------------------------------------------------------------------- /Google Data Structures/quick sort.py: -------------------------------------------------------------------------------- 1 | 2 | # quick sort 3 | 4 | def quickSort(alist): 5 | quickSortHelper(alist,0,len(alist)-1) 6 | return alist 7 | 8 | def quickSortHelper(alist,first,last): 9 | if first= pivotvalue and rightmark >= leftmark: 30 | rightmark = rightmark -1 31 | 32 | if rightmark < leftmark: 33 | done = True 34 | else: 35 | temp = alist[leftmark] 36 | alist[leftmark] = alist[rightmark] 37 | alist[rightmark] = temp 38 | 39 | temp = alist[first] 40 | alist[first] = alist[rightmark] 41 | alist[rightmark] = temp 42 | 43 | 44 | return rightmark 45 | 46 | alist = [54,26,93,17,77,31,44,55,20] 47 | print(quickSort(alist)) 48 | 49 | 50 | -------------------------------------------------------------------------------- /Google Data Structures/recursion google.py: -------------------------------------------------------------------------------- 1 | 2 | # fibonacci sequence 3 | 4 | def get_fib(position): 5 | if position == 0 or position==1: 6 | return position 7 | return get_fib(position-1)+get_fib(position-2) 8 | 9 | -------------------------------------------------------------------------------- /Google Data Structures/test.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/test.py -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/easy-install.pth: -------------------------------------------------------------------------------- 1 | ./setuptools-28.8.0-py3.7.egg 2 | ./pip-9.0.1-py3.7.egg 3 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/EGG-INFO/dependency_links.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/EGG-INFO/entry_points.txt: -------------------------------------------------------------------------------- 1 | [console_scripts] 2 | pip = pip:main 3 | pip3 = pip:main 4 | pip3.7 = pip:main 5 | 6 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/EGG-INFO/not-zip-safe: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/EGG-INFO/requires.txt: -------------------------------------------------------------------------------- 1 | 2 | [testing] 3 | pytest 4 | virtualenv>=1.10 5 | scripttest>=1.3 6 | mock 7 | pretend 8 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/EGG-INFO/top_level.txt: -------------------------------------------------------------------------------- 1 | pip 2 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/__main__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import os 4 | import sys 5 | 6 | # If we are running from a wheel, add the wheel to sys.path 7 | # This allows the usage python pip-*.whl/pip install pip-*.whl 8 | if __package__ == '': 9 | # __file__ is pip-*.whl/pip/__main__.py 10 | # first dirname call strips of '/__main__.py', second strips off '/pip' 11 | # Resulting path is the name of the wheel itself 12 | # Add that to sys.path so we can import pip 13 | path = os.path.dirname(os.path.dirname(__file__)) 14 | sys.path.insert(0, path) 15 | 16 | import pip # noqa 17 | 18 | if __name__ == '__main__': 19 | sys.exit(pip.main()) 20 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/cachecontrol/__init__.py: -------------------------------------------------------------------------------- 1 | """CacheControl import Interface. 2 | 3 | Make it easy to import from cachecontrol without long namespaces. 4 | """ 5 | __author__ = 'Eric Larson' 6 | __email__ = 'eric@ionrock.org' 7 | __version__ = '0.11.7' 8 | 9 | from .wrapper import CacheControl 10 | from .adapter import CacheControlAdapter 11 | from .controller import CacheController 12 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/cachecontrol/_cmd.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from pip._vendor import requests 4 | 5 | from pip._vendor.cachecontrol.adapter import CacheControlAdapter 6 | from pip._vendor.cachecontrol.cache import DictCache 7 | from pip._vendor.cachecontrol.controller import logger 8 | 9 | from argparse import ArgumentParser 10 | 11 | 12 | def setup_logging(): 13 | logger.setLevel(logging.DEBUG) 14 | handler = logging.StreamHandler() 15 | logger.addHandler(handler) 16 | 17 | 18 | def get_session(): 19 | adapter = CacheControlAdapter( 20 | DictCache(), 21 | cache_etags=True, 22 | serializer=None, 23 | heuristic=None, 24 | ) 25 | sess = requests.Session() 26 | sess.mount('http://', adapter) 27 | sess.mount('https://', adapter) 28 | 29 | sess.cache_controller = adapter.controller 30 | return sess 31 | 32 | 33 | def get_args(): 34 | parser = ArgumentParser() 35 | parser.add_argument('url', help='The URL to try and cache') 36 | return parser.parse_args() 37 | 38 | 39 | def main(args=None): 40 | args = get_args() 41 | sess = get_session() 42 | 43 | # Make a request to get a response 44 | resp = sess.get(args.url) 45 | 46 | # Turn on logging 47 | setup_logging() 48 | 49 | # try setting the cache 50 | sess.cache_controller.cache_response(resp.request, resp.raw) 51 | 52 | # Now try to get it 53 | if sess.cache_controller.cached_request(resp.request): 54 | print('Cached!') 55 | else: 56 | print('Not cached :(') 57 | 58 | 59 | if __name__ == '__main__': 60 | main() 61 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/cachecontrol/cache.py: -------------------------------------------------------------------------------- 1 | """ 2 | The cache object API for implementing caches. The default is a thread 3 | safe in-memory dictionary. 4 | """ 5 | from threading import Lock 6 | 7 | 8 | class BaseCache(object): 9 | 10 | def get(self, key): 11 | raise NotImplemented() 12 | 13 | def set(self, key, value): 14 | raise NotImplemented() 15 | 16 | def delete(self, key): 17 | raise NotImplemented() 18 | 19 | def close(self): 20 | pass 21 | 22 | 23 | class DictCache(BaseCache): 24 | 25 | def __init__(self, init_dict=None): 26 | self.lock = Lock() 27 | self.data = init_dict or {} 28 | 29 | def get(self, key): 30 | return self.data.get(key, None) 31 | 32 | def set(self, key, value): 33 | with self.lock: 34 | self.data.update({key: value}) 35 | 36 | def delete(self, key): 37 | with self.lock: 38 | if key in self.data: 39 | self.data.pop(key) 40 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/cachecontrol/caches/__init__.py: -------------------------------------------------------------------------------- 1 | from textwrap import dedent 2 | 3 | try: 4 | from .file_cache import FileCache 5 | except ImportError: 6 | notice = dedent(''' 7 | NOTE: In order to use the FileCache you must have 8 | lockfile installed. You can install it via pip: 9 | pip install lockfile 10 | ''') 11 | print(notice) 12 | 13 | 14 | try: 15 | import redis 16 | from .redis_cache import RedisCache 17 | except ImportError: 18 | pass 19 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/cachecontrol/caches/redis_cache.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | from datetime import datetime 4 | 5 | 6 | def total_seconds(td): 7 | """Python 2.6 compatability""" 8 | if hasattr(td, 'total_seconds'): 9 | return td.total_seconds() 10 | 11 | ms = td.microseconds 12 | secs = (td.seconds + td.days * 24 * 3600) 13 | return (ms + secs * 10**6) / 10**6 14 | 15 | 16 | class RedisCache(object): 17 | 18 | def __init__(self, conn): 19 | self.conn = conn 20 | 21 | def get(self, key): 22 | return self.conn.get(key) 23 | 24 | def set(self, key, value, expires=None): 25 | if not expires: 26 | self.conn.set(key, value) 27 | else: 28 | expires = expires - datetime.now() 29 | self.conn.setex(key, total_seconds(expires), value) 30 | 31 | def delete(self, key): 32 | self.conn.delete(key) 33 | 34 | def clear(self): 35 | """Helper for clearing all the keys in a database. Use with 36 | caution!""" 37 | for key in self.conn.keys(): 38 | self.conn.delete(key) 39 | 40 | def close(self): 41 | self.conn.disconnect() 42 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/cachecontrol/compat.py: -------------------------------------------------------------------------------- 1 | try: 2 | from urllib.parse import urljoin 3 | except ImportError: 4 | from urlparse import urljoin 5 | 6 | 7 | try: 8 | import cPickle as pickle 9 | except ImportError: 10 | import pickle 11 | 12 | 13 | from pip._vendor.requests.packages.urllib3.response import HTTPResponse 14 | from pip._vendor.requests.packages.urllib3.util import is_fp_closed 15 | 16 | # Replicate some six behaviour 17 | try: 18 | text_type = (unicode,) 19 | except NameError: 20 | text_type = (str,) 21 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/cachecontrol/wrapper.py: -------------------------------------------------------------------------------- 1 | from .adapter import CacheControlAdapter 2 | from .cache import DictCache 3 | 4 | 5 | def CacheControl(sess, 6 | cache=None, 7 | cache_etags=True, 8 | serializer=None, 9 | heuristic=None): 10 | 11 | cache = cache or DictCache() 12 | adapter = CacheControlAdapter( 13 | cache, 14 | cache_etags=cache_etags, 15 | serializer=serializer, 16 | heuristic=heuristic, 17 | ) 18 | sess.mount('http://', adapter) 19 | sess.mount('https://', adapter) 20 | 21 | return sess 22 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/colorama/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | from .initialise import init, deinit, reinit, colorama_text 3 | from .ansi import Fore, Back, Style, Cursor 4 | from .ansitowin32 import AnsiToWin32 5 | 6 | __version__ = '0.3.7' 7 | 8 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2012-2016 Vinay Sajip. 4 | # Licensed to the Python Software Foundation under a contributor agreement. 5 | # See LICENSE.txt and CONTRIBUTORS.txt. 6 | # 7 | import logging 8 | 9 | __version__ = '0.2.4' 10 | 11 | class DistlibException(Exception): 12 | pass 13 | 14 | try: 15 | from logging import NullHandler 16 | except ImportError: # pragma: no cover 17 | class NullHandler(logging.Handler): 18 | def handle(self, record): pass 19 | def emit(self, record): pass 20 | def createLock(self): self.lock = None 21 | 22 | logger = logging.getLogger(__name__) 23 | logger.addHandler(NullHandler()) 24 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/_backport/__init__.py: -------------------------------------------------------------------------------- 1 | """Modules copied from Python 3 standard libraries, for internal use only. 2 | 3 | Individual classes and functions are found in d2._backport.misc. Intended 4 | usage is to always import things missing from 3.1 from that module: the 5 | built-in/stdlib objects will be used if found. 6 | """ 7 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/_backport/misc.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2012 The Python Software Foundation. 4 | # See LICENSE.txt and CONTRIBUTORS.txt. 5 | # 6 | """Backports for individual classes and functions.""" 7 | 8 | import os 9 | import sys 10 | 11 | __all__ = ['cache_from_source', 'callable', 'fsencode'] 12 | 13 | 14 | try: 15 | from imp import cache_from_source 16 | except ImportError: 17 | def cache_from_source(py_file, debug=__debug__): 18 | ext = debug and 'c' or 'o' 19 | return py_file + ext 20 | 21 | 22 | try: 23 | callable = callable 24 | except NameError: 25 | from collections import Callable 26 | 27 | def callable(obj): 28 | return isinstance(obj, Callable) 29 | 30 | 31 | try: 32 | fsencode = os.fsencode 33 | except AttributeError: 34 | def fsencode(filename): 35 | if isinstance(filename, bytes): 36 | return filename 37 | elif isinstance(filename, str): 38 | return filename.encode(sys.getfilesystemencoding()) 39 | else: 40 | raise TypeError("expect bytes or str, not %s" % 41 | type(filename).__name__) 42 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/t32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/t32.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/t64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/t64.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/w32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/w32.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/w64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/distlib/w64.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | HTML parsing library based on the WHATWG "HTML5" 3 | specification. The parser is designed to be compatible with existing 4 | HTML found in the wild and implements well-defined error recovery that 5 | is largely compatible with modern desktop web browsers. 6 | 7 | Example usage: 8 | 9 | import html5lib 10 | f = open("my_document.html") 11 | tree = html5lib.parse(f) 12 | """ 13 | 14 | from __future__ import absolute_import, division, unicode_literals 15 | 16 | from .html5parser import HTMLParser, parse, parseFragment 17 | from .treebuilders import getTreeBuilder 18 | from .treewalkers import getTreeWalker 19 | from .serializer import serialize 20 | 21 | __all__ = ["HTMLParser", "parse", "parseFragment", "getTreeBuilder", 22 | "getTreeWalker", "serialize"] 23 | 24 | # this has to be at the top level, see how setup.py parses this 25 | __version__ = "1.0b10" 26 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/_trie/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, unicode_literals 2 | 3 | from .py import Trie as PyTrie 4 | 5 | Trie = PyTrie 6 | 7 | # pylint:disable=wrong-import-position 8 | try: 9 | from .datrie import Trie as DATrie 10 | except ImportError: 11 | pass 12 | else: 13 | Trie = DATrie 14 | # pylint:enable=wrong-import-position 15 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/_trie/_base.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, unicode_literals 2 | 3 | from collections import Mapping 4 | 5 | 6 | class Trie(Mapping): 7 | """Abstract base class for tries""" 8 | 9 | def keys(self, prefix=None): 10 | # pylint:disable=arguments-differ 11 | keys = super(Trie, self).keys() 12 | 13 | if prefix is None: 14 | return set(keys) 15 | 16 | # Python 2.6: no set comprehensions 17 | return set([x for x in keys if x.startswith(prefix)]) 18 | 19 | def has_keys_with_prefix(self, prefix): 20 | for key in self.keys(): 21 | if key.startswith(prefix): 22 | return True 23 | 24 | return False 25 | 26 | def longest_prefix(self, prefix): 27 | if prefix in self: 28 | return prefix 29 | 30 | for i in range(1, len(prefix) + 1): 31 | if prefix[:-i] in self: 32 | return prefix[:-i] 33 | 34 | raise KeyError(prefix) 35 | 36 | def longest_prefix_item(self, prefix): 37 | lprefix = self.longest_prefix(prefix) 38 | return (lprefix, self[lprefix]) 39 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/_trie/datrie.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, unicode_literals 2 | 3 | from datrie import Trie as DATrie 4 | from pip._vendor.six import text_type 5 | 6 | from ._base import Trie as ABCTrie 7 | 8 | 9 | class Trie(ABCTrie): 10 | def __init__(self, data): 11 | chars = set() 12 | for key in data.keys(): 13 | if not isinstance(key, text_type): 14 | raise TypeError("All keys must be strings") 15 | for char in key: 16 | chars.add(char) 17 | 18 | self._data = DATrie("".join(chars)) 19 | for key, value in data.items(): 20 | self._data[key] = value 21 | 22 | def __contains__(self, key): 23 | return key in self._data 24 | 25 | def __len__(self): 26 | return len(self._data) 27 | 28 | def __iter__(self): 29 | raise NotImplementedError() 30 | 31 | def __getitem__(self, key): 32 | return self._data[key] 33 | 34 | def keys(self, prefix=None): 35 | return self._data.keys(prefix) 36 | 37 | def has_keys_with_prefix(self, prefix): 38 | return self._data.has_keys_with_prefix(prefix) 39 | 40 | def longest_prefix(self, prefix): 41 | return self._data.longest_prefix(prefix) 42 | 43 | def longest_prefix_item(self, prefix): 44 | return self._data.longest_prefix_item(prefix) 45 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/filters/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/filters/__init__.py -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/filters/alphabeticalattributes.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, unicode_literals 2 | 3 | from . import base 4 | 5 | try: 6 | from collections import OrderedDict 7 | except ImportError: 8 | from ordereddict import OrderedDict 9 | 10 | 11 | class Filter(base.Filter): 12 | def __iter__(self): 13 | for token in base.Filter.__iter__(self): 14 | if token["type"] in ("StartTag", "EmptyTag"): 15 | attrs = OrderedDict() 16 | for name, value in sorted(token["data"].items(), 17 | key=lambda x: x[0]): 18 | attrs[name] = value 19 | token["data"] = attrs 20 | yield token 21 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/filters/base.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, unicode_literals 2 | 3 | 4 | class Filter(object): 5 | def __init__(self, source): 6 | self.source = source 7 | 8 | def __iter__(self): 9 | return iter(self.source) 10 | 11 | def __getattr__(self, name): 12 | return getattr(self.source, name) 13 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/filters/whitespace.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, unicode_literals 2 | 3 | import re 4 | 5 | from . import base 6 | from ..constants import rcdataElements, spaceCharacters 7 | spaceCharacters = "".join(spaceCharacters) 8 | 9 | SPACES_REGEX = re.compile("[%s]+" % spaceCharacters) 10 | 11 | 12 | class Filter(base.Filter): 13 | 14 | spacePreserveElements = frozenset(["pre", "textarea"] + list(rcdataElements)) 15 | 16 | def __iter__(self): 17 | preserve = 0 18 | for token in base.Filter.__iter__(self): 19 | type = token["type"] 20 | if type == "StartTag" \ 21 | and (preserve or token["name"] in self.spacePreserveElements): 22 | preserve += 1 23 | 24 | elif type == "EndTag" and preserve: 25 | preserve -= 1 26 | 27 | elif not preserve and type == "SpaceCharacters" and token["data"]: 28 | # Test on token["data"] above to not introduce spaces where there were not 29 | token["data"] = " " 30 | 31 | elif not preserve and type == "Characters": 32 | token["data"] = collapse_spaces(token["data"]) 33 | 34 | yield token 35 | 36 | 37 | def collapse_spaces(text): 38 | return SPACES_REGEX.sub(' ', text) 39 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/treeadapters/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, unicode_literals 2 | 3 | from . import sax 4 | 5 | __all__ = ["sax"] 6 | 7 | try: 8 | from . import genshi # noqa 9 | except ImportError: 10 | pass 11 | else: 12 | __all__.append("genshi") 13 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/treeadapters/genshi.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, unicode_literals 2 | 3 | from genshi.core import QName, Attrs 4 | from genshi.core import START, END, TEXT, COMMENT, DOCTYPE 5 | 6 | 7 | def to_genshi(walker): 8 | text = [] 9 | for token in walker: 10 | type = token["type"] 11 | if type in ("Characters", "SpaceCharacters"): 12 | text.append(token["data"]) 13 | elif text: 14 | yield TEXT, "".join(text), (None, -1, -1) 15 | text = [] 16 | 17 | if type in ("StartTag", "EmptyTag"): 18 | if token["namespace"]: 19 | name = "{%s}%s" % (token["namespace"], token["name"]) 20 | else: 21 | name = token["name"] 22 | attrs = Attrs([(QName("{%s}%s" % attr if attr[0] is not None else attr[1]), value) 23 | for attr, value in token["data"].items()]) 24 | yield (START, (QName(name), attrs), (None, -1, -1)) 25 | if type == "EmptyTag": 26 | type = "EndTag" 27 | 28 | if type == "EndTag": 29 | if token["namespace"]: 30 | name = "{%s}%s" % (token["namespace"], token["name"]) 31 | else: 32 | name = token["name"] 33 | 34 | yield END, QName(name), (None, -1, -1) 35 | 36 | elif type == "Comment": 37 | yield COMMENT, token["data"], (None, -1, -1) 38 | 39 | elif type == "Doctype": 40 | yield DOCTYPE, (token["name"], token["publicId"], 41 | token["systemId"]), (None, -1, -1) 42 | 43 | else: 44 | pass # FIXME: What to do? 45 | 46 | if text: 47 | yield TEXT, "".join(text), (None, -1, -1) 48 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/treeadapters/sax.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, unicode_literals 2 | 3 | from xml.sax.xmlreader import AttributesNSImpl 4 | 5 | from ..constants import adjustForeignAttributes, unadjustForeignAttributes 6 | 7 | prefix_mapping = {} 8 | for prefix, localName, namespace in adjustForeignAttributes.values(): 9 | if prefix is not None: 10 | prefix_mapping[prefix] = namespace 11 | 12 | 13 | def to_sax(walker, handler): 14 | """Call SAX-like content handler based on treewalker walker""" 15 | handler.startDocument() 16 | for prefix, namespace in prefix_mapping.items(): 17 | handler.startPrefixMapping(prefix, namespace) 18 | 19 | for token in walker: 20 | type = token["type"] 21 | if type == "Doctype": 22 | continue 23 | elif type in ("StartTag", "EmptyTag"): 24 | attrs = AttributesNSImpl(token["data"], 25 | unadjustForeignAttributes) 26 | handler.startElementNS((token["namespace"], token["name"]), 27 | token["name"], 28 | attrs) 29 | if type == "EmptyTag": 30 | handler.endElementNS((token["namespace"], token["name"]), 31 | token["name"]) 32 | elif type == "EndTag": 33 | handler.endElementNS((token["namespace"], token["name"]), 34 | token["name"]) 35 | elif type in ("Characters", "SpaceCharacters"): 36 | handler.characters(token["data"]) 37 | elif type == "Comment": 38 | pass 39 | else: 40 | assert False, "Unknown token type" 41 | 42 | for prefix, namespace in prefix_mapping.items(): 43 | handler.endPrefixMapping(prefix) 44 | handler.endDocument() 45 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/html5lib/treewalkers/dom.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, unicode_literals 2 | 3 | from xml.dom import Node 4 | 5 | from . import base 6 | 7 | 8 | class TreeWalker(base.NonRecursiveTreeWalker): 9 | def getNodeDetails(self, node): 10 | if node.nodeType == Node.DOCUMENT_TYPE_NODE: 11 | return base.DOCTYPE, node.name, node.publicId, node.systemId 12 | 13 | elif node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): 14 | return base.TEXT, node.nodeValue 15 | 16 | elif node.nodeType == Node.ELEMENT_NODE: 17 | attrs = {} 18 | for attr in list(node.attributes.keys()): 19 | attr = node.getAttributeNode(attr) 20 | if attr.namespaceURI: 21 | attrs[(attr.namespaceURI, attr.localName)] = attr.value 22 | else: 23 | attrs[(None, attr.name)] = attr.value 24 | return (base.ELEMENT, node.namespaceURI, node.nodeName, 25 | attrs, node.hasChildNodes()) 26 | 27 | elif node.nodeType == Node.COMMENT_NODE: 28 | return base.COMMENT, node.nodeValue 29 | 30 | elif node.nodeType in (Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE): 31 | return (base.DOCUMENT,) 32 | 33 | else: 34 | return base.UNKNOWN, node.nodeType 35 | 36 | def getFirstChild(self, node): 37 | return node.firstChild 38 | 39 | def getNextSibling(self, node): 40 | return node.nextSibling 41 | 42 | def getParentNode(self, node): 43 | return node.parentNode 44 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/packaging/__about__.py: -------------------------------------------------------------------------------- 1 | # This file is dual licensed under the terms of the Apache License, Version 2 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 3 | # for complete details. 4 | from __future__ import absolute_import, division, print_function 5 | 6 | __all__ = [ 7 | "__title__", "__summary__", "__uri__", "__version__", "__author__", 8 | "__email__", "__license__", "__copyright__", 9 | ] 10 | 11 | __title__ = "packaging" 12 | __summary__ = "Core utilities for Python packages" 13 | __uri__ = "https://github.com/pypa/packaging" 14 | 15 | __version__ = "16.8" 16 | 17 | __author__ = "Donald Stufft and individual contributors" 18 | __email__ = "donald@stufft.io" 19 | 20 | __license__ = "BSD or Apache License, Version 2.0" 21 | __copyright__ = "Copyright 2014-2016 %s" % __author__ 22 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/packaging/__init__.py: -------------------------------------------------------------------------------- 1 | # This file is dual licensed under the terms of the Apache License, Version 2 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 3 | # for complete details. 4 | from __future__ import absolute_import, division, print_function 5 | 6 | from .__about__ import ( 7 | __author__, __copyright__, __email__, __license__, __summary__, __title__, 8 | __uri__, __version__ 9 | ) 10 | 11 | __all__ = [ 12 | "__title__", "__summary__", "__uri__", "__version__", "__author__", 13 | "__email__", "__license__", "__copyright__", 14 | ] 15 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/packaging/_compat.py: -------------------------------------------------------------------------------- 1 | # This file is dual licensed under the terms of the Apache License, Version 2 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 3 | # for complete details. 4 | from __future__ import absolute_import, division, print_function 5 | 6 | import sys 7 | 8 | 9 | PY2 = sys.version_info[0] == 2 10 | PY3 = sys.version_info[0] == 3 11 | 12 | # flake8: noqa 13 | 14 | if PY3: 15 | string_types = str, 16 | else: 17 | string_types = basestring, 18 | 19 | 20 | def with_metaclass(meta, *bases): 21 | """ 22 | Create a base class with a metaclass. 23 | """ 24 | # This requires a bit of explanation: the basic idea is to make a dummy 25 | # metaclass for one level of class instantiation that replaces itself with 26 | # the actual metaclass. 27 | class metaclass(meta): 28 | def __new__(cls, name, this_bases, d): 29 | return meta(name, bases, d) 30 | return type.__new__(metaclass, 'temporary_class', (), {}) 31 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/packaging/_structures.py: -------------------------------------------------------------------------------- 1 | # This file is dual licensed under the terms of the Apache License, Version 2 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 3 | # for complete details. 4 | from __future__ import absolute_import, division, print_function 5 | 6 | 7 | class Infinity(object): 8 | 9 | def __repr__(self): 10 | return "Infinity" 11 | 12 | def __hash__(self): 13 | return hash(repr(self)) 14 | 15 | def __lt__(self, other): 16 | return False 17 | 18 | def __le__(self, other): 19 | return False 20 | 21 | def __eq__(self, other): 22 | return isinstance(other, self.__class__) 23 | 24 | def __ne__(self, other): 25 | return not isinstance(other, self.__class__) 26 | 27 | def __gt__(self, other): 28 | return True 29 | 30 | def __ge__(self, other): 31 | return True 32 | 33 | def __neg__(self): 34 | return NegativeInfinity 35 | 36 | Infinity = Infinity() 37 | 38 | 39 | class NegativeInfinity(object): 40 | 41 | def __repr__(self): 42 | return "-Infinity" 43 | 44 | def __hash__(self): 45 | return hash(repr(self)) 46 | 47 | def __lt__(self, other): 48 | return True 49 | 50 | def __le__(self, other): 51 | return True 52 | 53 | def __eq__(self, other): 54 | return isinstance(other, self.__class__) 55 | 56 | def __ne__(self, other): 57 | return not isinstance(other, self.__class__) 58 | 59 | def __gt__(self, other): 60 | return False 61 | 62 | def __ge__(self, other): 63 | return False 64 | 65 | def __neg__(self): 66 | return Infinity 67 | 68 | NegativeInfinity = NegativeInfinity() 69 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/packaging/utils.py: -------------------------------------------------------------------------------- 1 | # This file is dual licensed under the terms of the Apache License, Version 2 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 3 | # for complete details. 4 | from __future__ import absolute_import, division, print_function 5 | 6 | import re 7 | 8 | 9 | _canonicalize_regex = re.compile(r"[-_.]+") 10 | 11 | 12 | def canonicalize_name(name): 13 | # This is taken from PEP 503. 14 | return _canonicalize_regex.sub("-", name).lower() 15 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/progress/counter.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright (c) 2012 Giorgos Verigakis 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | from . import Infinite, Progress 18 | from .helpers import WriteMixin 19 | 20 | 21 | class Counter(WriteMixin, Infinite): 22 | message = '' 23 | hide_cursor = True 24 | 25 | def update(self): 26 | self.write(str(self.index)) 27 | 28 | 29 | class Countdown(WriteMixin, Progress): 30 | hide_cursor = True 31 | 32 | def update(self): 33 | self.write(str(self.remaining)) 34 | 35 | 36 | class Stack(WriteMixin, Progress): 37 | phases = (u' ', u'▁', u'▂', u'▃', u'▄', u'▅', u'▆', u'▇', u'█') 38 | hide_cursor = True 39 | 40 | def update(self): 41 | nphases = len(self.phases) 42 | i = min(nphases - 1, int(self.progress * nphases)) 43 | self.write(self.phases[i]) 44 | 45 | 46 | class Pie(Stack): 47 | phases = (u'○', u'◔', u'◑', u'◕', u'●') 48 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/progress/spinner.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright (c) 2012 Giorgos Verigakis 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | from . import Infinite 18 | from .helpers import WriteMixin 19 | 20 | 21 | class Spinner(WriteMixin, Infinite): 22 | message = '' 23 | phases = ('-', '\\', '|', '/') 24 | hide_cursor = True 25 | 26 | def update(self): 27 | i = self.index % len(self.phases) 28 | self.write(self.phases[i]) 29 | 30 | 31 | class PieSpinner(Spinner): 32 | phases = [u'◷', u'◶', u'◵', u'◴'] 33 | 34 | 35 | class MoonSpinner(Spinner): 36 | phases = [u'◑', u'◒', u'◐', u'◓'] 37 | 38 | 39 | class LineSpinner(Spinner): 40 | phases = [u'⎺', u'⎻', u'⎼', u'⎽', u'⎼', u'⎻'] 41 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/re-vendor.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pip 4 | import glob 5 | import shutil 6 | 7 | here = os.path.abspath(os.path.dirname(__file__)) 8 | 9 | def usage(): 10 | print("Usage: re-vendor.py [clean|vendor]") 11 | sys.exit(1) 12 | 13 | def clean(): 14 | for fn in os.listdir(here): 15 | dirname = os.path.join(here, fn) 16 | if os.path.isdir(dirname): 17 | shutil.rmtree(dirname) 18 | # six is a single file, not a package 19 | os.unlink(os.path.join(here, 'six.py')) 20 | 21 | def vendor(): 22 | pip.main(['install', '-t', here, '-r', 'vendor.txt']) 23 | for dirname in glob.glob('*.egg-info'): 24 | shutil.rmtree(dirname) 25 | 26 | if __name__ == '__main__': 27 | if len(sys.argv) != 2: 28 | usage() 29 | if sys.argv[1] == 'clean': 30 | clean() 31 | elif sys.argv[1] == 'vendor': 32 | vendor() 33 | else: 34 | usage() 35 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/certs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | requests.certs 6 | ~~~~~~~~~~~~~~ 7 | 8 | This module returns the preferred default CA certificate bundle. 9 | 10 | If you are packaging Requests, e.g., for a Linux distribution or a managed 11 | environment, you can change the definition of where() to return a separately 12 | packaged CA bundle. 13 | """ 14 | import os.path 15 | 16 | try: 17 | from certifi import where 18 | except ImportError: 19 | def where(): 20 | """Return the preferred certificate bundle.""" 21 | # vendored bundle inside Requests 22 | return os.path.join(os.path.dirname(__file__), 'cacert.pem') 23 | 24 | if __name__ == '__main__': 25 | print(where()) 26 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/hooks.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | requests.hooks 5 | ~~~~~~~~~~~~~~ 6 | 7 | This module provides the capabilities for the Requests hooks system. 8 | 9 | Available hooks: 10 | 11 | ``response``: 12 | The response generated from a Request. 13 | """ 14 | HOOKS = ['response'] 15 | 16 | 17 | def default_hooks(): 18 | return dict((event, []) for event in HOOKS) 19 | 20 | # TODO: response is the only one 21 | 22 | 23 | def dispatch_hook(key, hooks, hook_data, **kwargs): 24 | """Dispatches a hook dictionary on a given piece of data.""" 25 | hooks = hooks or dict() 26 | hooks = hooks.get(key) 27 | if hooks: 28 | if hasattr(hooks, '__call__'): 29 | hooks = [hooks] 30 | for hook in hooks: 31 | _hook_data = hook(hook_data, **kwargs) 32 | if _hook_data is not None: 33 | hook_data = _hook_data 34 | return hook_data 35 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Debian and other distributions "unbundle" requests' vendored dependencies, and 3 | rewrite all imports to use the global versions of ``urllib3`` and ``chardet``. 4 | The problem with this is that not only requests itself imports those 5 | dependencies, but third-party code outside of the distros' control too. 6 | 7 | In reaction to these problems, the distro maintainers replaced 8 | ``requests.packages`` with a magical "stub module" that imports the correct 9 | modules. The implementations were varying in quality and all had severe 10 | problems. For example, a symlink (or hardlink) that links the correct modules 11 | into place introduces problems regarding object identity, since you now have 12 | two modules in `sys.modules` with the same API, but different identities:: 13 | 14 | requests.packages.urllib3 is not urllib3 15 | 16 | With version ``2.5.2``, requests started to maintain its own stub, so that 17 | distro-specific breakage would be reduced to a minimum, even though the whole 18 | issue is not requests' fault in the first place. See 19 | https://github.com/kennethreitz/requests/pull/2375 for the corresponding pull 20 | request. 21 | ''' 22 | 23 | from __future__ import absolute_import 24 | import sys 25 | 26 | try: 27 | from . import urllib3 28 | except ImportError: 29 | import urllib3 30 | sys.modules['%s.urllib3' % __name__] = urllib3 31 | 32 | try: 33 | from . import chardet 34 | except ImportError: 35 | import chardet 36 | sys.modules['%s.chardet' % __name__] = chardet 37 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/chardet/__init__.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # This library is free software; you can redistribute it and/or 3 | # modify it under the terms of the GNU Lesser General Public 4 | # License as published by the Free Software Foundation; either 5 | # version 2.1 of the License, or (at your option) any later version. 6 | # 7 | # This library is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | # Lesser General Public License for more details. 11 | # 12 | # You should have received a copy of the GNU Lesser General Public 13 | # License along with this library; if not, write to the Free Software 14 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 15 | # 02110-1301 USA 16 | ######################### END LICENSE BLOCK ######################### 17 | 18 | __version__ = "2.3.0" 19 | from sys import version_info 20 | 21 | 22 | def detect(aBuf): 23 | if ((version_info < (3, 0) and isinstance(aBuf, unicode)) or 24 | (version_info >= (3, 0) and not isinstance(aBuf, bytes))): 25 | raise ValueError('Expected a bytes object, not a unicode object') 26 | 27 | from . import universaldetector 28 | u = universaldetector.UniversalDetector() 29 | u.reset() 30 | u.feed(aBuf) 31 | u.close() 32 | return u.result 33 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/chardet/big5prober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is Mozilla Communicator client code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from .mbcharsetprober import MultiByteCharSetProber 29 | from .codingstatemachine import CodingStateMachine 30 | from .chardistribution import Big5DistributionAnalysis 31 | from .mbcssm import Big5SMModel 32 | 33 | 34 | class Big5Prober(MultiByteCharSetProber): 35 | def __init__(self): 36 | MultiByteCharSetProber.__init__(self) 37 | self._mCodingSM = CodingStateMachine(Big5SMModel) 38 | self._mDistributionAnalyzer = Big5DistributionAnalysis() 39 | self.reset() 40 | 41 | def get_charset_name(self): 42 | return "Big5" 43 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/chardet/compat.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # Contributor(s): 3 | # Ian Cordasco - port to Python 4 | # 5 | # This library is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2.1 of the License, or (at your option) any later version. 9 | # 10 | # This library is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public 16 | # License along with this library; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18 | # 02110-1301 USA 19 | ######################### END LICENSE BLOCK ######################### 20 | 21 | import sys 22 | 23 | 24 | if sys.version_info < (3, 0): 25 | base_str = (str, unicode) 26 | else: 27 | base_str = (bytes, str) 28 | 29 | 30 | def wrap_ord(a): 31 | if sys.version_info < (3, 0) and isinstance(a, base_str): 32 | return ord(a) 33 | else: 34 | return a 35 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/chardet/constants.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is Mozilla Universal charset detector code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 2001 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # Shy Shalom - original C code 12 | # 13 | # This library is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Lesser General Public 15 | # License as published by the Free Software Foundation; either 16 | # version 2.1 of the License, or (at your option) any later version. 17 | # 18 | # This library is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | # Lesser General Public License for more details. 22 | # 23 | # You should have received a copy of the GNU Lesser General Public 24 | # License along with this library; if not, write to the Free Software 25 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 26 | # 02110-1301 USA 27 | ######################### END LICENSE BLOCK ######################### 28 | 29 | _debug = 0 30 | 31 | eDetecting = 0 32 | eFoundIt = 1 33 | eNotMe = 2 34 | 35 | eStart = 0 36 | eError = 1 37 | eItsMe = 2 38 | 39 | SHORTCUT_THRESHOLD = 0.95 40 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/chardet/euckrprober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is mozilla.org code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from .mbcharsetprober import MultiByteCharSetProber 29 | from .codingstatemachine import CodingStateMachine 30 | from .chardistribution import EUCKRDistributionAnalysis 31 | from .mbcssm import EUCKRSMModel 32 | 33 | 34 | class EUCKRProber(MultiByteCharSetProber): 35 | def __init__(self): 36 | MultiByteCharSetProber.__init__(self) 37 | self._mCodingSM = CodingStateMachine(EUCKRSMModel) 38 | self._mDistributionAnalyzer = EUCKRDistributionAnalysis() 39 | self.reset() 40 | 41 | def get_charset_name(self): 42 | return "EUC-KR" 43 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/chardet/euctwprober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is mozilla.org code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from .mbcharsetprober import MultiByteCharSetProber 29 | from .codingstatemachine import CodingStateMachine 30 | from .chardistribution import EUCTWDistributionAnalysis 31 | from .mbcssm import EUCTWSMModel 32 | 33 | class EUCTWProber(MultiByteCharSetProber): 34 | def __init__(self): 35 | MultiByteCharSetProber.__init__(self) 36 | self._mCodingSM = CodingStateMachine(EUCTWSMModel) 37 | self._mDistributionAnalyzer = EUCTWDistributionAnalysis() 38 | self.reset() 39 | 40 | def get_charset_name(self): 41 | return "EUC-TW" 42 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/chardet/gb2312prober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is mozilla.org code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from .mbcharsetprober import MultiByteCharSetProber 29 | from .codingstatemachine import CodingStateMachine 30 | from .chardistribution import GB2312DistributionAnalysis 31 | from .mbcssm import GB2312SMModel 32 | 33 | class GB2312Prober(MultiByteCharSetProber): 34 | def __init__(self): 35 | MultiByteCharSetProber.__init__(self) 36 | self._mCodingSM = CodingStateMachine(GB2312SMModel) 37 | self._mDistributionAnalyzer = GB2312DistributionAnalysis() 38 | self.reset() 39 | 40 | def get_charset_name(self): 41 | return "GB2312" 42 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/urllib3/contrib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/urllib3/contrib/__init__.py -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/urllib3/packages/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from . import ssl_match_hostname 4 | 5 | __all__ = ('ssl_match_hostname', ) 6 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py: -------------------------------------------------------------------------------- 1 | try: 2 | # Python 3.2+ 3 | from ssl import CertificateError, match_hostname 4 | except ImportError: 5 | try: 6 | # Backport of the function from a pypi module 7 | from backports.ssl_match_hostname import CertificateError, match_hostname 8 | except ImportError: 9 | # Our vendored copy 10 | from ._implementation import CertificateError, match_hostname 11 | 12 | # Not needed, but documenting what we provide. 13 | __all__ = ('CertificateError', 'match_hostname') 14 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/requests/packages/urllib3/util/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | # For backwards compatibility, provide imports that used to be here. 3 | from .connection import is_connection_dropped 4 | from .request import make_headers 5 | from .response import is_fp_closed 6 | from .ssl_ import ( 7 | SSLContext, 8 | HAS_SNI, 9 | IS_PYOPENSSL, 10 | assert_fingerprint, 11 | resolve_cert_reqs, 12 | resolve_ssl_version, 13 | ssl_wrap_socket, 14 | ) 15 | from .timeout import ( 16 | current_time, 17 | Timeout, 18 | ) 19 | 20 | from .retry import Retry 21 | from .url import ( 22 | get_host, 23 | parse_url, 24 | split_first, 25 | Url, 26 | ) 27 | 28 | __all__ = ( 29 | 'HAS_SNI', 30 | 'IS_PYOPENSSL', 31 | 'SSLContext', 32 | 'Retry', 33 | 'Timeout', 34 | 'Url', 35 | 'assert_fingerprint', 36 | 'current_time', 37 | 'is_connection_dropped', 38 | 'is_fp_closed', 39 | 'get_host', 40 | 'parse_url', 41 | 'make_headers', 42 | 'resolve_cert_reqs', 43 | 'resolve_ssl_version', 44 | 'split_first', 45 | 'ssl_wrap_socket', 46 | ) 47 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/_vendor/webencodings/mklabels.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | webencodings.mklabels 4 | ~~~~~~~~~~~~~~~~~~~~~ 5 | 6 | Regenarate the webencodings.labels module. 7 | 8 | :copyright: Copyright 2012 by Simon Sapin 9 | :license: BSD, see LICENSE for details. 10 | 11 | """ 12 | 13 | import json 14 | try: 15 | from urllib import urlopen 16 | except ImportError: 17 | from urllib.request import urlopen 18 | 19 | 20 | def assert_lower(string): 21 | assert string == string.lower() 22 | return string 23 | 24 | 25 | def generate(url): 26 | parts = ['''\ 27 | """ 28 | 29 | webencodings.labels 30 | ~~~~~~~~~~~~~~~~~~~ 31 | 32 | Map encoding labels to their name. 33 | 34 | :copyright: Copyright 2012 by Simon Sapin 35 | :license: BSD, see LICENSE for details. 36 | 37 | """ 38 | 39 | # XXX Do not edit! 40 | # This file is automatically generated by mklabels.py 41 | 42 | LABELS = { 43 | '''] 44 | labels = [ 45 | (repr(assert_lower(label)).lstrip('u'), 46 | repr(encoding['name']).lstrip('u')) 47 | for category in json.loads(urlopen(url).read().decode('ascii')) 48 | for encoding in category['encodings'] 49 | for label in encoding['labels']] 50 | max_len = max(len(label) for label, name in labels) 51 | parts.extend( 52 | ' %s:%s %s,\n' % (label, ' ' * (max_len - len(label)), name) 53 | for label, name in labels) 54 | parts.append('}') 55 | return ''.join(parts) 56 | 57 | 58 | if __name__ == '__main__': 59 | print(generate('http://encoding.spec.whatwg.org/encodings.json')) 60 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/commands/check.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from pip.basecommand import Command 4 | from pip.operations.check import check_requirements 5 | from pip.utils import get_installed_distributions 6 | 7 | 8 | logger = logging.getLogger(__name__) 9 | 10 | 11 | class CheckCommand(Command): 12 | """Verify installed packages have compatible dependencies.""" 13 | name = 'check' 14 | usage = """ 15 | %prog [options]""" 16 | summary = 'Verify installed packages have compatible dependencies.' 17 | 18 | def run(self, options, args): 19 | dists = get_installed_distributions(local_only=False, skip=()) 20 | missing_reqs_dict, incompatible_reqs_dict = check_requirements(dists) 21 | 22 | for dist in dists: 23 | key = '%s==%s' % (dist.project_name, dist.version) 24 | 25 | for requirement in missing_reqs_dict.get(key, []): 26 | logger.info( 27 | "%s %s requires %s, which is not installed.", 28 | dist.project_name, dist.version, requirement.project_name) 29 | 30 | for requirement, actual in incompatible_reqs_dict.get(key, []): 31 | logger.info( 32 | "%s %s has requirement %s, but you have %s %s.", 33 | dist.project_name, dist.version, requirement, 34 | actual.project_name, actual.version) 35 | 36 | if missing_reqs_dict or incompatible_reqs_dict: 37 | return 1 38 | else: 39 | logger.info("No broken requirements found.") 40 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/commands/hash.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import hashlib 4 | import logging 5 | import sys 6 | 7 | from pip.basecommand import Command 8 | from pip.status_codes import ERROR 9 | from pip.utils import read_chunks 10 | from pip.utils.hashes import FAVORITE_HASH, STRONG_HASHES 11 | 12 | 13 | logger = logging.getLogger(__name__) 14 | 15 | 16 | class HashCommand(Command): 17 | """ 18 | Compute a hash of a local package archive. 19 | 20 | These can be used with --hash in a requirements file to do repeatable 21 | installs. 22 | 23 | """ 24 | name = 'hash' 25 | usage = '%prog [options] ...' 26 | summary = 'Compute hashes of package archives.' 27 | 28 | def __init__(self, *args, **kw): 29 | super(HashCommand, self).__init__(*args, **kw) 30 | self.cmd_opts.add_option( 31 | '-a', '--algorithm', 32 | dest='algorithm', 33 | choices=STRONG_HASHES, 34 | action='store', 35 | default=FAVORITE_HASH, 36 | help='The hash algorithm to use: one of %s' % 37 | ', '.join(STRONG_HASHES)) 38 | self.parser.insert_option_group(0, self.cmd_opts) 39 | 40 | def run(self, options, args): 41 | if not args: 42 | self.parser.print_usage(sys.stderr) 43 | return ERROR 44 | 45 | algorithm = options.algorithm 46 | for path in args: 47 | logger.info('%s:\n--hash=%s:%s', 48 | path, algorithm, _hash_of_file(path, algorithm)) 49 | 50 | 51 | def _hash_of_file(path, algorithm): 52 | """Return the hash digest of a file.""" 53 | with open(path, 'rb') as archive: 54 | hash = hashlib.new(algorithm) 55 | for chunk in read_chunks(archive): 56 | hash.update(chunk) 57 | return hash.hexdigest() 58 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/commands/help.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from pip.basecommand import Command, SUCCESS 4 | from pip.exceptions import CommandError 5 | 6 | 7 | class HelpCommand(Command): 8 | """Show help for commands""" 9 | name = 'help' 10 | usage = """ 11 | %prog """ 12 | summary = 'Show help for commands.' 13 | 14 | def run(self, options, args): 15 | from pip.commands import commands_dict, get_similar_commands 16 | 17 | try: 18 | # 'pip help' with no args is handled by pip.__init__.parseopt() 19 | cmd_name = args[0] # the command we need help for 20 | except IndexError: 21 | return SUCCESS 22 | 23 | if cmd_name not in commands_dict: 24 | guess = get_similar_commands(cmd_name) 25 | 26 | msg = ['unknown command "%s"' % cmd_name] 27 | if guess: 28 | msg.append('maybe you meant "%s"' % guess) 29 | 30 | raise CommandError(' - '.join(msg)) 31 | 32 | command = commands_dict[cmd_name]() 33 | command.parser.print_help() 34 | 35 | return SUCCESS 36 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/models/__init__.py: -------------------------------------------------------------------------------- 1 | from pip.models.index import Index, PyPI 2 | 3 | 4 | __all__ = ["Index", "PyPI"] 5 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/models/index.py: -------------------------------------------------------------------------------- 1 | from pip._vendor.six.moves.urllib import parse as urllib_parse 2 | 3 | 4 | class Index(object): 5 | def __init__(self, url): 6 | self.url = url 7 | self.netloc = urllib_parse.urlsplit(url).netloc 8 | self.simple_url = self.url_to_path('simple') 9 | self.pypi_url = self.url_to_path('pypi') 10 | self.pip_json_url = self.url_to_path('pypi/pip/json') 11 | 12 | def url_to_path(self, path): 13 | return urllib_parse.urljoin(self.url, path) 14 | 15 | 16 | PyPI = Index('https://pypi.python.org/') 17 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/operations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/operations/__init__.py -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/operations/check.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def check_requirements(installed_dists): 4 | missing_reqs_dict = {} 5 | incompatible_reqs_dict = {} 6 | 7 | for dist in installed_dists: 8 | key = '%s==%s' % (dist.project_name, dist.version) 9 | 10 | missing_reqs = list(get_missing_reqs(dist, installed_dists)) 11 | if missing_reqs: 12 | missing_reqs_dict[key] = missing_reqs 13 | 14 | incompatible_reqs = list(get_incompatible_reqs( 15 | dist, installed_dists)) 16 | if incompatible_reqs: 17 | incompatible_reqs_dict[key] = incompatible_reqs 18 | 19 | return (missing_reqs_dict, incompatible_reqs_dict) 20 | 21 | 22 | def get_missing_reqs(dist, installed_dists): 23 | """Return all of the requirements of `dist` that aren't present in 24 | `installed_dists`. 25 | 26 | """ 27 | installed_names = set(d.project_name.lower() for d in installed_dists) 28 | missing_requirements = set() 29 | 30 | for requirement in dist.requires(): 31 | if requirement.project_name.lower() not in installed_names: 32 | missing_requirements.add(requirement) 33 | yield requirement 34 | 35 | 36 | def get_incompatible_reqs(dist, installed_dists): 37 | """Return all of the requirements of `dist` that are present in 38 | `installed_dists`, but have incompatible versions. 39 | 40 | """ 41 | installed_dists_by_name = {} 42 | for installed_dist in installed_dists: 43 | installed_dists_by_name[installed_dist.project_name] = installed_dist 44 | 45 | for requirement in dist.requires(): 46 | present_dist = installed_dists_by_name.get(requirement.project_name) 47 | 48 | if present_dist and present_dist not in requirement: 49 | yield (requirement, present_dist) 50 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/req/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .req_install import InstallRequirement 4 | from .req_set import RequirementSet, Requirements 5 | from .req_file import parse_requirements 6 | 7 | __all__ = [ 8 | "RequirementSet", "Requirements", "InstallRequirement", 9 | "parse_requirements", 10 | ] 11 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/status_codes.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | SUCCESS = 0 4 | ERROR = 1 5 | UNKNOWN_ERROR = 2 6 | VIRTUALENV_NOT_FOUND = 3 7 | PREVIOUS_BUILD_DIR_ERROR = 4 8 | NO_MATCHES_FOUND = 23 9 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/utils/build.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import os.path 4 | import tempfile 5 | 6 | from pip.utils import rmtree 7 | 8 | 9 | class BuildDirectory(object): 10 | 11 | def __init__(self, name=None, delete=None): 12 | # If we were not given an explicit directory, and we were not given an 13 | # explicit delete option, then we'll default to deleting. 14 | if name is None and delete is None: 15 | delete = True 16 | 17 | if name is None: 18 | # We realpath here because some systems have their default tmpdir 19 | # symlinked to another directory. This tends to confuse build 20 | # scripts, so we canonicalize the path by traversing potential 21 | # symlinks here. 22 | name = os.path.realpath(tempfile.mkdtemp(prefix="pip-build-")) 23 | # If we were not given an explicit directory, and we were not given 24 | # an explicit delete option, then we'll default to deleting. 25 | if delete is None: 26 | delete = True 27 | 28 | self.name = name 29 | self.delete = delete 30 | 31 | def __repr__(self): 32 | return "<{} {!r}>".format(self.__class__.__name__, self.name) 33 | 34 | def __enter__(self): 35 | return self.name 36 | 37 | def __exit__(self, exc, value, tb): 38 | self.cleanup() 39 | 40 | def cleanup(self): 41 | if self.delete: 42 | rmtree(self.name) 43 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/utils/encoding.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | import locale 3 | import re 4 | 5 | 6 | BOMS = [ 7 | (codecs.BOM_UTF8, 'utf8'), 8 | (codecs.BOM_UTF16, 'utf16'), 9 | (codecs.BOM_UTF16_BE, 'utf16-be'), 10 | (codecs.BOM_UTF16_LE, 'utf16-le'), 11 | (codecs.BOM_UTF32, 'utf32'), 12 | (codecs.BOM_UTF32_BE, 'utf32-be'), 13 | (codecs.BOM_UTF32_LE, 'utf32-le'), 14 | ] 15 | 16 | ENCODING_RE = re.compile(b'coding[:=]\s*([-\w.]+)') 17 | 18 | 19 | def auto_decode(data): 20 | """Check a bytes string for a BOM to correctly detect the encoding 21 | 22 | Fallback to locale.getpreferredencoding(False) like open() on Python3""" 23 | for bom, encoding in BOMS: 24 | if data.startswith(bom): 25 | return data[len(bom):].decode(encoding) 26 | # Lets check the first two lines as in PEP263 27 | for line in data.split(b'\n')[:2]: 28 | if line[0:1] == b'#' and ENCODING_RE.search(line): 29 | encoding = ENCODING_RE.search(line).groups()[0].decode('ascii') 30 | return data.decode(encoding) 31 | return data.decode(locale.getpreferredencoding(False)) 32 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/utils/filesystem.py: -------------------------------------------------------------------------------- 1 | import os 2 | import os.path 3 | 4 | from pip.compat import get_path_uid 5 | 6 | 7 | def check_path_owner(path): 8 | # If we don't have a way to check the effective uid of this process, then 9 | # we'll just assume that we own the directory. 10 | if not hasattr(os, "geteuid"): 11 | return True 12 | 13 | previous = None 14 | while path != previous: 15 | if os.path.lexists(path): 16 | # Check if path is writable by current user. 17 | if os.geteuid() == 0: 18 | # Special handling for root user in order to handle properly 19 | # cases where users use sudo without -H flag. 20 | try: 21 | path_uid = get_path_uid(path) 22 | except OSError: 23 | return False 24 | return path_uid == 0 25 | else: 26 | return os.access(path, os.W_OK) 27 | else: 28 | previous, path = path, os.path.dirname(path) 29 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/pip-9.0.1-py3.7.egg/pip/utils/setuptools_build.py: -------------------------------------------------------------------------------- 1 | # Shim to wrap setup.py invocation with setuptools 2 | SETUPTOOLS_SHIM = ( 3 | "import setuptools, tokenize;__file__=%r;" 4 | "f=getattr(tokenize, 'open', open)(__file__);" 5 | "code=f.read().replace('\\r\\n', '\\n');" 6 | "f.close();" 7 | "exec(compile(code, __file__, 'exec'))" 8 | ) 9 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/setuptools-28.8.0-py3.7.egg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Lib/site-packages/setuptools-28.8.0-py3.7.egg -------------------------------------------------------------------------------- /Google Data Structures/venv/Lib/site-packages/setuptools.pth: -------------------------------------------------------------------------------- 1 | ./setuptools-28.8.0-py3.7.egg 2 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/Activate.ps1: -------------------------------------------------------------------------------- 1 | function global:deactivate ([switch]$NonDestructive) { 2 | # Revert to original values 3 | if (Test-Path function:_OLD_VIRTUAL_PROMPT) { 4 | copy-item function:_OLD_VIRTUAL_PROMPT function:prompt 5 | remove-item function:_OLD_VIRTUAL_PROMPT 6 | } 7 | 8 | if (Test-Path env:_OLD_VIRTUAL_PYTHONHOME) { 9 | copy-item env:_OLD_VIRTUAL_PYTHONHOME env:PYTHONHOME 10 | remove-item env:_OLD_VIRTUAL_PYTHONHOME 11 | } 12 | 13 | if (Test-Path env:_OLD_VIRTUAL_PATH) { 14 | copy-item env:_OLD_VIRTUAL_PATH env:PATH 15 | remove-item env:_OLD_VIRTUAL_PATH 16 | } 17 | 18 | if (Test-Path env:VIRTUAL_ENV) { 19 | remove-item env:VIRTUAL_ENV 20 | } 21 | 22 | if (!$NonDestructive) { 23 | # Self destruct! 24 | remove-item function:deactivate 25 | } 26 | } 27 | 28 | deactivate -nondestructive 29 | 30 | $env:VIRTUAL_ENV="E:\PyCharm\Data Structures\venv" 31 | 32 | if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) { 33 | # Set the prompt to include the env name 34 | # Make sure _OLD_VIRTUAL_PROMPT is global 35 | function global:_OLD_VIRTUAL_PROMPT {""} 36 | copy-item function:prompt function:_OLD_VIRTUAL_PROMPT 37 | function global:prompt { 38 | Write-Host -NoNewline -ForegroundColor Green '(venv) ' 39 | _OLD_VIRTUAL_PROMPT 40 | } 41 | } 42 | 43 | # Clear PYTHONHOME 44 | if (Test-Path env:PYTHONHOME) { 45 | copy-item env:PYTHONHOME env:_OLD_VIRTUAL_PYTHONHOME 46 | remove-item env:PYTHONHOME 47 | } 48 | 49 | # Add the venv to the PATH 50 | copy-item env:PATH env:_OLD_VIRTUAL_PATH 51 | $env:PATH = "$env:VIRTUAL_ENV\Scripts;$env:PATH" 52 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_asyncio.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_asyncio.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_bz2.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_bz2.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_contextvars.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_contextvars.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_ctypes.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_ctypes.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_ctypes_test.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_ctypes_test.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_decimal.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_decimal.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_distutils_findvs.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_distutils_findvs.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_elementtree.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_elementtree.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_hashlib.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_hashlib.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_lzma.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_lzma.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_msi.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_msi.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_multiprocessing.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_multiprocessing.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_overlapped.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_overlapped.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_queue.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_queue.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_socket.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_socket.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_sqlite3.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_sqlite3.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_ssl.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_ssl.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_testbuffer.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_testbuffer.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_testcapi.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_testcapi.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_testconsole.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_testconsole.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_testimportmultiple.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_testimportmultiple.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_testmultiphase.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_testmultiphase.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/_tkinter.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/_tkinter.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/activate.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem This file is UTF-8 encoded, so we need to update the current code page while executing it 4 | for /f "tokens=2 delims=:" %%a in ('"%SystemRoot%\System32\chcp.com"') do ( 5 | set "_OLD_CODEPAGE=%%a" 6 | ) 7 | if defined _OLD_CODEPAGE ( 8 | "%SystemRoot%\System32\chcp.com" 65001 > nul 9 | ) 10 | 11 | set "VIRTUAL_ENV=E:\PyCharm\Data Structures\venv" 12 | 13 | if not defined PROMPT ( 14 | set "PROMPT=$P$G" 15 | ) 16 | 17 | if defined _OLD_VIRTUAL_PROMPT ( 18 | set "PROMPT=%_OLD_VIRTUAL_PROMPT%" 19 | ) 20 | 21 | if defined _OLD_VIRTUAL_PYTHONHOME ( 22 | set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" 23 | ) 24 | 25 | set "_OLD_VIRTUAL_PROMPT=%PROMPT%" 26 | set "PROMPT=(venv) %PROMPT%" 27 | 28 | if defined PYTHONHOME ( 29 | set "_OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%" 30 | set PYTHONHOME= 31 | ) 32 | 33 | if defined _OLD_VIRTUAL_PATH ( 34 | set "PATH=%_OLD_VIRTUAL_PATH%" 35 | ) else ( 36 | set "_OLD_VIRTUAL_PATH=%PATH%" 37 | ) 38 | 39 | set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%" 40 | 41 | :END 42 | if defined _OLD_CODEPAGE ( 43 | "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul 44 | set "_OLD_CODEPAGE=" 45 | ) 46 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/deactivate.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | if defined _OLD_VIRTUAL_PROMPT ( 4 | set "PROMPT=%_OLD_VIRTUAL_PROMPT%" 5 | ) 6 | set _OLD_VIRTUAL_PROMPT= 7 | 8 | if defined _OLD_VIRTUAL_PYTHONHOME ( 9 | set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" 10 | set _OLD_VIRTUAL_PYTHONHOME= 11 | ) 12 | 13 | if defined _OLD_VIRTUAL_PATH ( 14 | set "PATH=%_OLD_VIRTUAL_PATH%" 15 | ) 16 | 17 | set _OLD_VIRTUAL_PATH= 18 | 19 | set VIRTUAL_ENV= 20 | 21 | :END 22 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/easy_install-3.7-script.py: -------------------------------------------------------------------------------- 1 | #!"E:\PyCharm\Data Structures\venv\Scripts\python.exe" 2 | # EASY-INSTALL-ENTRY-SCRIPT: 'setuptools==28.8.0','console_scripts','easy_install-3.7' 3 | __requires__ = 'setuptools==28.8.0' 4 | import re 5 | import sys 6 | from pkg_resources import load_entry_point 7 | 8 | if __name__ == '__main__': 9 | sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) 10 | sys.exit( 11 | load_entry_point('setuptools==28.8.0', 'console_scripts', 'easy_install-3.7')() 12 | ) 13 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/easy_install-3.7.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/easy_install-3.7.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/easy_install-script.py: -------------------------------------------------------------------------------- 1 | #!"E:\PyCharm\Data Structures\venv\Scripts\python.exe" 2 | # EASY-INSTALL-ENTRY-SCRIPT: 'setuptools==28.8.0','console_scripts','easy_install' 3 | __requires__ = 'setuptools==28.8.0' 4 | import re 5 | import sys 6 | from pkg_resources import load_entry_point 7 | 8 | if __name__ == '__main__': 9 | sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) 10 | sys.exit( 11 | load_entry_point('setuptools==28.8.0', 'console_scripts', 'easy_install')() 12 | ) 13 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/easy_install.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/easy_install.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/libcrypto-1_1-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/libcrypto-1_1-x64.dll -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/libssl-1_1-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/libssl-1_1-x64.dll -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/pip-script.py: -------------------------------------------------------------------------------- 1 | #!"E:\PyCharm\Data Structures\venv\Scripts\python.exe" 2 | # EASY-INSTALL-ENTRY-SCRIPT: 'pip==9.0.1','console_scripts','pip' 3 | __requires__ = 'pip==9.0.1' 4 | import re 5 | import sys 6 | from pkg_resources import load_entry_point 7 | 8 | if __name__ == '__main__': 9 | sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) 10 | sys.exit( 11 | load_entry_point('pip==9.0.1', 'console_scripts', 'pip')() 12 | ) 13 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/pip.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/pip.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/pip3-script.py: -------------------------------------------------------------------------------- 1 | #!"E:\PyCharm\Data Structures\venv\Scripts\python.exe" 2 | # EASY-INSTALL-ENTRY-SCRIPT: 'pip==9.0.1','console_scripts','pip3' 3 | __requires__ = 'pip==9.0.1' 4 | import re 5 | import sys 6 | from pkg_resources import load_entry_point 7 | 8 | if __name__ == '__main__': 9 | sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) 10 | sys.exit( 11 | load_entry_point('pip==9.0.1', 'console_scripts', 'pip3')() 12 | ) 13 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/pip3.7-script.py: -------------------------------------------------------------------------------- 1 | #!"E:\PyCharm\Data Structures\venv\Scripts\python.exe" 2 | # EASY-INSTALL-ENTRY-SCRIPT: 'pip==9.0.1','console_scripts','pip3.7' 3 | __requires__ = 'pip==9.0.1' 4 | import re 5 | import sys 6 | from pkg_resources import load_entry_point 7 | 8 | if __name__ == '__main__': 9 | sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) 10 | sys.exit( 11 | load_entry_point('pip==9.0.1', 'console_scripts', 'pip3.7')() 12 | ) 13 | -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/pip3.7.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/pip3.7.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/pip3.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/pip3.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/pyexpat.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/pyexpat.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/python.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/python.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/python3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/python3.dll -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/python37.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/python37.dll -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/pythonw.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/pythonw.exe -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/select.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/select.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/sqlite3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/sqlite3.dll -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/tcl86t.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/tcl86t.dll -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/tk86t.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/tk86t.dll -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/unicodedata.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/unicodedata.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/vcruntime140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/vcruntime140.dll -------------------------------------------------------------------------------- /Google Data Structures/venv/Scripts/winsound.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Google Data Structures/venv/Scripts/winsound.pyd -------------------------------------------------------------------------------- /Google Data Structures/venv/pyvenv.cfg: -------------------------------------------------------------------------------- 1 | home = C:\Users\neera\AppData\Local\Programs\Python\Python37 2 | include-system-site-packages = false 3 | version = 3.7.1 4 | -------------------------------------------------------------------------------- /Greedy Algorithms/activity_selection.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem Statement: https://www.geeksforgeeks.org/python-program-for-activity-selection-problem-greedy-algo-1/ 3 | ''' 4 | 5 | def maximizeActivitySelection(s, f): 6 | # s[i] - start time of ith task 7 | # f[i] - finish time of ith task 8 | 9 | n = len(s) 10 | 11 | # first we sort the array based on finishing times 12 | s = [x for x, _ in sorted(zip(s, f), key=lambda i: i[1])] 13 | f = sorted(f) 14 | 15 | # we always select the first activity 16 | i = 0 17 | count = 1 18 | 19 | for j in range(1, n): 20 | # if the start time of the current activity if 21 | # greater than the finish time of the last activity 22 | # we select it 23 | if s[j] >= f[i]: 24 | count += 1 25 | i = j 26 | 27 | return count -------------------------------------------------------------------------------- /Greedy Algorithms/fractional_knapsack.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem: https://www.sanfoundry.com/python-program-solve-fractional-knapsack-problem-using-greedy-algorithm/ 3 | ''' 4 | 5 | def fractional_knapsack(value, weight, capacity): 6 | ''' 7 | value[i] - value of ith item 8 | weigth[i] - weight of ith item 9 | capacty - max capacity our knapsack can hold 10 | 11 | our goal is to fill the knapsack with max value 12 | ''' 13 | n = len(value) 14 | ratio = [v/w for v, w in zip(value, weight)] 15 | indices = list(range(len(n))) 16 | fractions = [0]*n 17 | 18 | indices.sort(key=lambda x: ratio[x], reverse=True) 19 | 20 | total_value = 0 21 | for i in indices: 22 | if weight[i] <= capacity: 23 | fractions[i] = 1 24 | capacity -= weight[i] 25 | total_value += value[i] 26 | else: 27 | fractions[i] = capacity/weight[i] 28 | total_value += value[i] * capacity/weight[i] 29 | break 30 | return fractions, total_value 31 | 32 | -------------------------------------------------------------------------------- /Greedy Algorithms/maximize_reward_matrix.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem Statement: https://algodaily.com/lessons/getting-to-know-greedy-algorithms-through-examples?view=article 3 | ''' 4 | 5 | def maximizeReward(matrix): 6 | # start cell - (0, 0) 7 | # goal cell - (m, n) 8 | # can only move right or down 9 | m = len(matrix)-1 10 | n = len(matrix[0])-1 11 | 12 | i, j = 0, 0 13 | curr_cost = 0 14 | 15 | while (i, j) != (m, n): 16 | curr_cost += matrix[i][j] 17 | if i == m: 18 | j += 1 19 | continue 20 | if j == n: 21 | i += 1 22 | continue 23 | 24 | if matrix[i+1][j] > matrix[i][j+1]: 25 | i += 1 26 | else: 27 | j += 1 28 | 29 | return curr_cost + matrix[m][n] 30 | 31 | test = [[5, 20, 36], [4, 34, 32], [100, 23, 45]] # expected 138 32 | print(maximizeReward(test)) 33 | -------------------------------------------------------------------------------- /Greedy Algorithms/minimum_energy.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem: https://leetcode.com/contest/weekly-contest-216/problems/minimum-initial-energy-to-finish-tasks/ 3 | ''' 4 | 5 | class Solution: 6 | def minimumEffort(self, tasks): 7 | # sort them based of diff 8 | tasks = sorted(tasks, key = lambda x: x[1]-x[0], reverse=True) 9 | total_cost = curr_cost = 0 10 | # curr cost is the residual cost we carry to the next task 11 | for cost, min_cost in tasks: 12 | if min_cost > curr_cost: 13 | total_cost += (min_cost-curr_cost) 14 | curr_cost = min_cost 15 | curr_cost -= cost 16 | return total_cost 17 | 18 | -------------------------------------------------------------------------------- /Greedy Algorithms/smallest_string.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem: https://leetcode.com/contest/weekly-contest-216/problems/smallest-string-with-a-given-numeric-value/ 3 | ''' 4 | 5 | class Solution: 6 | def getSmallestString(self, n, k): 7 | alphabets_value = list(range(1, 27)) 8 | pointer = len(alphabets_value) - 1 9 | 10 | chars_used = 0 11 | result = [] 12 | 13 | while chars_used < n: 14 | chars_used += 1 15 | if (k-alphabets_value[pointer]) < (n-chars_used): 16 | chars_used -= 1 17 | pointer -= 1 18 | continue 19 | result.append(pointer+1) 20 | k -= alphabets_value[pointer] 21 | 22 | result = list(reversed([chr(x+96) for x in result])) 23 | 24 | return "".join(result) -------------------------------------------------------------------------------- /Greedy Algorithms/two_city_interview_scheduling.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def twoCitySchedCost(self, costs): 3 | costs.sort(key=lambda x: x[0]-x[1]) 4 | total_cost = 0 5 | n = len(costs) 6 | for i in range(n): 7 | if i < n/2: 8 | total_cost += costs[i][0] 9 | else: 10 | total_cost += costs[i][1] 11 | return total_cost 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data-Structures-and-Algorithms-in-Python 2 | Implementation of Data-Structures-and-Algorithms-in-Python. 3 | My Resources include: 4 | * "A common sense guide to data structures and algorithms" by jay wengrow, 5 | * Udacity Course - "Data Structures and Algorithms in Python" 6 | * MIT 6.006 - Introduction to Algorithms 7 | * Mentioned the other resources in the respective script itself 8 | 9 | -------------------------------------------------------------------------------- /Sorting/bubble_sort.py: -------------------------------------------------------------------------------- 1 | # reference: https://realpython.com/sorting-algorithms-python/#the-bubble-sort-algorithm-in-python 2 | 3 | import random 4 | 5 | def bubble_sort(arr): 6 | flag = True 7 | n = len(arr) 8 | for i in range(n): 9 | for j in range(n-1-i): 10 | if arr[j] > arr[j + 1]: 11 | arr[j+1], arr[j] = arr[j], arr[j+1] 12 | flag = False 13 | if flag: 14 | break 15 | 16 | return arr 17 | 18 | for k in range(10): 19 | random_array = [random.randrange(100) for i in range(10)] 20 | print("Array Before Sorting: {}".format(random_array)) 21 | sorted_array = bubble_sort(random_array) 22 | print("Array After Sorting: {}".format(sorted_array)) 23 | print("-----------------------") 24 | -------------------------------------------------------------------------------- /Sorting/insertion_sort.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | def insertion_sort(arr): 4 | if len(arr) == 1: 5 | return arr 6 | for i in range(1, len(arr)): 7 | current_index = i 8 | for j in reversed(range(i)): 9 | if arr[current_index] < arr[j]: 10 | arr[current_index], arr[j] = arr[j], arr[current_index] 11 | current_index = j 12 | return arr 13 | 14 | for k in range(10): 15 | random_array = [random.randrange(100) for i in range(10)] 16 | print("Array Before Sorting: {}".format(random_array)) 17 | sorted_array = insertion_sort(random_array) 18 | print("Array After Sorting: {}".format(sorted_array)) 19 | print("-----------------------") -------------------------------------------------------------------------------- /Sorting/merge_sort.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | def merge(left_array, right_array, main_array): 4 | i = 0 # left array counter 5 | j = 0 # right array counter 6 | k = 0 # main array counter 7 | 8 | while i < len(left_array) and j < len(right_array): 9 | if left_array[i] <= right_array[j]: 10 | main_array[k] = left_array[i] 11 | i += 1 12 | elif left_array[i] > right_array[j]: 13 | main_array[k] = right_array[j] 14 | j += 1 15 | k += 1 16 | 17 | while i < len(left_array): 18 | main_array[k] = left_array[i] 19 | i += 1 20 | k += 1 21 | 22 | while j < len(right_array): 23 | main_array[k] = right_array[j] 24 | j += 1 25 | k += 1 26 | 27 | return main_array 28 | 29 | def merge_sort(arr): 30 | if len(arr) < 2: 31 | return arr 32 | 33 | mid = len(arr) // 2 34 | left_array = arr[:mid] 35 | right_array = arr[mid:] 36 | 37 | left_array = merge_sort(left_array) 38 | right_array = merge_sort(right_array) 39 | 40 | return merge(left_array, right_array, arr) 41 | 42 | for k in range(10): 43 | random_array = [random.randrange(100) for i in range(10)] 44 | print("Array Before Sorting: {}".format(random_array)) 45 | sorted_array = merge_sort(random_array) 46 | print("Array After Sorting: {}".format(sorted_array)) 47 | print("-----------------------") -------------------------------------------------------------------------------- /Sorting/playground.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/Sorting/playground.py -------------------------------------------------------------------------------- /Sorting/quick_sort.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | def partition(arr, start_index, end_index): 4 | ''' 5 | Partitioning 6 | -------------- 7 | 1. Pick an element (called pivot) 8 | 2. manipulate the array such that 9 | 3. left elements to the pivot are lesser than pivot 10 | 4. right elements to pivot are greater than pivot 11 | ''' 12 | 13 | pivot_element = arr[end_index] 14 | partition_index = start_index 15 | 16 | while start_index < end_index: 17 | if arr[start_index] <= pivot_element: 18 | arr[start_index], arr[partition_index] = arr[partition_index], arr[start_index] 19 | partition_index += 1 20 | start_index += 1 21 | 22 | arr[partition_index], arr[end_index] = arr[end_index], arr[partition_index] 23 | 24 | return partition_index 25 | 26 | 27 | def quick_sort_helper(arr, start_index, end_index): 28 | if start_index >= end_index: 29 | return 30 | 31 | partition_index = partition(arr, start_index, end_index) 32 | 33 | quick_sort_helper(arr, start_index, partition_index-1) 34 | quick_sort_helper(arr, partition_index + 1, end_index) 35 | 36 | return arr 37 | 38 | def quick_sort(arr): 39 | start_index = 0 40 | end_index = len(arr) - 1 41 | return quick_sort_helper(arr, start_index, end_index) 42 | 43 | for k in range(10): 44 | random_array = [random.randrange(100) for i in range(10)] 45 | print("Array Before Sorting: {}".format(random_array)) 46 | sorted_array = quick_sort(random_array) 47 | print("Array After Sorting: {}".format(sorted_array)) 48 | print("-----------------------") -------------------------------------------------------------------------------- /Sorting/quickselect.py: -------------------------------------------------------------------------------- 1 | def swap(idx1, idx2, array): 2 | array[idx1], array[idx2] = array[idx2], array[idx1] 3 | 4 | def partition(start_index, end_index, array): 5 | leftPointer = start_index + 1 6 | rightPointer = end_index 7 | pivotPointer = start_index 8 | while leftPointer <= rightPointer: 9 | if array[leftPointer] > array[pivotPointer] and array[rightPointer] < array[pivotPointer]: 10 | swap(leftPointer, rightPointer, array) 11 | elif array[leftPointer] <= array[pivotPointer]: 12 | leftPointer += 1 13 | elif array[rightPointer] >= array[pivotPointer]: 14 | rightPointer -= 1 15 | swap(rightPointer, pivotPointer, array) 16 | pivotPointer = rightPointer 17 | 18 | return pivotPointer 19 | 20 | def quickselect_helper(array, start_index, end_index, k): 21 | partition_index = partition(start_index, end_index, array) 22 | if k > partition_index: 23 | return quickselect_helper(array, partition_index + 1, end_index, k) 24 | elif k < partition_index: 25 | return quickselect_helper(array, start_index, partition_index - 1, k) 26 | else: 27 | return array[partition_index] 28 | 29 | def quickselect(array, k): 30 | ''' 31 | Time Complexity - O(n) 32 | ''' 33 | return quickselect_helper(array, 0, len(array)-1, k) 34 | 35 | array = [8, 5, 2, 9, 7, 6, 3] 36 | k = 2 37 | print(quickselect(array, k)) -------------------------------------------------------------------------------- /Sorting/selection_sort.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | def selection_sort(arr): 4 | for i in range(len(arr)): 5 | min_index = i 6 | for j in range(i+1, len(arr)): 7 | if arr[min_index] > arr[j]: 8 | min_index = j 9 | arr[i], arr[min_index] = arr[min_index], arr[i] 10 | return arr 11 | 12 | for k in range(10): 13 | random_array = [random.randrange(100) for i in range(10)] 14 | print("Array Before Sorting: {}".format(random_array)) 15 | sorted_array = selection_sort(random_array) 16 | print("Array After Sorting: {}".format(sorted_array)) 17 | print("-----------------------") -------------------------------------------------------------------------------- /Trees/Binary Search Trees/closest_value_in_BST.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a target value, return the closet value in BST 3 | ''' 4 | class TreeNode: 5 | def __init__(self, val, left=None, right=None): 6 | self.val = val 7 | self.left = left 8 | self.right = right 9 | 10 | def closestValueBST(root, target): 11 | # Time Complexity = O(logN) 12 | # Worst Case Time Complexity = O(N) this occurs if there is a single branch 13 | # Space Complexity will be the same as time complexity if done recursively else O(1) 14 | return closestValueBSTHelper(root, target, float('inf')) 15 | 16 | def closestValueBSTHelper(root, target, closestVal): 17 | if not root: 18 | return closestVal 19 | if abs(target - root.val) < abs(target - closestVal): 20 | closestVal = root.val 21 | if target > root.val: 22 | return closestValueBSTHelper(root.right, target, closestVal) 23 | elif target < root.val: 24 | return closestValueBSTHelper(root.left, target, closestVal) 25 | else: 26 | return closestVal 27 | 28 | def closestValueBSTIteratively(root, target): 29 | if not root: 30 | return None 31 | closestValue = float('inf') 32 | stack = [root] 33 | while stack: 34 | node = stack.pop() 35 | if not node: 36 | return closestValue 37 | if abs(target - node.val) < abs(target - closestValue): 38 | closestValue = node.val 39 | if target > node.val: 40 | stack.append(node.right) 41 | elif target < node.val: 42 | stack.append(node.left) 43 | else: 44 | break 45 | return closestValue -------------------------------------------------------------------------------- /Trees/Binary Search Trees/is_valid_bst.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | 8 | class Solution: 9 | def isValidBST(self, root): 10 | 11 | if not root: 12 | return True 13 | 14 | stack = [] 15 | current_node = root 16 | previous_val = float('-inf') 17 | 18 | while stack or current_node: 19 | 20 | while current_node: 21 | stack.append(current_node) 22 | current_node = current_node.left 23 | 24 | current_node = stack.pop() 25 | 26 | current_val = current_node.val 27 | 28 | if current_val <= previous_val: 29 | return False 30 | 31 | previous_val = current_val 32 | current_node = current_node.right 33 | 34 | return True 35 | 36 | def isValidBSTRecursive(self, root): 37 | def helper(root, lower=float('-inf'), upper=float('inf')): 38 | if not root: 39 | return True 40 | 41 | val = root.val 42 | 43 | if val <= lower or val >= upper: 44 | return False 45 | 46 | if not helper(root.right, val, upper): 47 | return False 48 | if not helper(root.left, lower, val): 49 | return False 50 | return True 51 | 52 | return helper(root) -------------------------------------------------------------------------------- /Trees/binary_tree_topologies.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a binary tree, find the number of topologies it can take 3 | 4 | Solution 5 | --------- 6 | 1. Say F(n) is the number of binary tree topologies with n nodes 7 | 2. Say a tree has 5 nodes. If we fix the root, the number of binary tree topologies are: 8 | 3. F(0)*F(4) + F(1)*F(3) + F(2)*F(2) + F(3)*F(1) + F(4)*F(0) where the left function represents the 9 | number of binary tree topologies for left subtree and the right function for right subtree 10 | 4. So essentially we iterate through 0 to n-1, and calculate F(i)*F(n-1-i) and sum it cummulatively 11 | 5. Also, we will need memoization here because we will be calculating the value of F(n) multiple times 12 | ''' 13 | 14 | def number_of_binary_tree_topologies(n): 15 | memo = dict() 16 | return number_of_binary_tree_topologies_helper(n, memo) 17 | 18 | def number_of_binary_tree_topologies_helper(n, memo): 19 | if n == 0 or n == 1: 20 | return 1 21 | if n in memo: 22 | return n 23 | n_topologies = 0 24 | for i in range(n): 25 | n_topologies += number_of_binary_tree_topologies_helper(i, memo) * number_of_binary_tree_topologies_helper(n-1-i, memo) 26 | memo[n] = n_topologies 27 | return memo[n] 28 | 29 | print(number_of_binary_tree_topologies(3)) 30 | -------------------------------------------------------------------------------- /Trees/in-order traversal.py: -------------------------------------------------------------------------------- 1 | def inorder_traversal(root): 2 | result = [] 3 | stack = [] 4 | node = root 5 | while stack or node: 6 | while node: 7 | stack.append(node) 8 | node = node.left 9 | node = stack.pop() 10 | # notice we are appending only valid nodes to the stack 11 | result.append(node.val) 12 | node = node.right 13 | return result -------------------------------------------------------------------------------- /Trees/invert_binary_tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, val=0, left=None, right=None): 4 | self.val = val 5 | self.left = left 6 | self.right = right 7 | 8 | class Solution: 9 | def invertTree(self, root): 10 | if not root: 11 | return None 12 | temp = root.left 13 | root.left = root.right 14 | root.right = temp 15 | 16 | root.left = self.invertTree(root.left) 17 | root.right = self.invertTree(root.right) 18 | 19 | return root 20 | 21 | def invertTreeIteratively(self, root): 22 | if not root: 23 | return None 24 | stack = [root] 25 | while stack: 26 | node = stack.pop() 27 | if not node: 28 | continue 29 | # swap 30 | temp = node.left 31 | node.left = node.right 32 | node.right = temp 33 | 34 | stack.append(node.right) 35 | stack.append(node.left) 36 | return root -------------------------------------------------------------------------------- /Trees/level-order traversal recursion.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, val=0, left=None, right=None): 4 | self.val = val 5 | self.left = left 6 | self.right = right 7 | 8 | class Solution: 9 | def levelOrder(self, root): 10 | if not root: 11 | return 12 | 13 | maxDepth = self.getMaxDepth(root) 14 | 15 | final_result = [] 16 | for level in range(1, maxDepth+1): 17 | result = [] 18 | self.helper(root, 1, level, result) 19 | final_result.append(result) 20 | 21 | return final_result 22 | 23 | def getMaxDepth(self, root): 24 | if not root: 25 | return 0 26 | return 1 + max(self.getMaxDepth(root.left), self.getMaxDepth(root.right)) 27 | 28 | 29 | def helper(self, node, current_depth, required_depth, result): 30 | if not node: 31 | return 32 | 33 | if current_depth == required_depth: 34 | result.append(node.val) 35 | return 36 | 37 | self.helper(node.left, current_depth + 1, required_depth, result) 38 | self.helper(node.right, current_depth + 1, required_depth, result) -------------------------------------------------------------------------------- /Trees/level-order traversal.py: -------------------------------------------------------------------------------- 1 | def levelorder_traversal(root): 2 | result = [] 3 | queue = [root] 4 | while queue: 5 | level = [] 6 | children = [] 7 | for node in queue: 8 | if not node: 9 | continue 10 | level.append(node.val) 11 | children.append(node.left) 12 | children.append(node.right) 13 | if len(level) > 0: 14 | result.append(level) 15 | queue = children 16 | return result -------------------------------------------------------------------------------- /Trees/lowest common ancestor.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | 8 | class Solution: 9 | def lowestCommonAncestor(self, root, p, q): 10 | if not root: 11 | return None 12 | 13 | if root == p or root == q: 14 | return root 15 | 16 | left = self.lowestCommonAncestor(root.left, p, q) 17 | right = self.lowestCommonAncestor(root.right, p, q) 18 | 19 | if left and right: 20 | return root 21 | 22 | return left or right -------------------------------------------------------------------------------- /Trees/path sum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. 3 | 4 | example 5 | --------- 6 | sum = 22 7 | 8 | 5 9 | / \ 10 | 4 8 11 | / / \ 12 | 11 13 4 13 | / \ \ 14 | 7 2 1 15 | 16 | output: True 17 | ''' 18 | 19 | 20 | # Definition for a binary tree node. 21 | class TreeNode: 22 | def __init__(self, val=0, left=None, right=None): 23 | self.val = val 24 | self.left = left 25 | self.right = right 26 | 27 | class Solution: 28 | def hasPathSum(self, root, _sum): 29 | return self.helper(root, 0, _sum) 30 | 31 | def helper(self, node, current_sum, required_sum): 32 | 33 | if not node: 34 | return False 35 | 36 | current_sum += node.val 37 | 38 | if node.left == None and node.right == None: 39 | if current_sum == required_sum: 40 | return True 41 | else: 42 | return False 43 | 44 | return self.helper(node.left, current_sum, required_sum) or self.helper(node.right, current_sum, required_sum) 45 | 46 | 47 | -------------------------------------------------------------------------------- /Trees/post-order traversal.py: -------------------------------------------------------------------------------- 1 | def postorder_traversal(root): 2 | result = [] 3 | stack = [(False, root)] 4 | while stack: 5 | is_visited, node = stack.pop() 6 | if not node: 7 | continue 8 | if is_visited: 9 | result.append(node.val) 10 | else: 11 | stack.append((True, node)) 12 | stack.append((False, node.right)) 13 | stack.append((False, node.left)) 14 | return result -------------------------------------------------------------------------------- /Trees/pre-order traversal.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Iterative Solution for Preorder Traversal 3 | ''' 4 | 5 | def preorder_traversal(root): 6 | stack = [root] 7 | result = [] 8 | while stack: 9 | node = stack.pop() 10 | if not node: 11 | continue 12 | result.append(node.val) 13 | stack.append(node.right) 14 | stack.append(node.left) 15 | return result -------------------------------------------------------------------------------- /Trees/serialize and deserialize a binary tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode(object): 3 | def __init__(self, x): 4 | self.val = x 5 | self.left = None 6 | self.right = None 7 | 8 | class Codec: 9 | 10 | def serialize(self, root): 11 | """Encodes a tree to a single string. 12 | 13 | :type root: TreeNode 14 | :rtype: str 15 | """ 16 | queue = [root] 17 | result = [] 18 | while queue: 19 | children = [] 20 | for node in queue: 21 | result.append(node.val if node != None else None) 22 | if not node: 23 | continue 24 | children.append(node.left) 25 | children.append(node.right) 26 | queue = children 27 | return result 28 | 29 | def deserialize(self, data): 30 | """Decodes your encoded data to tree. 31 | 32 | :type data: str 33 | :rtype: TreeNode 34 | """ 35 | # make node objects from the data 36 | nodes = [TreeNode(val) if val != None else None for val in data] 37 | reversed_nodes = [] 38 | for node in reversed(nodes): 39 | reversed_nodes.append(node) 40 | root = reversed_nodes.pop() 41 | for node in nodes: 42 | if node == None: 43 | continue 44 | node.left = reversed_nodes.pop() 45 | node.right = reversed_nodes.pop() 46 | return root -------------------------------------------------------------------------------- /Trees/symmetric tree recursion.py: -------------------------------------------------------------------------------- 1 | # Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). 2 | 3 | ''' 4 | example 5 | 1 6 | / \\ 7 | 2 2 8 | / \ / \\ 9 | 3 4 4 3 10 | ''' 11 | 12 | # Definition for a binary tree node. 13 | class TreeNode: 14 | def __init__(self, val=0, left=None, right=None): 15 | self.val = val 16 | self.left = left 17 | self.right = right 18 | 19 | class Solution: 20 | def isSymmetric(self, root): 21 | return self.recursiveMirror(root, root) 22 | 23 | def recursiveMirror(self, nodeA, nodeB): 24 | 25 | # base case 26 | if nodeA == None and nodeB == None: 27 | return True 28 | elif nodeA == None or nodeB == None: 29 | return False 30 | 31 | return self.recursiveMirror(nodeA.left, nodeB.right) and self.recursiveMirror(nodeA.right, nodeB.left) and nodeA.val == nodeB.val -------------------------------------------------------------------------------- /amazonOA/amazon_prime_air_route.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a list of forward air routes and backward air routes, 3 | and a maximum distance, return pairs of optimal routes such that 4 | the sum of forward distance and backward distance is just less than 5 | or equal to the optimal distance. 6 | 7 | example 8 | -------- 9 | max distance: 11000 10 | forward route: [[1, 3000], [2, 5000], [3, 4000], [4, 10000]] 11 | backward route: [[1, 2000], [2, 3000], [3, 4000]] 12 | 13 | ans: (2, 3) 14 | ''' 15 | 16 | def optimal_air_route(forward_routes, backward_routes, optimal_dist): 17 | ''' 18 | The idea is to sort forward routes, and for each backward route, 19 | we find the optimal forward route (such that the forward_dist + backward_dist <= optimal_dist) 20 | for that route using binary search on forward routes. 21 | 22 | Time complexity - NlogN (for sorting forward routes) + MlogN(for binary search) 23 | ''' 24 | forward_routes = sorted(forward_routes, key=lambda x: x[1]) 25 | result = [0, 0, 0] 26 | for route_id, dist in backward_routes: 27 | i = 0 28 | j = len(forward_routes) 29 | target = optimal_dist - dist 30 | while i < j: 31 | mid = (i + j) // 2 32 | val = forward_routes[mid][1] 33 | if target == val: 34 | result = [forward_routes[mid][0], route_id, val] 35 | return result[:2] 36 | elif val > target: 37 | j = mid - 1 38 | else: 39 | i = mid 40 | 41 | total_dist = forward_routes[i][1] + dist 42 | if total_dist > result[2]: 43 | result = [forward_routes[i][0], route_id, total_dist] 44 | 45 | return result[:2] 46 | 47 | f = [[1, 3000], [2, 5000], [3, 4000], [4, 10000]] 48 | b = [[1, 2000], [2, 3000], [3, 4000]] 49 | d = 11000 50 | 51 | print(optimal_air_route(f, b, d)) 52 | -------------------------------------------------------------------------------- /amazonOA/k_distinct_substrings.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string s and an int k, return all unique substrings of s of size k with k distinct characters. 3 | A substring is a contiguous piece of array 4 | 5 | Example: 6 | Input: s = "abcabc", k = 3 7 | Output: ["abc", "bca", "cab"] 8 | ''' 9 | def k_distinct_substrings(s, k): 10 | j = 0 11 | result = set() 12 | for i in range(len(s)+1): 13 | while i - j >= k: 14 | if i - j == k: 15 | # check if the subarray of size k has distinct characters 16 | if len(set(s[j:i])) == k: 17 | result.add(s[j:i]) 18 | j += 1 19 | return list(result) 20 | 21 | print(k_distinct_substrings("abcabc", 3)) 22 | print(k_distinct_substrings("abacab", 3)) 23 | print(k_distinct_substrings("awaglknagawunagwkwagl", 4)) -------------------------------------------------------------------------------- /amazonOA/leetcode_problems.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 1. https://leetcode.com/problems/pairs-of-songs-with-total-durations-divisible-by-60/ 3 | 2. https://leetcode.com/problems/k-closest-points-to-origin/submissions/ 4 | ''' -------------------------------------------------------------------------------- /arrays/addition_with_carry.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Add Two Numbers using Normal way of addition 3 | ''' 4 | 5 | def convert_numbers_to_list(num): 6 | result = [] 7 | while num > 0: 8 | result.append(num%10) 9 | num = num // 10 10 | return result[::-1] 11 | 12 | def add_two_numbers(num1, num2): 13 | # convert numbers to list 14 | num1_list = convert_numbers_to_list(num1) 15 | num2_list = convert_numbers_to_list(num2) 16 | 17 | _sum = 0 18 | result = [] 19 | 20 | for _ in range(max(len(num1_list), len(num2_list))): 21 | 22 | if len(num1_list) > 0: 23 | _sum += num1_list[-1] 24 | if len(num2_list) > 0: 25 | _sum += num2_list[-1] 26 | 27 | place = _sum % 10 28 | _sum = _sum // 10 29 | 30 | result.append(place) 31 | 32 | num1_list = num1_list[:-1] 33 | num2_list = num2_list[:-1] 34 | 35 | if _sum != 0: 36 | result.append(_sum) 37 | 38 | result = list(map(str, result)) 39 | result = result[::-1] 40 | 41 | return int("".join(result)) 42 | 43 | print(add_two_numbers(1224, 1)) -------------------------------------------------------------------------------- /arrays/intersection of two arrays.py: -------------------------------------------------------------------------------- 1 | def intersection(nums1, nums2): 2 | ''' 3 | Constant Space Solution 4 | ''' 5 | nums1 = sorted(nums1) 6 | nums2 = sorted(nums2) 7 | i = 0 8 | j = 0 9 | result = set() 10 | while i < len(nums1) and j < len(nums2): 11 | if nums1[i] == nums2[j]: 12 | result.add(nums1[i]) 13 | i += 1 14 | j += 1 15 | elif nums1[i] < nums2[j]: 16 | i += 1 17 | else: 18 | j += 1 19 | return list(result) -------------------------------------------------------------------------------- /arrays/merge_k_sorted_arrays.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | def merge_arrays(arr_list): 4 | # remove empty arrays 5 | arr_list = [arr for arr in arr_list if len(arr) > 0] 6 | k = len(arr_list) 7 | min_heap = [] 8 | for i in range(k): 9 | arr = arr_list[i] 10 | val = arr[0] 11 | heapq.heappush(min_heap, (val, 0, i)) # (val, element_idx, arr_idx) 12 | 13 | merged_array = [] 14 | while len(min_heap) > 0: 15 | # pop the root element of heap 16 | root_val, root_idx, arr_idx = heapq.heappop(min_heap) 17 | # add the root element to the merged array 18 | merged_array.append(root_val) 19 | # find the next element to add into the array 20 | next_idx = root_idx + 1 21 | arr = arr_list[arr_idx] 22 | if next_idx == len(arr): 23 | continue 24 | next_val = arr[next_idx] 25 | heapq.heappush(min_heap, (next_val, next_idx, arr_idx)) 26 | 27 | return merged_array 28 | 29 | list1 = [[1, 4, 6, 8], [2, 3, 5, 7], [11, 12, 13, 14], [0, 1, 2]] 30 | print(merge_arrays(list1)) 31 | 32 | -------------------------------------------------------------------------------- /arrays/playground.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /arrays/sliding window/fixed_size_max_subarray.py: -------------------------------------------------------------------------------- 1 | def max_sum_subarray(arr, window_size): 2 | if window_size > arr: 3 | return sum(arr) 4 | j = 0 5 | max_sum = -float('inf') 6 | for i in range(window_size, len(arr)): 7 | _sum = sum(arr[j:i]) 8 | if _sum > max_sum: 9 | max_sum = _sum 10 | j += 1 11 | return max_sum 12 | 13 | arr = [4, 2, 1, 7, 8, 1, 2, 8, 1, 0] 14 | print(max_sum_subarray(arr, 3)) -------------------------------------------------------------------------------- /arrays/sliding window/important_problems.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 1. https://leetcode.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/submissions/ 3 | 2. https://leetcode.com/problems/number-of-substrings-containing-all-three-characters/submissions/ 4 | 3. https://leetcode.com/problems/replace-the-substring-for-balanced-string/submissions/ 5 | 4. https://leetcode.com/problems/max-consecutive-ones-iii/submissions/ 6 | 5. https://leetcode.com/problems/fruit-into-baskets/submissions/ 7 | ''' -------------------------------------------------------------------------------- /arrays/sliding window/longest_substring.py: -------------------------------------------------------------------------------- 1 | ''' 2 | find longest substring length with k distinct characters 3 | ''' 4 | 5 | def longest_substring(arr, k): 6 | ''' 7 | The idea is to prepare a hash map with char - count mapping 8 | and update the hashmap as we move along the array. 9 | when the condition is met i.e number of distinct characters is equal to k 10 | when calculate and update the min size 11 | if the number of distinct characters are more than k, 12 | we decrease the size of the sliding window until the condition is satisfied 13 | ''' 14 | hash_map = {} 15 | j = 0 16 | result = -float('inf') 17 | for i in range(len(arr)): 18 | hash_map[arr[i]] = hash_map[arr[i]] + 1 if arr[i] in hash_map else 1 19 | while len(hash_map) > k: 20 | # remove items with zero in it - because we are checking the len of hashmap as condition 21 | for key, val in hash_map.items(): 22 | if val == 0: 23 | hash_map.pop(key) 24 | hash_map[arr[j]] -= 1 25 | j += 1 26 | else: 27 | if len(hash_map) == k: 28 | size = sum(hash_map.values()) 29 | if size > result: 30 | result = size 31 | return result 32 | 33 | arr = ["a", "a", "a", "h", "h", "i", "b", "c"] 34 | print(longest_substring(arr, 2)) -------------------------------------------------------------------------------- /arrays/sliding window/max_sum_subarray.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Kadanes Algorithm 3 | ''' 4 | 5 | def max_sum_subarray(arr): 6 | current_sum = arr[0] 7 | max_sum = arr[0] 8 | for i in range(1, len(arr)): 9 | current_sum = max(current_sum + arr[i], arr[i]) 10 | max_sum = max(current_sum, max_sum) 11 | 12 | return max_sum 13 | 14 | arr = [-2, 2, 5, -11, 6] 15 | print(max_sum_subarray(arr)) -------------------------------------------------------------------------------- /arrays/sliding window/smallest_subarray_with_given_sum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | find smallest subarray >= x 3 | ''' 4 | 5 | def smallest_subarray(arr, target): 6 | ''' 7 | The idea is to increase the size of the sliding window 8 | until we reach the desired criterion which is sum(subarray) >= x 9 | Once the reach the criterion, we decrease the size of the window 10 | and test the condition again so that we get the minimum size 11 | ''' 12 | j = 0 13 | minSize = float('inf') 14 | for i in range(len(arr)): 15 | subarray = arr[j:i] 16 | # assuming that each element in the array is less than target 17 | while sum(subarray) >= target and j < i: 18 | size = i - j 19 | if size < minSize: 20 | minSize = size 21 | j += 1 22 | subarray = arr[j:i] 23 | 24 | return minSize 25 | 26 | arr = [4, 2, 2, 7, 1, 8, 2, 1, 0] 27 | print(smallest_subarray(arr, 8)) -------------------------------------------------------------------------------- /arrays/sliding window/subarray_with_K_distinct_elements.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem: https://leetcode.com/problems/subarrays-with-k-different-integers/submissions/ 3 | ''' 4 | 5 | class Solution: 6 | def subarraysWithKDistinct(self, A, K): 7 | ''' 8 | This is basically saying, give me the amount of subarrays 9 | we can form with at most K, and give me the amount of subarrays 10 | we can form with at most K-1, and the diff between the two will be ONLY 11 | subarrays at K (since we have eliminated everything K-1 and under). 12 | 13 | This is the trick used in atmostK sliding window problems 14 | ''' 15 | return self.atMostK(A, K) - self.atMostK(A, K-1) 16 | 17 | def atMostK(self, A, K): 18 | j = 0 19 | hash_map = dict() 20 | result = 0 21 | for i, val in enumerate(A): 22 | if hash_map.get(val, 0) == 0: 23 | K -= 1 24 | hash_map[val] = hash_map[val] + 1 if val in hash_map else 1 25 | while K < 0 and j<=i: 26 | hash_map[A[j]] -= 1 27 | if hash_map[A[j]] == 0: 28 | K += 1 29 | j += 1 30 | # Generally in problems they ask for the max length or min length of subarray 31 | # but here in this problem they are asking for the number of possibilities 32 | # coincidentally, the length of the subarray also gives us the number of possibilites 33 | # example: [1, 2, 1, 2] - length = 4, possibilities are [1, 2, 1], [2, 1, 2], [1, 2], [1, 2, 1, 2] which is 4 34 | # i-j+1 is the length of subarray with atmost K distinct elements 35 | result += i - j + 1 36 | return result -------------------------------------------------------------------------------- /dynamic-programming/01_knapsack.py: -------------------------------------------------------------------------------- 1 | ''' 2 | problem: https://www.techiedelight.com/0-1-knapsack-problem/ 3 | ''' 4 | 5 | def knapsack_01(values, weights, capacity): 6 | n = len(values)-1 7 | memo = dict() 8 | return helper_dp(values, weights, capacity, n, memo) 9 | 10 | def helper_dp(values, weights, capacity, n, memo): 11 | # base case 12 | # the capacity is negative 13 | # -inf because we do not want to consider the item that leads to such value 14 | if capacity < 0: 15 | return float('-inf') 16 | 17 | # if n_items = 0 or capacity == 0 18 | if n < 0 or capacity == 0: 19 | return 0 20 | 21 | # memoization 22 | if (capacity, n) in memo: 23 | return memo[(capacity, n)] 24 | 25 | # we have two choices: either include the item or exclude it 26 | include = helper_dp(values, weights, capacity - weights[n], n-1, memo) + values[n] 27 | exclude = helper_dp(values, weights, capacity, n-1, memo) 28 | 29 | memo[(capacity, n)] = max(include, exclude) 30 | return memo[(capacity, n)] 31 | 32 | # Input: set of items each with a weight and a value 33 | v = [20, 5, 10, 40, 15, 25] 34 | w = [1, 2, 3, 8, 7, 4] 35 | 36 | # Knapsack capacity 37 | W = 10 38 | 39 | print(knapsack_01(v, w, W)) -------------------------------------------------------------------------------- /dynamic-programming/bottom_up/climbing_n_stairs_III.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem Statement and Explanation: Narasimha Karumanchi's Algorithm Design Patterns 3 | ''' 4 | 5 | def climb_stairs(n): 6 | table = [None]*n 7 | # note that step no. = i+1 8 | table[0] = 1 # no. of ways you can climb 1 stair ((1, 0)) 9 | table[1] = 2 # no. of ways you can climb 2 stairs ((1, 1), (2, 0)) 10 | table[2] = 3 # no. of ways you can climb 3 stairs ((1, 2), (2, 1), (3, 0)) 11 | for i in range(3, n): 12 | table[i] = table[i-1] + table[i-2] + table[i-3] 13 | return table[n-1] 14 | 15 | print(climb_stairs(5)) -------------------------------------------------------------------------------- /dynamic-programming/bottom_up/factorial.py: -------------------------------------------------------------------------------- 1 | def factorial_dp(n): 2 | table = [None]*(n+1) 3 | for i in range(n+1): 4 | if i == 0 or i == 1: 5 | table[i] = 1 6 | else: 7 | table[i] = i*table[i-1] 8 | return table[n] 9 | 10 | print(factorial_dp(4)) -------------------------------------------------------------------------------- /dynamic-programming/bottom_up/fibonacci.py: -------------------------------------------------------------------------------- 1 | def fibonacci_dp(n): 2 | table = [None]*(n+1) 3 | for i in range(n+1): 4 | if i == 0 or i == 1: 5 | table[i] = i 6 | else: 7 | table[i] = table[i-1] + table[i-2] 8 | return table[n] 9 | 10 | print(fibonacci_dp(4)) -------------------------------------------------------------------------------- /dynamic-programming/bottom_up/longest_common_subsequence.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Explanation: https://www.youtube.com/watch?v=ASoaQq66foQ 3 | Algorithm: https://www.programiz.com/dsa/longest-common-subsequence 4 | ''' 5 | 6 | def LCS_finder(X, Y): 7 | m = len(X) 8 | n = len(Y) 9 | LCS = [[None for j in range(n+1)] for i in range(m+1)] 10 | 11 | for i in range(m+1): 12 | for j in range(n+1): 13 | if i == 0 or j == 0: 14 | LCS[i][j] = 0 15 | elif X[i-1] == Y[j-1]: 16 | LCS[i][j] = 1 + LCS[i-1][j-1] 17 | else: 18 | LCS[i][j] = max(LCS[i-1][j], LCS[i][j-1]) 19 | 20 | LCS_length = LCS[m][n] # length of the common subsequence 21 | 22 | subsequence = [""]*LCS_length 23 | i, j = m, n 24 | while i > 0 and j > 0: 25 | if X[i-1] == Y[j-1]: 26 | subsequence[LCS_length-1] = X[i-1] 27 | i -= 1 28 | j -= 1 29 | LCS_length -= 1 30 | 31 | elif LCS[i-1][j] > LCS[i][j-1]: 32 | i -= 1 33 | else: 34 | j -= 1 35 | 36 | return "".join(subsequence) 37 | 38 | X = "AGGTAB" 39 | Y = "GXTXAYB" 40 | 41 | print(LCS_finder(X, Y)) -------------------------------------------------------------------------------- /dynamic-programming/bottom_up/max_contiguos_sum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Kadane's Algorithm or Largest subarray sum 3 | ''' 4 | 5 | def max_continguos_sum(arr): 6 | ''' 7 | 1. We cannot use sliding window here as there is no condition for the window size 8 | 2. This is a DP problem 9 | 3. table[i] represents the max sum for the subarray arr[:i] 10 | 4. at each point i, we can start afresh (consider only that element) 11 | or continue adding the previous max sum to the element 12 | ''' 13 | n = len(arr) 14 | table = [None]*n 15 | table[0] = arr[0] 16 | for i in range(1, n): 17 | table[i] = max(table[i-1] + arr[i], arr[i]) 18 | 19 | return table[n-1] 20 | 21 | arr = [2, -6, 3, -2, 4, 1] 22 | print(max_continguos_sum(arr)) -------------------------------------------------------------------------------- /dynamic-programming/bottom_up/max_contiguous_sum_II.py: -------------------------------------------------------------------------------- 1 | ''' 2 | max subarray sum where no two consecutive elements are included (no two adjacent elements) 3 | ''' 4 | 5 | def max_sum_II(arr): 6 | ''' 7 | 1. This is a DP problem 8 | 2. table[i] represents the max sum for the subarray arr[:i] 9 | 3. at each point i, we can choose to keep the element i or not 10 | 4. if we choose to keep element i, we have to add to it dp(i-2) (max sum upto i-2 elements) 11 | because we cannot add dp(i-1) since no two consecutive elements can be selected 12 | 5. if we choose not to keep it, then we continue with the previous max sum of i-1 elements 13 | ''' 14 | n = len(arr) 15 | table = [None] * n 16 | table[0] = arr[0] 17 | table[1] = max(arr[0], arr[1]) 18 | for i in range(2, n): 19 | table[i] = max(arr[i] + table[i-2], table[i-1]) 20 | return table[n-1] 21 | 22 | arr = [-2, 1, -3, 4,-1, 2, 1, -5, 4] 23 | print(max_sum_II(arr)) -------------------------------------------------------------------------------- /dynamic-programming/bottom_up/max_contiguous_sum_III.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Max sum where 3 consecutive elements cannot be included. (2 consecutive elements can) 3 | ''' 4 | 5 | def max_sum_III(arr): 6 | n = len(arr) 7 | table = [None]*n 8 | table[0] = arr[0] 9 | table[1] = max(table[0], arr[1]+arr[0]) 10 | table[2] = max(table[1], arr[2]+table[0], arr[2] + arr[1]) 11 | for i in range(3, n): 12 | table[i] = max(arr[i] + arr[i-1] + table[i-3], arr[i] + table[i-2], table[i-1]) 13 | return table[n-1] 14 | 15 | arr = [2, 13, 16, 100, 4, 5] 16 | print(max_sum_III(arr)) -------------------------------------------------------------------------------- /dynamic-programming/bottom_up/range_sum_query.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Question from Narasimha Karumahanchi's book 3 | ''' 4 | 5 | cummulative_sum_array = [] 6 | def preprocess_cummulative_sum(arr): 7 | ''' 8 | Here, the starting index should be exclusive, hence we add that extra element to cummulative_sum_array 9 | ''' 10 | global cummulative_sum_array 11 | cummulative_sum_array.append(arr[0]) 12 | for i in range(len(arr)): 13 | cummulative_sum_array.append(arr[i] + cummulative_sum_array[i]) 14 | 15 | def range_sum_query(i, j): 16 | return cummulative_sum_array[j+1] - cummulative_sum_array[i] 17 | 18 | arr = [-2, 1, 6, -5, 9, -1, 19] 19 | 20 | preprocess_cummulative_sum(arr) 21 | print(range_sum_query(0, 1)) -------------------------------------------------------------------------------- /dynamic-programming/bottom_up/range_sum_query_2D.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/dynamic-programming/bottom_up/range_sum_query_2D.py -------------------------------------------------------------------------------- /dynamic-programming/bottom_up/recurrence_sum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | F(0) = F(1) = 2 3 | F(n) = sum(2*F(i)*F(i-1) for i in range(1, n)) 4 | ''' 5 | 6 | def f(n): 7 | table = [0]*(n+1) 8 | table[0] = 2 9 | table[1] = 2 10 | table[2] = 2*table[1]*table[0] 11 | for i in range(3, n+1): 12 | table[i] = table[i-1] + 2*table[i-1]*table[i-2] 13 | return table[n] -------------------------------------------------------------------------------- /dynamic-programming/edit_distance.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem: https://www.python-course.eu/levenshtein_distance.php 3 | ''' 4 | 5 | def edit_distance(X, Y): 6 | memo = dict() 7 | result = dp(0, 0, X, Y, memo) 8 | return result 9 | 10 | def dp(i, j, X, Y, memo): 11 | # base case 12 | if i == len(X): # we have reached the end of X, our only option now is to insert all chars from Y into X 13 | return len(Y) - j 14 | elif j == len(Y): # we have reached the end of Y, our only option now is to remove remaining chars from X 15 | return len(X) - i 16 | 17 | # memoization 18 | if (i, j) in memo: 19 | return memo[(i, j)] 20 | 21 | # if both chars are same 22 | if X[i] == Y[j]: 23 | return dp(i+1, j+1, X, Y, memo) 24 | 25 | cost = 1 # we are assuming that the cost of insert and delete and replace is the same and is 1 26 | 27 | # replace, insert, delete 28 | memo[(i, j)] = min(cost + dp(i+1, j+1, X, Y, memo), cost + dp(i, j+1, X, Y, memo), cost + dp(i+1, j, X, Y, memo)) 29 | return memo[(i, j)] 30 | 31 | print(edit_distance("sunday", "saturday")) 32 | print(edit_distance("Python", "Peithel")) -------------------------------------------------------------------------------- /dynamic-programming/fibonacci-dp.py: -------------------------------------------------------------------------------- 1 | # reference: https://medium.com/@davidguandev/introduction-to-dynamic-programming-with-examples-bc04dca3ccee 2 | 3 | memo = {} 4 | def fibonacci_dp(n): 5 | if n in memo: 6 | return memo[n] 7 | if n <= 2: 8 | f = 1 9 | else: 10 | f = fibonacci_dp(n-1) + fibonacci_dp(n-2) 11 | memo[n] = f 12 | return f 13 | -------------------------------------------------------------------------------- /dynamic-programming/graph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/dynamic-programming/graph.jpg -------------------------------------------------------------------------------- /dynamic-programming/important_problems.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 1 https://leetcode.com/problems/maximum-height-by-stacking-cuboids/submissions/ 3 | 2. https://leetcode.com/contest/weekly-contest-219/problems/stone-game-vii/ 4 | 5 | Longest Common Subsequence 6 | 1. https://leetcode.com/contest/weekly-contest-223/problems/minimize-hamming-distance-after-swap-operations/ 7 | ''' -------------------------------------------------------------------------------- /dynamic-programming/longest_common_subsequence.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem Statement and Explanation: Narasimha Karumanchi's Algorithm Design Patterns 3 | ''' 4 | 5 | def LCS_length(X, Y): 6 | m = len(X) 7 | n = len(Y) 8 | memo = dict() 9 | LCS_length = dp(m-1, n-1, X, Y, memo) 10 | return LCS_length 11 | 12 | def dp(i, j, X, Y, memo): 13 | if i < 0 or j < 0: 14 | return 0 15 | 16 | if (i, j) in memo: 17 | return memo[(i, j)] 18 | 19 | if X[i] == Y[j]: 20 | memo[(i, j)] = 1 + dp(i-1, j-1, X, Y, memo) 21 | 22 | else: 23 | memo[(i, j)] = max(dp(i-1, j, X, Y, memo), dp(i, j-1, X, Y, memo)) 24 | 25 | return memo[(i, j)] 26 | 27 | string1 = "AGGTAB" 28 | string2 = "GXTXAYB" 29 | 30 | print(LCS_length(string1, string2)) -------------------------------------------------------------------------------- /dynamic-programming/longest_contiguos_palindrome.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/dynamic-programming/longest_contiguos_palindrome.py -------------------------------------------------------------------------------- /dynamic-programming/n_choose_k.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem Statement and Explanation: Narasimha Karumanchi's Algorithm Design Patterns 3 | ''' 4 | 5 | def n_choose_k(n, k): 6 | memo = dict() 7 | return dp(n, k, memo) 8 | 9 | def dp(n, k, memo): 10 | if k==0 or n==k: 11 | return 1 12 | if (n, k) in memo: 13 | return memo[(n, k)] 14 | memo[(n, k)] = dp(n-1, k, memo) + dp(n-1, k-1, memo) 15 | return memo[(n, k)] 16 | 17 | print(n_choose_k(5, 2)) -------------------------------------------------------------------------------- /dynamic-programming/playground.py: -------------------------------------------------------------------------------- 1 | def max_continguos_sum_II(arr): 2 | n = len(arr) 3 | result = [0]*n 4 | result[0] = arr[0] 5 | result[1] = max(arr[0], arr[1]) 6 | for i in range(2, n): 7 | result[i] = max(arr[i] + result[i-2], result[i-1], arr[i]) 8 | return result[n-1] 9 | 10 | arr = [-2, 1, -3, 4,-1, 2, 1, -5, 4] 11 | print(max_continguos_sum_II(arr)) -------------------------------------------------------------------------------- /graphs/cableConnections.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem: https://leetcode.com/problems/number-of-operations-to-make-network-connected/ 3 | ''' 4 | 5 | class DisjointSet(object): 6 | def __init__(self, N): 7 | self.rank = [1]*N 8 | self.parent = [i for i in range(N)] 9 | self.num_sets = N 10 | self.existing_unions = 0 11 | 12 | def find(self, x): 13 | if self.parent[x] != x: 14 | self.parent[x] = self.find(self.parent[x]) 15 | return self.parent[x] 16 | 17 | def union(self, x, y): 18 | parentx = self.find(x) 19 | parenty = self.find(y) 20 | 21 | if parentx == parenty: 22 | self.existing_unions += 1 23 | return True 24 | 25 | if self.rank[parentx] > self.rank[parenty]: 26 | self.parent[parenty] = parentx 27 | elif self.rank[parentx] < self.rank[parenty]: 28 | self.parent[parentx] = parenty 29 | else: 30 | self.parent[parenty] = parentx 31 | self.rank[parentx] += 1 32 | 33 | self.num_sets -= 1 34 | return False 35 | 36 | class Solution: 37 | def makeConnected(self, n, connections): 38 | ''' 39 | The idea is to count the number of sets after performing all union operatons 40 | and also count reductant (already existing unions) 41 | and if n_reductant >= n_sets - 1 42 | (-1 because we are dealing here with not connected 43 | sets and hence we are removing the connected set) 44 | we return n_sets-1 else -1 45 | ''' 46 | ds = DisjointSet(n) 47 | for x, y in connections: 48 | ds.union(x, y) 49 | if ds.existing_unions >= ds.num_sets - 1: 50 | return ds.num_sets - 1 51 | return -1 -------------------------------------------------------------------------------- /graphs/cycleDetection.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem: https://leetcode.com/problems/find-eventual-safe-states/submissions/ 3 | ''' 4 | 5 | class Solution: 6 | def eventualSafeNodes(self, graph): 7 | ''' 8 | The idea is we iterate through each vertex and check if a backedge is present 9 | in that vertex. We use a recursion Stack to reset after we move to the next vertex. 10 | ''' 11 | visited = [False]*len(graph) 12 | recStack = [False]*len(graph) 13 | result = [] 14 | n= len(graph) 15 | for v in range(n): 16 | if not self.isCycle(v, graph, visited, recStack): 17 | result.append(v) 18 | return result 19 | 20 | def isCycle(self, v, graph, visited, recStack): 21 | ''' 22 | There is a cycle if the vertex has been visited previously 23 | and is also in the recursion stack 24 | ''' 25 | visited[v] = True 26 | recStack[v] = True 27 | neighbours = graph[v] 28 | for u in neighbours: 29 | if visited[u] == False: 30 | if self.isCycle(u, graph, visited, recStack): 31 | return True 32 | elif recStack[u] == True: 33 | return True 34 | recStack[v] = False 35 | return False -------------------------------------------------------------------------------- /graphs/dijkstras.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem: https://leetcode.com/problems/network-delay-time/submissions/ 3 | ''' 4 | 5 | from graph_rep import Graph 6 | 7 | def dijkstras(self, graph, source): 8 | visited = set() 9 | distance = [float('inf')] * graph.n_nodes 10 | vertices = list(range(graph.n_nodes)) 11 | 12 | # initialize source 13 | distance[source] = 0 14 | 15 | while len(vertices) > 0: 16 | # get current node 17 | # the current node is the node which has minimum distance from the source 18 | min_distance = float('inf') 19 | min_node = None 20 | for node in vertices: 21 | if node in visited: 22 | continue 23 | if distance[node] < min_distance: 24 | min_distance = distance[node] 25 | min_node = node 26 | 27 | visited.add(min_node) 28 | vertices.remove(min_node) 29 | 30 | # perform relaxation on neighbours of the current node 31 | neighbours = graph.adj_list[min_node] 32 | for v in neighbours: 33 | edge_weight = graph.adj_matrix[min_node][v] 34 | current_distance = edge_weight + min_distance 35 | if current_distance < distance[v]: 36 | distance[v] = current_distance 37 | 38 | return distance -------------------------------------------------------------------------------- /graphs/disjoint_sets_array.py: -------------------------------------------------------------------------------- 1 | class DisjointSet(object): 2 | def __init__(self, n): 3 | self.rank = [0]*n 4 | self.parent = [i for i in range(n)] 5 | 6 | def find(self, x): 7 | if self.parent[x] != x: 8 | self.parent[x] = self.find(self.parent[x]) 9 | return self.parent[x] 10 | 11 | def union(self, x, y): 12 | parentx = self.find(x) 13 | parenty = self.find(y) 14 | 15 | if parentx == parenty: 16 | return 17 | 18 | if self.rank[parentx] > self.rank[parenty]: 19 | self.parent[parenty] = parentx 20 | elif self.rank[parentx] < self.rank[parenty]: 21 | self.parent[parentx] = parenty 22 | else: 23 | self.parent[parenty] = parentx 24 | self.rank[parentx] += 1 -------------------------------------------------------------------------------- /graphs/disjoint_sets_tree.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Disjoint Set Implementation using Tree Representation and Collapse find 3 | ''' 4 | class Node(object): 5 | def __init__(self, data, parent=None, rank=0): 6 | self.data = data 7 | self.parent = parent 8 | self.rank = rank 9 | 10 | class DisjointSet(object): 11 | def __init__(self): 12 | self.map = dict() 13 | self.num_sets = 0 14 | 15 | def make_set(self, data): 16 | node = Node(data) 17 | node.parent = node 18 | self.map[data] = node 19 | self.num_sets += 1 20 | 21 | def find_set_util(self, node): 22 | parent = node.parent 23 | if parent == node: 24 | return parent 25 | 26 | node.parent = self.find_set_util(node.parent) # path compression or collapse find 27 | return node.parent 28 | 29 | def find_set(self, data): 30 | node = self.map[data] 31 | return self.find_set_util(node) 32 | 33 | def union(self, data1, data2): 34 | node1 = self.map[data1] 35 | node2 = self.map[data2] 36 | 37 | # get representative elements 38 | parent1 = self.find_set_util(node1) 39 | parent2 = self.find_set_util(node2) 40 | 41 | if parent1 == parent2: 42 | return 43 | 44 | if parent1.rank == parent2.rank: 45 | parent2.parent = parent1 46 | parent1.rank += 1 47 | elif parent1.rank > parent2.rank: 48 | parent2.parent = parent1 49 | else: 50 | parent1.parent = parent2 51 | 52 | self.num_sets -= 1 -------------------------------------------------------------------------------- /graphs/friendsCircles.py: -------------------------------------------------------------------------------- 1 | from disjoint_sets_tree import DisjointSet 2 | 3 | class Solution(object): 4 | ''' 5 | The idea is we find union of friends where there is a 1 in the matrix 6 | and at the end after finding all unions, 7 | the number of friends circles is the number of sets 8 | ''' 9 | def findCircleNum(self, M): 10 | """ 11 | :type M: List[List[int]] 12 | :rtype: int 13 | """ 14 | ds = DisjointSet() 15 | 16 | n = len(M) 17 | 18 | # make set for each vertex 19 | for i in range(n): 20 | ds.make_set(i) 21 | 22 | for i in range(n): 23 | for j in range(n): 24 | if M[i][j] == 1: 25 | ds.union(i, j) 26 | 27 | return ds.num_sets -------------------------------------------------------------------------------- /graphs/graph_rep.py: -------------------------------------------------------------------------------- 1 | class Graph: 2 | ''' 3 | Representation of a graph using adjaceny matrix and adjaceny list. 4 | This assumes vertices are numbered from 0-N 5 | ''' 6 | def __init__(self, N): 7 | self.n_nodes = N 8 | self.adj_matrix = [[0 for i in range(N)] for j in range(N)] 9 | self.adj_list = {key: [] for key in range(N)} 10 | 11 | def connect(self, u, v, w): 12 | ''' 13 | u - source 14 | v - destination 15 | w - weight 16 | ''' 17 | self.adj_matrix[u][v] = w 18 | 19 | def make_neighbours(self, u, v): 20 | self.adj_list[u].append(v) -------------------------------------------------------------------------------- /graphs/informAllEmployees.py: -------------------------------------------------------------------------------- 1 | ''' 2 | problem: https://leetcode.com/problems/time-needed-to-inform-all-employees/ 3 | ''' 4 | 5 | class Solution: 6 | def numOfMinutes(self, n, headID, manager, informTime): 7 | ''' 8 | This problem is very similar to 'get max path sum in a tree' 9 | ''' 10 | # get manager-employee mapping 11 | employees = [[] for i in range(n)] 12 | for idx, m in enumerate(manager): 13 | if m == -1: 14 | continue 15 | employees[m].append(idx) 16 | return self.DFS(headID, employees, informTime) 17 | 18 | def DFS(self, rootID, employees, informTime): 19 | return max([self.DFS(employeeID, employees, informTime) for employeeID in employees[rootID]] or [0]) + informTime[rootID] -------------------------------------------------------------------------------- /graphs/isGraphBipartite.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Explanation: https://leetcode.com/problems/is-graph-bipartite/discuss/115493/Python-7-lines-DFS-graph-coloring-w-graph-and-Explanation 3 | Problem: https://leetcode.com/problems/is-graph-bipartite/ 4 | ''' 5 | from collections import deque 6 | 7 | class Solution: 8 | def isBipartite(self, graph): 9 | visited = {} 10 | for i in range(len(graph)): 11 | if i in visited: 12 | continue 13 | # can do with BFS or DFS 14 | if self.DFS(i, graph, visited, 1) == False: 15 | return False 16 | return True 17 | 18 | 19 | def DFS(self, i, graph, visited, current_color): 20 | if i in visited: 21 | if visited[i] != current_color: 22 | return False 23 | return True 24 | visited[i] = current_color 25 | neighbours = graph[i] 26 | for j in neighbours: 27 | if self.DFS(j, graph, visited, -current_color) == False: 28 | return False 29 | return True 30 | 31 | def BFS(self, i, graph, visited): 32 | queue = deque() 33 | start_node = (i, 1) 34 | queue.append(start_node) 35 | while len(queue) > 0: 36 | node, color = queue.popleft() 37 | if node in visited: 38 | if visited[node] != color: 39 | return False 40 | continue 41 | visited[node] = color 42 | neighbours = graph[node] 43 | for v in neighbours: 44 | queue.append((v, -color)) 45 | return True -------------------------------------------------------------------------------- /graphs/numberOfIslands.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numIslands(self, grid): 3 | labels = [[0 for i in range(len(grid[0]))] for j in range(len(grid))] 4 | cluster_id = 0 5 | rows = len(grid) 6 | columns = len(grid[0]) 7 | for i in range(rows): 8 | for j in range(columns): 9 | if grid[i][j] == '0' or labels[i][j] != 0: 10 | continue 11 | cluster_id += 1 12 | labels[i][j] = cluster_id 13 | self.DFS(i, j, grid, labels, cluster_id) 14 | return cluster_id 15 | 16 | 17 | def DFS(self, x, y, grid, labels, cluster_id): 18 | if grid[x][y] == '0': 19 | return 20 | neighbours = self.get_neighbours(x, y, grid) 21 | for i, j in neighbours: 22 | if labels[i][j] != 0 or grid[i][j] == '0': 23 | continue 24 | labels[i][j] = cluster_id 25 | self.DFS(i, j, grid, labels, cluster_id) 26 | 27 | def get_neighbours(self, x, y, grid): 28 | rows = len(grid) 29 | columns = len(grid[0]) 30 | neighbours = [] 31 | for i, j in [[x+1, y], [x-1, y], [x, y+1], [x, y-1]]: 32 | if i < 0 or j < 0 or i >= rows or j >= columns: 33 | continue 34 | neighbours.append([i, j]) 35 | return neighbours -------------------------------------------------------------------------------- /graphs/numberOfIslands_disjointSet.py: -------------------------------------------------------------------------------- 1 | from disjoint_sets_tree import DisjointSet 2 | 3 | class Solution(object): 4 | def NumberOfIslands(self, M): 5 | """ 6 | :type M: List[List[int]] 7 | :rtype: int 8 | """ 9 | ds = DisjointSet() 10 | 11 | n = len(M) 12 | m = len(M[0]) 13 | 14 | # make set for each vertex 15 | for i in range(n): 16 | for j in range(m): 17 | # print(i, j, i*m+j) 18 | if M[i][j] == 1: 19 | ds.make_set(i*m + j) 20 | 21 | for i in range(n): 22 | for j in range(m): 23 | if M[i][j] == 0: 24 | continue 25 | if i+1 < n and M[i+1][j] == 1: 26 | ds.union(i*m + j, (i+1)*m + j) 27 | if i-1 >= 0 and M[i-1][j] == 1: 28 | ds.union(i*m + j, (i-1)*m + j) 29 | if j+1 < m and M[i][j+1] == 1: 30 | ds.union(i*m + j, i*m + j+1) 31 | if j-1 >=0 and M[i][j-1] == 1: 32 | ds.union(i*m + j, i*m + j-1) 33 | 34 | return ds.num_sets -------------------------------------------------------------------------------- /graphs/product_of_length_of_cycles.py: -------------------------------------------------------------------------------- 1 | ''' 2 | https://www.geeksforgeeks.org/product-of-lengths-of-all-cycles-in-an-undirected-graph/ 3 | ''' 4 | 5 | def DFS(current_node, parent_node, adj_list, parent_list, mark_list, rec_stack, visited): 6 | global cycle_number 7 | 8 | rec_stack[current_node] = True 9 | parent_list[current_node] = parent_node 10 | 11 | neighbours = adj_list[current_node] 12 | for v in neighbours: 13 | if parent_node == v: 14 | continue 15 | if visited[v] is True: 16 | continue 17 | if rec_stack[v] is True: # cycle found 18 | # backtrack and mark all of them with a unique number 19 | 20 | # if it's already marked, return 21 | if mark_list[v] != 0: 22 | return 23 | 24 | cycle_number += 1 25 | while current_node != v: 26 | mark_list[current_node] = cycle_number 27 | current_node = parent_list[current_node] 28 | if current_node is None: 29 | return 30 | mark_list[v] = cycle_number 31 | return 32 | 33 | DFS(v, current_node, adj_list, parent_list, mark_list, rec_stack, visited) 34 | 35 | rec_stack[current_node] = False 36 | visited[current_node] = True 37 | 38 | # add the edges to the graph 39 | def addEdge(u, v): 40 | 41 | adj_list[u].append(v) 42 | adj_list[v].append(u) 43 | 44 | n_nodes = 13 45 | adj_list = {i: [] for i in range(1, n_nodes+1)} 46 | 47 | # add edges 48 | addEdge(1, 2) 49 | addEdge(2, 3) 50 | addEdge(3, 4) 51 | addEdge(4, 6) 52 | addEdge(4, 7) 53 | addEdge(5, 6) 54 | addEdge(3, 5) 55 | addEdge(7, 8) 56 | addEdge(6, 10) 57 | addEdge(5, 9) 58 | addEdge(10, 11) 59 | addEdge(11, 12) 60 | addEdge(11, 13) 61 | addEdge(12, 13) 62 | 63 | parent_list = [None] * (n_nodes + 1) 64 | mark_list = [0] * (n_nodes + 1) 65 | rec_stack = [None] * (n_nodes + 1) 66 | visited = [None] * (n_nodes + 1) 67 | 68 | cycle_number = 0 69 | 70 | DFS(1, 0, adj_list, parent_list, mark_list, rec_stack, visited) 71 | -------------------------------------------------------------------------------- /graphs/removeStones.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem: https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/submissions/ 3 | ''' 4 | class DisjointSet(object): 5 | ''' 6 | The idea is we perform union of a two stones if they are in the same row or same column 7 | and then return sum(rank-1 for rank in sets) 8 | Note that here we are concerned about ranks and update accordingly 9 | ''' 10 | def __init__(self, N): 11 | self.rank = [1]*N 12 | self.parent = [i for i in range(N)] 13 | 14 | def find(self, x): 15 | if self.parent[x] != x: 16 | self.parent[x] = self.find(self.parent[x]) 17 | return self.parent[x] 18 | 19 | def union(self, x, y): 20 | parentx = self.find(x) 21 | parenty = self.find(y) 22 | 23 | if parentx == parenty: 24 | return 25 | 26 | if self.rank[parentx] >= self.rank[parenty]: 27 | self.parent[parenty] = parentx 28 | self.rank[parentx] += self.rank[parenty] 29 | self.rank[parenty] = 0 30 | else: 31 | self.parent[parentx] = parenty 32 | self.rank[parenty] += self.rank[parentx] 33 | self.rank[parentx] = 0 34 | 35 | 36 | class Solution: 37 | def removeStones(self, stones): 38 | N = len(stones) 39 | ds = DisjointSet(N) 40 | 41 | for i in range(N): 42 | for j in range(N): 43 | if stones[i][0] == stones[j][0] or stones[i][1] == stones[j][1]: 44 | ds.union(i, j) 45 | 46 | maxMoves = 0 47 | for i in range(N): 48 | if ds.rank[i] > 1: 49 | maxMoves += ds.rank[i]-1 # -1 because we cannot remove all stones 50 | 51 | return maxMoves 52 | -------------------------------------------------------------------------------- /graphs/rottenOranges.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem: https://leetcode.com/problems/rotting-oranges/submissions/ 3 | ''' 4 | 5 | class Solution: 6 | def orangesRotting(self, grid): 7 | ''' 8 | The trick is to use levels and children while doing BFS 9 | as done in BFS in trees 10 | ''' 11 | rows = len(grid) 12 | columns = len(grid[0]) 13 | queue = [] 14 | visited = set() 15 | total_oranges = 0 16 | for i in range(rows): 17 | for j in range(columns): 18 | if grid[i][j] > 0: 19 | total_oranges += 1 20 | if grid[i][j] == 2: 21 | visited.add((i, j)) 22 | queue.append([i, j]) 23 | minute = 0 24 | while len(queue) > 0: 25 | children = [] 26 | for level in queue: 27 | x, y = level 28 | neighbours = self.get_neighbours(x, y, grid) 29 | for i, j in neighbours: 30 | if grid[i][j] == 0 or (i, j) in visited: 31 | continue 32 | children.append([i, j]) 33 | visited.add((i, j)) 34 | queue = children 35 | if len(queue) > 0: 36 | minute += 1 37 | unvisited_oranges = total_oranges - len(visited) 38 | if unvisited_oranges > 0: 39 | return -1 40 | return minute 41 | 42 | def get_neighbours(self, x, y, grid): 43 | rows = len(grid) 44 | columns = len(grid[0]) 45 | neighbours = [] 46 | for i, j in [[x+1, y], [x-1, y], [x, y+1], [x, y-1]]: 47 | if i < 0 or j < 0 or i>=rows or j>=columns: 48 | continue 49 | neighbours.append([i, j]) 50 | return neighbours -------------------------------------------------------------------------------- /graphs/shortestPathBinaryMatrix.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | class Solution: 4 | def shortestPathBinaryMatrix(self, grid): 5 | ''' 6 | Using BFS to find shortest distance between start and end vertex 7 | ''' 8 | N = len(grid) 9 | if grid[0][0] == 1 or grid[N-1][N-1] == 1: 10 | return -1 11 | queue = deque() 12 | result = [[0 for i in range(N)] for j in range(N)] 13 | queue.append((0, 0)) 14 | result[0][0] = 1 15 | while len(queue) > 0: 16 | x, y = queue.popleft() 17 | neighbours = self.get_neighbours(x, y, grid) 18 | for i, j in neighbours: 19 | if grid[i][j] == 1 or result[i][j]!=0: 20 | continue 21 | result[i][j] = result[x][y] + 1 22 | queue.append((i, j)) 23 | if result[N-1][N-1] == 0: 24 | return -1 25 | return result[N-1][N-1] 26 | 27 | def get_neighbours(self, x, y, grid): 28 | N = len(grid) 29 | neighbours = [] 30 | for i, j in [[x+1, y], [x-1, y], [x, y+1], [x, y-1], [x+1, y+1], [x+1, y-1], [x-1, y+1], [x-1, y-1]]: 31 | if i < 0 or j < 0 or i>=N or j>=N: 32 | continue 33 | neighbours.append([i, j]) 34 | return neighbours -------------------------------------------------------------------------------- /graphs/topological_sort.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Description and Algorithm here: https://www.interviewcake.com/concept/python3/topological-sort 3 | ''' 4 | 5 | graph = {1: [2, 3], 2: [4, 5], 3: [4], 4: [5], 5: [None]} 6 | 7 | def topological_sort(graph): 8 | # construct a dictionary mapping nodes to their indegrees 9 | indegrees = {node:0 for node in graph} 10 | for node in graph: 11 | for neighbour in graph[node]: 12 | indegrees[neighbour] = indegrees.get(neighbour, 0) + 1 13 | 14 | # track nodes with no incoming edges 15 | nodes_with_no_incoming_edges = [] 16 | for node in indegrees: 17 | if indegrees.get(node) == 0: 18 | nodes_with_no_incoming_edges.append(node) 19 | 20 | topological_ordering = [] 21 | 22 | # until we have exhausted all the nodes 23 | while len(nodes_with_no_incoming_edges) > 0: 24 | 25 | # add the nodes with no incoming edges to the topological ordering 26 | node = nodes_with_no_incoming_edges.pop() 27 | topological_ordering.append(node) 28 | 29 | # after adding the node to the topological ordering, 30 | # we remove the node and it's edges 31 | # to do so, we reduce the indegree of the node's neighbours by 1 32 | for neighbour in graph[node]: 33 | if neighbour == None: 34 | continue 35 | indegrees[neighbour] -= 1 36 | if indegrees[neighbour] == 0: 37 | nodes_with_no_incoming_edges.append(neighbour) 38 | 39 | return topological_ordering 40 | 41 | print(topological_sort(graph)) -------------------------------------------------------------------------------- /graphs/updateMatrix.py: -------------------------------------------------------------------------------- 1 | ''' 2 | problem: https://leetcode.com/problems/01-matrix/submissions/ 3 | ''' 4 | 5 | from collections import deque 6 | 7 | class Solution: 8 | def updateMatrix(self, matrix): 9 | ''' 10 | This is a multi source BFS problem 11 | explanation: https://leetcode.com/problems/01-matrix/discuss/101080/Python-Simple-with-Explanation 12 | (down in the comments) 13 | ''' 14 | queue = deque() 15 | rows = len(matrix) 16 | columns = len(matrix[0]) 17 | result = [[-1 for j in range(columns)] for i in range(rows)] 18 | for i in range(rows): 19 | for j in range(columns): 20 | if matrix[i][j] == 0: 21 | queue.append((i, j)) 22 | result[i][j] = 0 23 | 24 | while len(queue) > 0: 25 | x, y = queue.popleft() 26 | for i, j in self.get_neighbours(x, y, matrix): 27 | if result[i][j] == -1: 28 | result[i][j] = result[x][y] + 1 29 | queue.append((i, j)) 30 | return result 31 | 32 | def get_neighbours(self, x, y, matrix): 33 | rows = len(matrix) 34 | columns = len(matrix[0]) 35 | neighbours = [] 36 | for i, j in [[x+1, y], [x-1, y], [x, y+1], [x, y-1]]: 37 | if i<0 or j<0 or i>=rows or j>=columns: 38 | continue 39 | neighbours.append([i, j]) 40 | return neighbours -------------------------------------------------------------------------------- /hash table/hashSet.py: -------------------------------------------------------------------------------- 1 | class MyHashSet: 2 | 3 | def __init__(self): 4 | """ 5 | Initialize your data structure here. 6 | """ 7 | n_buckets = 1000 8 | self.buckets = [None] * n_buckets 9 | 10 | def hashFunction(self, val): 11 | return val % len(self.buckets) 12 | 13 | def add(self, key: int) -> None: 14 | # a hashset should have only unique elements 15 | hashVal = self.hashFunction(key) 16 | if self.buckets[hashVal]: 17 | if key not in self.buckets[hashVal]: 18 | self.buckets[hashVal].append(key) 19 | else: 20 | self.buckets[hashVal] = [key] 21 | 22 | def remove(self, key: int) -> None: 23 | hashVal = self.hashFunction(key) 24 | if self.buckets[hashVal]: 25 | if key in self.buckets[hashVal]: 26 | self.buckets[hashVal].remove(key) 27 | 28 | def contains(self, key: int) -> bool: 29 | """ 30 | Returns true if this set contains the specified element 31 | """ 32 | hashVal = self.hashFunction(key) 33 | if self.buckets[hashVal]: 34 | if key in self.buckets[hashVal]: 35 | return True 36 | return False 37 | 38 | 39 | # Your MyHashSet object will be instantiated and called as such: 40 | # obj = MyHashSet() 41 | # obj.add(key) 42 | # obj.remove(key) 43 | # param_3 = obj.contains(key) -------------------------------------------------------------------------------- /hash table/important_problems.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Similar to two sum 3 | 1. https://leetcode.com/problems/pairs-of-songs-with-total-durations-divisible-by-60/ 4 | ''' -------------------------------------------------------------------------------- /hash table/playground.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/hash table/playground.py -------------------------------------------------------------------------------- /linked lists/playground.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/linked lists/playground.py -------------------------------------------------------------------------------- /linked lists/queues with linked lists.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data=None): 3 | self.data = data 4 | self.next = None 5 | 6 | class Queue: 7 | def __init__(self): 8 | self.front = self.back = Node() 9 | 10 | def isEmpty(self): 11 | return self.front == self.back 12 | 13 | def EnQueue(self, val): 14 | emptyNode = Node() 15 | self.back.data = val 16 | self.back.next = emptyNode 17 | if self.front.data == None: 18 | self.front = self.back 19 | self.back = emptyNode 20 | 21 | def DeQueue(self): 22 | if self.isEmpty(): 23 | return False 24 | frontVal = self.front.data 25 | self.front = self.front.next 26 | return frontVal 27 | 28 | def traverse(self, startNode, endNode): 29 | while startNode != None: 30 | print(startNode.data) 31 | if startNode == endNode: 32 | return "Traverse Completed" 33 | startNode = startNode.next 34 | return "Traverse Completed" 35 | 36 | def __str__(self): 37 | return self.traverse(self.front, self.back) 38 | 39 | queue = Queue() 40 | queue.EnQueue(12) 41 | queue.EnQueue(15) 42 | queue.EnQueue(34) 43 | queue.DeQueue() 44 | print(queue) -------------------------------------------------------------------------------- /linked lists/stacks with linked lists.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data = None): 3 | self.data = data 4 | self.next = None 5 | 6 | class Stack: 7 | def __init__(self): 8 | self.top = self.bottom = Node() 9 | 10 | def isEmpty(self): 11 | return self.top == self.bottom 12 | 13 | def pop(self): 14 | if self.isEmpty(): 15 | return False 16 | topElement = self.top.data 17 | self.top = self.top.next 18 | return topElement 19 | 20 | def push(self, val): 21 | emptyNode = Node(val) 22 | emptyNode.next = self.top 23 | self.top = emptyNode 24 | 25 | def traverse(self, startNode, endNode): 26 | while startNode != None: 27 | print(startNode.data) 28 | if startNode == endNode: 29 | break 30 | startNode = startNode.next 31 | return "Traversal complete" 32 | 33 | def __str__(self): 34 | return self.traverse(self.top, self.bottom) 35 | 36 | stack = Stack() 37 | stack.push(12) 38 | stack.push(7) 39 | stack.pop() 40 | print(stack) 41 | 42 | -------------------------------------------------------------------------------- /recursion and backtracking/backtracking/combinations.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. 3 | ''' 4 | 5 | def combinations(n, k): 6 | result = [] 7 | combinations_helper(n, k, 1, result, []) 8 | return result 9 | 10 | def combinations_helper(n, k, index, result, combination): 11 | if len(combination) == k: 12 | result.append(combination) 13 | return 14 | for i in range(index, n+1): 15 | combinations_helper(n, k, i+1, result, combination + [i]) 16 | 17 | print(combinations(4, 2)) -------------------------------------------------------------------------------- /recursion and backtracking/backtracking/combinations_with_repetitions.py: -------------------------------------------------------------------------------- 1 | def countVowelStrings(n): 2 | result = [] 3 | vowelsList = ["a", "e", "i", "o", "u"] 4 | countVowelStringsHelper(n, "", 0, result, vowelsList) 5 | return result 6 | 7 | def countVowelStringsHelper(n, current, index, result, vowelsList): 8 | if len(current) == n: 9 | result.append(current) 10 | return 11 | for idx in range(index, len(vowelsList)): 12 | vowel = vowelsList[idx] 13 | countVowelStringsHelper(n, current + vowel, idx, result, vowelsList) 14 | 15 | print(countVowelStrings(2)) -------------------------------------------------------------------------------- /recursion and backtracking/backtracking/important_problems.py: -------------------------------------------------------------------------------- 1 | ''' 2 | similar to K equal sum partition 3 | 1. https://leetcode.com/contest/weekly-contest-223/problems/find-minimum-time-to-finish-all-jobs/ 4 | 5 | Permutations and Combinations 6 | 1. https://leetcode.com/contest/weekly-contest-224/problems/tuple-with-same-product/ 7 | 8 | Similar to N Queens 9 | 1. https://leetcode.com/contest/weekly-contest-224/problems/cat-and-mouse-ii/ 10 | ''' -------------------------------------------------------------------------------- /recursion and backtracking/backtracking/kth_smallest_instructions.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Question: https://leetcode.com/problems/kth-smallest-instructions/ 3 | ''' 4 | 5 | class Solution: 6 | def kthSmallestPath(self, destination, k): 7 | result = [] 8 | maxRow = destination[0] 9 | maxColumn = destination[1] 10 | self.globalCount = 0 11 | return self.kthSmallestPathHelper(destination, "", 0, 0, maxRow, maxColumn, result, k) 12 | 13 | def kthSmallestPathHelper(self, destination, currentPath, currentRow, currentColumn, maxRow, maxColumn, result, k): 14 | if currentRow == destination[0] and currentColumn == destination[1]: 15 | self.globalCount += 1 16 | # print(currentPath, self.globalCount) 17 | if self.globalCount == k: 18 | return currentPath 19 | else: 20 | return None 21 | if currentRow > maxRow: 22 | return None 23 | if currentColumn > maxColumn: 24 | return None 25 | is_result_one = self.kthSmallestPathHelper(destination, currentPath + "H", currentRow, currentColumn+1, maxRow, maxColumn, result, k) 26 | is_result_two = self.kthSmallestPathHelper(destination, currentPath + "V", currentRow+1, currentColumn, maxRow, maxColumn, result, k) 27 | 28 | return is_result_one or is_result_two -------------------------------------------------------------------------------- /recursion and backtracking/backtracking/maze.py: -------------------------------------------------------------------------------- 1 | def solve_maze(current_position, maze, visited, end_position): 2 | x, y = current_position 3 | if current_position == end_position: 4 | maze[x][y] = 10 5 | return True 6 | maze[x][y] = 10 7 | neighbours = [[x+1, y], [x, y+1], [x-1, y], [x, y-1]] 8 | for v in neighbours: 9 | i, j = v 10 | if 0 <= i < len(maze) and 0 <=j < len(maze[0]) and maze[i][j] != 0: 11 | if tuple(v) in visited: 12 | continue 13 | visited.add(tuple(v)) 14 | if solve_maze(v, maze, visited, end_position): 15 | return True 16 | maze[i][j] = 1 17 | return False 18 | 19 | Maze = [[ 1 , 0 , 1, 0 , 0], 20 | [ 1 , 1 , 0, 1 , 0], 21 | [ 0 , 1 , 0, 1 , 0], 22 | [ 0 , 1 , 0, 0 , 0], 23 | [ 1 , 1 , 1, 1 , 1]] 24 | 25 | visited = set([0, 0]) 26 | solve_maze([0, 0], Maze, visited, [4, 4]) 27 | print(Maze) -------------------------------------------------------------------------------- /recursion and backtracking/backtracking/maze2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Rat in a Maze 3 | ''' 4 | 5 | def solve_maze(current_position, maze, end_position, solution): 6 | size = len(maze) 7 | x, y = current_position 8 | if current_position == end_position: 9 | solution[x][y] = 1 10 | return True 11 | 12 | neighbours = [[x+1, y], [x-1, y], [x, y+1], [x, y-1]] 13 | for v in neighbours: 14 | i, j = v 15 | if 0 <= i < size and 0 <=j < size and solution[i][j] == 0: 16 | if maze[i][j] == 0: 17 | continue 18 | solution[i][j] = 1 19 | if solve_maze(v, maze, end_position, solution): 20 | return True 21 | solution[i][j] = 0 22 | return False 23 | 24 | 25 | Maze = [[ 1 , 0 , 1, 0 , 0], 26 | [ 1 , 1 , 0, 1 , 0], 27 | [ 0 , 1 , 0, 1 , 0], 28 | [ 0 , 1 , 0, 0 , 0], 29 | [ 1 , 1 , 1, 1 , 1]] 30 | 31 | solution = [[0 for x in range(len(Maze[0]))] for y in range(len(Maze))] 32 | 33 | solve_maze([0, 0], Maze, [4, 4], solution) 34 | solution[0][0] = 1 35 | 36 | print(solution) -------------------------------------------------------------------------------- /recursion and backtracking/backtracking/mini-sudoku.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Reference: https://brilliant.org/wiki/recursive-backtracking/#:~:text=Recursive%20Backtracking,(one%20of%20the%20leaves). 3 | ''' 4 | 5 | def is_valid_line(arr): 6 | ''' 7 | Function to check if a row or column is valid 8 | ''' 9 | visited = set() 10 | for element in arr: 11 | if element == 0: 12 | continue 13 | elif element in visited: 14 | return False 15 | visited.add(element) 16 | return True 17 | 18 | def is_valid_board(board): 19 | ''' 20 | Function to check if a sudoku board is valid 21 | ''' 22 | N = len(board) 23 | for i in range(N): 24 | row = board[i] 25 | column = [board[x][i] for x in range(N)] 26 | if not is_valid_line(row) or not is_valid_line(column): 27 | return False 28 | return True 29 | 30 | def solve_sudoku(board, N): 31 | size = len(board) 32 | if N == 0: 33 | return is_valid_board(board) 34 | for i in range(size): 35 | for j in range(size): 36 | cell = board[i][j] 37 | if cell != 0: 38 | continue 39 | for num in range(1, size+1): 40 | board[i][j] = num 41 | if solve_sudoku(board, N-1) and is_valid_board(board): 42 | return True 43 | board[i][j] = 0 44 | return False 45 | 46 | Board = [ [ 0 , 0 , 0 ], 47 | [ 1 , 0 , 0 ], 48 | [ 0 , 3 , 1 ] ] 49 | 50 | solve_sudoku(Board, 6) 51 | 52 | print(Board) 53 | -------------------------------------------------------------------------------- /recursion and backtracking/backtracking/playground.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wingedrasengan927/Data-Structures-and-Algorithms-in-Python/8357dc23efa07a08f37bc9c96aebeeb804660deb/recursion and backtracking/backtracking/playground.py -------------------------------------------------------------------------------- /recursion and backtracking/backtracking/string_permutation.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Reference: https://brilliant.org/wiki/recursive-backtracking/ 3 | Given a string of length N, find all its permutations 4 | ''' 5 | 6 | def permuation(stringList, i): 7 | if i == len(stringList): 8 | print("".join(stringList)) 9 | for k in range(i, len(stringList)): 10 | stringList[k], stringList[i] = stringList[i], stringList[k] # swap i, k 11 | permuation(stringList, i+1) 12 | stringList[k], stringList[i] = stringList[i], stringList[k] # backtracking 13 | 14 | permuation(['b', 'o', 'a', 't'], 0) -------------------------------------------------------------------------------- /recursion and backtracking/recursion/kth_grammar.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 1. First row Starts with 0 3 | 2. children of 0 are 0 and 1 in the order 4 | 3. children of 1 are 1 and 0 in the order 5 | 4. find Kth index of Nth row 6 | 7 | example 8 | --------- 9 | N=4, k=5 10 | 0 11 | 01 12 | 0110 13 | 01101001 14 | 15 | ans: 5 (1 indexed) 16 | 17 | Solution 18 | --------- 19 | 1. One observation is that if K is odd, then the node is left child of it's parent 20 | 2. Else if K is even, then the node is right child of it's parent 21 | 3. based on this, we find the parent recursively and return the node accordingly 22 | ''' 23 | class Solution: 24 | def kthGrammar(self, N: int, K: int) -> int: 25 | if N==1: 26 | return 0 27 | 28 | if K%2 == 0: 29 | if self.kthGrammar(N-1, K/2) == 0: 30 | return 1 31 | else: 32 | return 0 33 | else: 34 | if self.kthGrammar(N-1, (K+1)/2) == 0: 35 | return 0 36 | else: 37 | return 1 -------------------------------------------------------------------------------- /recursion and backtracking/recursion/kth_odd_natural_number.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Find the kth odd natural number. 1 being the first natural number 3 | ans: 2*(k-1) + 1 4 | ''' 5 | 6 | def kth_odd_num(k): 7 | if k == 1: 8 | return 1 9 | return kth_odd_num(k-1) + 2 10 | 11 | print(kth_odd_num(8)) -------------------------------------------------------------------------------- /recursion and backtracking/recursion/kth_power_of_2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given k, n find n^k 3 | ''' 4 | 5 | memo = dict() 6 | def kth_power_of_n(n, k): 7 | if k == 0: 8 | return 1 9 | if k == 1: 10 | return n 11 | if k < 0: 12 | k = abs(k) 13 | n = 1/n 14 | 15 | if (n, k) in memo: 16 | return memo[(n, k)] 17 | 18 | if k % 2 == 0: 19 | memo[(n, k)] = kth_power_of_n(n, k//2) * kth_power_of_n(n, k//2) 20 | else: 21 | memo[(n, k)] = kth_power_of_n(n, k//2)*kth_power_of_n(n, (k//2) + 1) 22 | return memo[(n, k)] 23 | 24 | print(kth_power_of_n(2, 5)) -------------------------------------------------------------------------------- /recursion and backtracking/recursion/largestRectangleArea.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def largestRectangleArea(self, heights): 3 | ''' 4 | The idea is that we create a stack and store indices of bars in 5 | ascending order, and as soon as we encounter a bar that breaks the 6 | pattern i.e it's height is less than the top most bar in the stack, 7 | we calculate the areas of all the bars in the stack and compare it to the max value 8 | and continue forming the pattern in the stack 9 | ''' 10 | heights.append(0) 11 | stack = [-1] 12 | area = 0 13 | for i in range(len(heights)): 14 | while heights[i] < heights[stack[-1]]: 15 | # calculate bars area 16 | h = heights[stack.pop()] 17 | w = i - stack[-1] - 1 18 | area = max(area, h*w) 19 | stack.append(i) 20 | return area -------------------------------------------------------------------------------- /recursion and backtracking/recursion/merge_two_linked_lists.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def mergeTwoLists(self, l1, l2): 3 | if not l1: 4 | return l2 5 | if not l2: 6 | return l1 7 | 8 | if l1.val <= l2.val: 9 | current_node = l1 10 | l1 = l1.next 11 | else: 12 | current_node = l2 13 | l2 = l2.next 14 | 15 | current_node.next = self.mergeTwoLists(l1, l2) 16 | 17 | return current_node -------------------------------------------------------------------------------- /recursion and backtracking/recursion/n_combinations.py: -------------------------------------------------------------------------------- 1 | ''' 2 | choose m elements from n elements 3 | nCm = n!/(n-m)! * m! 4 | 5 | The problem with using the formula is n! becomes too big and it might not fit the integer representation 6 | 7 | The other way is to use recursion. The recurrence relation would be: 8 | nCm = n-1Cm-1 + n-1Cm 9 | ''' 10 | memo = dict() 11 | def n_choose_m(n, m): 12 | if n == m or m == 0: 13 | return 1 14 | if (n, m) in memo: 15 | return memo[(n, m)] 16 | memo[(n, m)] = n_choose_m(n-1, m-1) + n_choose_m(n-1, m) 17 | return memo[(n, m)] 18 | 19 | print(n_choose_m(52, 5)) -------------------------------------------------------------------------------- /recursion and backtracking/recursion/pascals_triangle_nth_row.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def getRow(self, rowIndex): 3 | i = rowIndex 4 | result = [] 5 | memo = dict() 6 | for j in range(i+1): 7 | result.append(self.get_element(i, j, memo)) 8 | return result 9 | 10 | def get_element(self, i, j, memo): # i - rowIndex, j - columnIned 11 | if i == 0 or j == 0 or i==j: 12 | return 1 13 | if (i, j) in memo: 14 | return memo[(i, j)] 15 | 16 | # F(i, j) = F(i-1, j-1) + F(i-1, j) # recurrence relation 17 | memo[(i, j)] = self.get_element(i-1, j-1, memo) + self.get_element(i-1, j, memo) 18 | return memo[(i, j)] -------------------------------------------------------------------------------- /recursion and backtracking/recursion/pow_x_n.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def myPow(self, x, n): 3 | if n == 0: 4 | return 1 5 | elif n == 1: 6 | return x 7 | elif n < 0: 8 | return 1/self.myPow(x, -n) 9 | 10 | if n % 2 == 0: 11 | return self.myPow(x*x, n//2) 12 | else: 13 | return x*self.myPow(x, n-1) 14 | 15 | def myPowMemo(self, x, n): 16 | memo = {} 17 | def myPowHelper(x, n): 18 | # base case 19 | if n == 0: 20 | return 1 21 | elif n == 1: 22 | return x 23 | 24 | elif n < 0: 25 | x = (1/x) 26 | n = abs(n) 27 | 28 | # memoization 29 | if (x, n) in memo: 30 | return memo[(x, n)] 31 | 32 | if n % 2 == 0: 33 | memo[(x, n)] = myPowHelper(x, n//2) * myPowHelper(x, n//2) 34 | else: 35 | memo[(x, n)] = myPowHelper(x, n//2) * myPowHelper(x, n - n//2) 36 | return memo[(x, n)] 37 | return myPowHelper(x, n) -------------------------------------------------------------------------------- /recursion and backtracking/recursion/reverse_linked_list.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | class ListNode: 3 | def __init__(self, val=0, next=None): 4 | self.val = val 5 | self.next = next 6 | 7 | class Solution: 8 | def reverseList(self, head): 9 | return self.reverseListHelper(None, head) 10 | 11 | def reverseListHelper(self, previous_node, current_node): 12 | if not current_node: 13 | return previous_node 14 | next_node = current_node.next 15 | current_node.next = previous_node 16 | previous_node = current_node 17 | current_node = next_node 18 | 19 | return self.reverseListHelper(previous_node, current_node) -------------------------------------------------------------------------------- /recursion and backtracking/recursion/search_in_2D_matrix_I.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Search for a given target in a sorted 2D matrix 3 | 4 | 0 1 2 3 4 5 | 5 6 7 8 9 6 | 10 11 12 13 15 7 | ''' 8 | 9 | 10 | def get_coordinate(index, n_cols): 11 | rowIdx = index // n_cols 12 | colIdx = index % n_cols 13 | return rowIdx, colIdx 14 | 15 | def binarySearchHelper(matrix, target, startIdx, endIdx, n_cols): 16 | if startIdx > endIdx: 17 | return None 18 | midIdx = (startIdx + endIdx) // 2 19 | rowIdx, colIdx = get_coordinate(midIdx, n_cols) 20 | element = matrix[rowIdx][colIdx] 21 | if element > target: 22 | return binarySearchHelper(matrix, target, startIdx, midIdx-1, n_cols) 23 | elif element < target: 24 | return binarySearchHelper(matrix, target, midIdx+1, endIdx, n_cols) 25 | else: 26 | return (rowIdx, colIdx) 27 | 28 | def binarySearch(matrix, target): 29 | ''' 30 | Time Complexity - O(log(mn)) 31 | ''' 32 | n_cols = len(matrix[0]) 33 | n_rows = len(matrix) 34 | startIdx = 0 35 | endIdx = n_cols*n_rows - 1 36 | return binarySearchHelper(matrix, target, startIdx, endIdx, n_cols) 37 | 38 | matrix = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]] 39 | print(binarySearch(matrix, 6)) -------------------------------------------------------------------------------- /recursion and backtracking/recursion/search_in_BST.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, val=0, left=None, right=None): 4 | self.val = val 5 | self.left = left 6 | self.right = right 7 | 8 | 9 | class Solution: 10 | def searchBST(self, root, val): 11 | if not root: 12 | return None 13 | 14 | if root.val == val: 15 | return root 16 | 17 | is_left_subtree = self.searchBST(root.left, val) 18 | is_right_subtree = self.searchBST(root.right, val) 19 | 20 | return is_left_subtree or is_right_subtree -------------------------------------------------------------------------------- /recursion and backtracking/recursion/search_in_a_2D_matrix_II.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Search in a 2D matrix 3 | where rows are sorted and columns are sorted 4 | but matrix is not sorted 5 | 6 | 1 4 7 11 7 | 8 9 10 20 8 | 11 12 17 30 9 | ''' 10 | 11 | def search2DHelper(matrix, target, rowIdx, colIdx, n_cols): 12 | if rowIdx < 0 or colIdx >= n_cols: 13 | return None 14 | element = matrix[rowIdx][colIdx] 15 | if element > target: 16 | return search2DHelper(matrix, target, rowIdx-1, colIdx, n_cols) 17 | elif element < target: 18 | return search2DHelper(matrix, target, rowIdx, colIdx+1,n_cols) 19 | else: 20 | return (rowIdx, colIdx) 21 | 22 | def search2D(matrix, target): 23 | ''' 24 | Time Complexity - O(m + n) 25 | ''' 26 | n_rows = len(matrix) 27 | n_cols = len(matrix[0]) 28 | rowIdx = n_rows - 1 29 | colIdx = 0 30 | return search2DHelper(matrix, target, rowIdx, colIdx, n_cols) 31 | 32 | matrix = [[1, 4, 7, 11], [8, 9, 10, 20], [11, 12, 17, 30]] 33 | target = 7 34 | print(search2D(matrix, target)) -------------------------------------------------------------------------------- /recursion and backtracking/recursion/swap_nodes_in_pairs_linked_list.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | class ListNode: 3 | def __init__(self, val=0, next=None): 4 | self.val = val 5 | self.next = next 6 | 7 | class Solution: 8 | def swapPairs(self, head): 9 | if not head: 10 | return None 11 | 12 | if not head.next: 13 | return head 14 | 15 | next_pair_head = head.next.next 16 | temp = head 17 | head = head.next 18 | head.next = temp 19 | 20 | head.next.next = self.swapPairs(next_pair_head) 21 | 22 | return head -------------------------------------------------------------------------------- /recursion and backtracking/recursion/tower_of_hanoi.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Problem Statement: https://www.hackerearth.com/practice/algorithms/dynamic-programming/introduction-to-dynamic-programming-1/practice-problems/algorithm/tower-of-hanoi-17/ 3 | Basically we have three towers: source, destination, auxillary 4 | Our aim is to move all the disks from source to destination with some rules: 5 | 1. You can only move one disk at a time 6 | 2. Larger disk cannot be placed on top of a smaller disk 7 | 8 | Solution 9 | -------- 10 | 1. Move the top n-1 disks from source to auxillary tower 11 | 2. Move the nth disk from source to destination 12 | 3. Move the n-1 disks from auxillary to destination tower 13 | ''' 14 | 15 | def move_tower(ndisks, fromTower, toTower, withTower): 16 | # time complexity - 2^n - 1 17 | if ndisks >= 1: 18 | move_tower(ndisks-1, fromTower, withTower, toTower) 19 | move_disk(fromTower, toTower) 20 | move_tower(ndisks-1, withTower, toTower, fromTower) 21 | 22 | 23 | def move_disk(fromTower, toTower): 24 | print("Moving disk from {} tower to {} tower".format(fromTower, toTower)) 25 | 26 | move_tower(3, "source", "destination", "auxillary") --------------------------------------------------------------------------------