Generating code exercise#
One of the most powerful features of an AI coding assistant is its ability to generate repetitive or boilerplate code under your direction. This capability allows you to write code much faster while staying focused on higher-level concepts rather than getting stuck on syntax or implementation details. It is especially useful for tasks involving new libraries or functions that you may not be familiar with.
Generating Snippets#
When generating code snippets, you can provide a description of the functionality you need, and the AI will generate the corresponding code. You should specify the programming language and any relevant libraries or frameworks you want to use if you are using a chatbot that is not integrated in your editor. You can also specify the structure of the code, such as whether you want it in a function.
In the code snippet below, ask the LLM to generate a function that normalizes a list of numbers. Ask the LLM to use the same function signature as the one you provided, and to use the numpy
library for calculations. You can copy and paste the template below along your prompt to have the LLM fill it in.
Tip
If using an integrated LLM like GitHub Copilot, you can generate code inline and avoid the hassle of copying and pasting. You also then do not have to specify context regarding the programming langauge or surrounding comments. It learns from context around the place where you call the inline code generation, so you can start typing a function signature or a comment, and it will suggest the code that follows! No extra prompting is needed as the function signature is often enough for simple tasks, and otherwise writing comments helps guide the integrated assistant.
import numpy as np
def normalize_array(arr):
# YOUR CODE HERE
pass
To verify the correctness of the generated code, run the cell below which runs a few tests. If the tests pass, it indicates that the code is functioning as expected.
arr1 = np.array([0, 5, 10])
assert np.allclose(normalize_array(arr1), np.array([0.0, 0.5, 1.0]))
arr2 = np.array([3, 3, 3])
assert np.allclose(normalize_array(arr2), np.array([np.nan, np.nan, np.nan])) or np.all(normalize_array(arr2) == 0)
arr3 = np.array([-1, 0, 1])
assert np.allclose(normalize_array(arr3), np.array([0.0, 0.5, 1.0]))
Generating Longer Code#
For more complex tasks, the LLMs may struggle to generate the entire code in one go. Even if it does, it often fails to adhere to specific constraints or requirements you want if you ask for too much at once. In such cases, it is better to break down the task into smaller parts and generate code incrementally.
You can start by asking the LLM to generate a function or a class and then iteratively refine it by asking for additional features or modifications. This way, you can guide the LLM to produce code that meets your specific needs. You can treat this as an interactive process or a conversation, where you provide feedback and ask for changes until the code meets your requirements.
The example allows you to practice with a more complex task. Use LLMs to solve it!
Goal: Write a function find_local_maxima(matrix, threshold)
that takes a 2D NumPy array and returns the coordinates of all elements that are strict local maxima (greater than all 8 neighbors), and have a value greater than the threshold. The function should return a list of (row, col)
index tuples.
Although the example could still possibly be solved in one go, it is better to break it down into smaller parts. You can start by asking the LLM to generate a function that checks if a given element is a local maximum, and then build on that to find all local maxima in the matrix.
Tip
To use code autocompletion features effectively, you can start typing a comment in the function that does the small subtask you want it to implement. For example, you can write # Check if the element is a local maximum
and then let the LLM complete the snippet. This way, it will generate the complex task bit by bit, ensuring that it matches your expectations.
# YOUR CODE HERE
Similarly to the previous example, you can run the cell below to test the correctness of the generated code. If the tests pass, it indicates that the code is functioning as expected.
import numpy as np
# Simple peak in center
mat1 = np.array([
[1, 2, 3],
[4, 9, 6],
[7, 8, 5]
])
assert find_local_maxima(mat1, threshold=5) == [(1, 1)]
# No values above threshold
mat2 = np.array([
[1, 2, 1],
[2, 3, 2],
[1, 2, 1]
])
assert find_local_maxima(mat2, threshold=10) == []
# Multiple peaks
mat3 = np.array([
[1, 9, 1, 9, 1],
[1, 1, 1, 1, 1],
[1, 9, 1, 9, 1]
])
expected = [(0, 1), (0, 3), (2, 1), (2, 3)]
assert sorted(find_local_maxima(mat3, threshold=5)) == expected
# Border elements shouldn't be considered (by design)
mat4 = np.array([
[10, 10, 10],
[10, 5, 10],
[10, 10, 10]
])
# 5 is not greater than neighbors
assert find_local_maxima(mat4, threshold=0) == []