<jupyter_start><jupyter_text>Exercise 1Write a function `create_n_random_particles` that takes the arguments `n` (number of particles), `m` (mass of every particle) and a domain within to generate a random number (as in the class above).It should create an array with `n` elements and `dtype=particle_dtype` and then return that array.For each particle, the mass should be initialized to the value of `m` and the potential `phi` initialized to zero.For the `x` component of a given particle `p`, you might do something like```pythonp['x'] = domain * numpy.random.random()```<jupyter_code>@njit
def create_n_random_particles(n, m, domain=1):
    '''
    Creates `n` particles with mass `m` with random coordinates
    between 0 and `domain`
    '''
    parts = numpy.zeros((n), dtype=particle_dtype)
    for p in parts:
        p.m = m
        p.phi = 0
        p.x = domain*numpy.random.random()
        p.y = domain*numpy.random.random()
        p.y = domain*numpy.random.random()
    #your code here

    return parts<jupyter_output><empty_output><jupyter_text>Test it out!<jupyter_code>time_taken = %timeit -o parts = create_n_random_particles(1000, .001, 1)<jupyter_output>10000 loops, best of 3: 63.5 µs per loop<jupyter_text>Exercise 2 Write a JITted function `distance` to calculate the distance between two particles of dtype `particle_dtype` Here's the `distance` method from the `Particle` class as a reference:```pythondef distance(self, other):        return ((self.x - other.x)**2 +                 (self.y - other.y)**2 +                 (self.z - other.z)**2)**.5```<jupyter_code>@njit
def distance(part1, part2):
    '''calculate the distance between two particles'''
    return ((part1['x'] - part2['x'])**2 +
            (part1['x'] - part2['x'])**2 +
            (part1['x'] - part2['x'])**2 )**.5
    # your code here<jupyter_output><empty_output><jupyter_text>Try it out!<jupyter_code>distance(parts[0], parts[1])<jupyter_output><empty_output><jupyter_text>Exercise 3 Modify the original `direct_sum` function (copied below for reference) to instead work a NumPy array of particles.  Loop over each element in the array and calculate its total potential.```pythondef direct_sum(particles):    """    Calculate the potential at each particle    using direct summation method.    Arguments:        particles: the list of particles    """    for i, target in enumerate(particles):        for source in (particles[:i] + particles[i+1:]):            r = target.distance(source)            target.phi += source.m / r```<jupyter_code>@njit
def direct_sum(particles):
    # take it away
    for i,target in enumerate(particles):
        for j,source in enumerate(particles):
            if i!=j:
                r = distance(target,source)
                target['phi'] += source['m']/r
numba_time = %timeit -o direct_sum(parts)<jupyter_output>The slowest run took 10.02 times longer than the fastest. This could mean that an intermediate result is being cached.
1 loop, best of 3: 33.1 ms per loop
{'fraction_non_alphanumeric': 0.1182331451345068, 'fraction_numerical': 0.01693789438724676, 'mean_word_length': 3.6338461538461537, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, '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': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '246908', 'license': 'MIT', 'n_tokens_mistral': 960, 'n_tokens_neox': 916, 'n_words': 307, 'path': 'numba_tutorial_scipy2016-master/notebooks/exercises/04.Direct.Summation.Exercises.ipynb', 'repo_name': 'sunny2309/scipy_conf_notebooks', 'size': '3011'}