<jupyter_start><jupyter_text>GridThe functions here are used often when dealing with 2D grids (like in TicTacToe).  HeadingWith the `turn_heading`, `turn_left` and `turn_right` functions an agent can turn around in a grid. In a 2D grid the orientations normally are:* North: (0,1)* South: (0,-1)* East: (1,0)* West: (-1,0)In code:<jupyter_code>orientations = [(1, 0), (0, 1), (-1, 0), (0, -1)]<jupyter_output><empty_output><jupyter_text>We signify a left turn with a +1 and a right turn with a -1.The functions `turn_left` and `turn_right` call `turn_heading`, which then turns the agent around according to the input.First the code for `turn_heading`:<jupyter_code>def turn_heading(heading, inc, headings=orientations):
    return headings[(headings.index(heading) + inc) % len(headings)]<jupyter_output><empty_output><jupyter_text>We can now use the function to turn left:<jupyter_code>print(turn_heading((0, 1), 1))<jupyter_output>(-1, 0)<jupyter_text>We were facing north and we turned left, so we are now facing west.Let's now take a look at the other two functions, which automate this process:<jupyter_code>def turn_right(heading):
    return turn_heading(heading, -1)

def turn_left(heading):
    return turn_heading(heading, +1)<jupyter_output><empty_output><jupyter_text>The first one turns the agent right, so it passes -1 to `turn_heading`, while the second one turns the agent left, so it passes +1.Let's see what happens when we are facing north and want to turn left and right:<jupyter_code>print(turn_left((0, 1)))
print(turn_right((0, 1)))<jupyter_output>(-1, 0)
(1, 0)<jupyter_text>When we turn left from north we end up facing west, while on the other hand if we turn right we end up facing east.  DistanceThe function returns the Euclidean Distance between two points in the 2D space.<jupyter_code>import math

def distance(a, b):
    """The distance between two (x, y) points."""
    return math.hypot((a[0] - b[0]), (a[1] - b[1]))<jupyter_output><empty_output><jupyter_text>For example:<jupyter_code>print(distance((1, 2), (5, 5)))<jupyter_output>5.0<jupyter_text>Distance SquaredThis function returns the square of the distance between two points.<jupyter_code>def distance_squared(a, b):
    """The square of the distance between two (x, y) points."""
    return (a[0] - b[0])**2 + (a[1] - b[1])**2<jupyter_output><empty_output><jupyter_text>For example:<jupyter_code>print(distance_squared((1, 2), (5, 5)))<jupyter_output>25<jupyter_text>Vector ClipWith this function we can make sure the values of a vector are within a given range. It takes as arguments three vectors: the vector to clip (`vector`), a vector containing the lowest values allowed (`lowest`) and a vector for the highest values (`highest`). All these vectors are of the same length. If a value `v1` in `vector` is lower than the corresponding value `v2` in `lowest`, then we set `v1` to `v2`. Similarly we "clip" the values exceeding the `highest` values.<jupyter_code>from utils import clip

def vector_clip(vector, lowest, highest):
    """Return vector, except if any element is less than the corresponding
    value of lowest or more than the corresponding value of highest, clip to
    those values."""
    return type(vector)(map(clip, vector, lowest, highest))<jupyter_output><empty_output><jupyter_text>For example:<jupyter_code>print(vector_clip((-1, 10), (0, 0), (9, 9)))<jupyter_output>(0, 9)
{'fraction_non_alphanumeric': 0.11840942562592047, 'fraction_numerical': 0.02150220913107511, 'mean_word_length': 5.8884381338742395, 'pattern_counts': {'":': 0, '<': 40, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '237550', 'license': 'MIT', 'n_tokens_mistral': 1154, 'n_tokens_neox': 1103, 'n_words': 402, 'path': 'grid.ipynb', 'repo_name': 'aldousbirchall/aima-python', 'size': '3395'}