ChatGPT 3.5 and AI in general is not yet a programmer, even if some are expecting it to become one. I have tried it several times myself, and my conclusion is the same as many other professional programmers: it is not yet ready to replace a human programmer.
You must have domain competence to be able to correct the erroneous answers received from chatGPT. It is the same if you ask chatGPT to write some code. But if used as the Devil’s Advocate, it might help you improve the robustness and maintainability of the code as described in this article.
I’ve observed some use of it as an advanced search tool, and I’ve used it when I’ve forgotten how to write an if-statement in an obscure language such as JavaScript. However, in this article I will show how I used it to find two errors in my Python code. Note that this is not the full conversation I had with chatGPT and it is only a subset of my implementation – hopefully just enough to show a possible interesting use of chatGPT already, as an aid in finding test cases.
def adapt_recipe(txt, x):
adapted_recipte = ""
for line in txt.splitlines():
number = line.split(" ")[0]
if number.isdecimal() :
volume = round(float(number)*float(x),1)
adapted_recipte = adapted_recipte + str(volume) + " " + line.replace(number,"") + "\n"
else:
adapted_recipte = adapted_recipte + line
return adapted_recipte
def adapt_recipe(txt, x):
adapted_recipe = ""
for line in txt.splitlines():
parts = line.split(None, 1) # Split the line into number and the rest of the line
if len(parts) == 2:
number, rest_of_line = parts
try:
number = float(number)
volume = round(number * x, 1)
adapted_recipe += f"{volume} {rest_of_line}\n"
except ValueError:
# Handle cases where the number cannot be converted to a float
adapted_recipe += line + "\n"
else:
# If the line doesn't contain a number, just append it as is
adapted_recipe += line + "\n"
return adapted_recipe
Improvements and explanations:
- I split each line into two parts: the number and the rest of the line using “split(None, 1)” to better handle variations in formatting.
- I added error handling with a “try-except block” to catch cases where the number can’t be converted to a float. This ensures that lines without valid numbers won’t cause the function to fail.
- The code now handles lines without numbers by directly appending them without modification.
- I used an f-string to make the string concatenation more concise and readable.
# Test cases
test_recipe = """
1 cup flour
2.5 tbsp sugar
Salt to taste
Eggs - 2
"""
# Test case 1: Adapt the recipe to 3 times its size (integer)
result = adapt_recipe(test_recipe, 3)
print(result)
# Test case 2: Adapt the recipe to half its size (float)
result = adapt_recipe(test_recipe, 0.5)
print(result)
# Test case 3: No scaling, the recipe remains the same
result = adapt_recipe(test_recipe, 1)
print(result)
The second example gave more help than the above one. This was the requirements
Ingredients in food recipes can be represented by a class Ingredient, which collects together information about them: the name, the unit used, and the amount of calories per unit. Define this class so that the frittata recipe can be defined as a list of tuples of amounts and Ingredient objects, as in the screen dump to the right above. Notice that the missing amount is represented as None. Also define a function calories(ingrs), which computes the total amount of calories in a recipe and works in the way shown to the right below. If the amount is None, that ingredient is just ignored.
def calories(ingre):
total_calories = 0
for ingredient in ingre:
if str(ingredient[0]).isdecimal():
total_calories = total_calories + ingredient[1].amount_of_calories * ingredient[0]
print ("Total calories: ", total_calories)
class Ingredient:
def __init__(self, name, unit, amount_of_calories):
self.name = name
self.unit = unit
self.amount_of_calories = amount_of_calories
def __init__(self, name, unit, amount_of_calories):
self.name = name
self.unit = unit
self.amount_of_calories = amount_of_calories
def calories(ingre):
total_calories = 0
for ingredient in ingre:
if ingredient[0] is not None and str(ingredient[0]).isdecimal():
total_calories += ingredient[1].amount_of_calories * ingredient[0]
return total_calories
# Test cases
if __name__ == "__main__":
# Create Ingredient objects
egg = Ingredient("Egg", "unit", 68)
cheese = Ingredient("Cheese", "gram", 110)
bacon = Ingredient("Bacon", "strip", 42)
# Define a frittata recipe
frittata_recipe = [
(2, egg),
(None, cheese), # Test None as the amount
(3, bacon),
]
# Calculate calories in the frittata recipe
total_calories = calories(frittata_recipe)
print("Total calories in the frittata recipe:", total_calories) # Expected output: 2 * 68 + 3 * 42 = 282
Improvements and suggestions:
- In the “calories” function, I’ve added a check for “ingredient[0] is not None” to ignore ingredients with “None” as their amount.
- I’ve removed the “print” statement from the “calories” function since it’s generally better to return the value and let the caller decide whether to print or use the result.
- I’ve added test cases to demonstrate how the code works, including a case where one ingredient has “None” as the amount.
- Ensure that the “amount_of_calories” is a numeric value (integer or float) when creating Ingredient objects. It’s a good practice to validate inputs to your class.
- Make sure to define the ingredients and the frittata recipe as needed for your application.
# Test Case 1: Empty recipe
empty_recipe = []
assert calories(empty_recipe) == 0
# Test Case 2: Recipe with a single ingredient
single_ingredient_recipe = [(2, Ingredient('carrot', 'g', 41))]
assert calories(single_ingredient_recipe) == 2 * 41
# Test Case 3: Recipe with multiple ingredients and one ingredient having None as amount
mixed_recipe = [
(3, Ingredient('chicken breast', 'oz', 46)),
(None, Ingredient('sugar', 'g', 387)), # Ignored due to None
(2, Ingredient('broccoli', 'g', 34)),
(1.5, Ingredient('milk', 'cup', 103)),
]
assert calories(mixed_recipe) == 3 * 46 + 2 * 34 + 1.5 * 103
# Test Case 4: Recipe with all ingredients having None as amount (should result in 0 calories)
no_amount_recipe = [
(None, Ingredient('flour', 'g', 364)),
(None, Ingredient('sugar', 'g', 387)),
(None, Ingredient('butter', 'g', 717)),
]
assert calories(no_amount_recipe) == 0
# Test Case 5: Recipe with negative amounts (should be treated as 0 calories)
negative_amount_recipe = [
(-1, Ingredient('apple', 'unit', 52)),
(2, Ingredient('banana', 'unit', 105)),
]
assert calories(negative_amount_recipe) == 2 * 105 # The negative amount is ignored
# Test Case 6: Recipe with ingredients having zero calories
zero_calories_recipe = [
(2, Ingredient('lettuce', 'g', 0)),
(3, Ingredient('tomato', 'unit', 0)),
(1, Ingredient('cucumber', 'g', 0)),
]
assert calories(zero_calories_recipe) == 0
print("All test cases passed!")
These test cases cover various scenarios, including empty recipes, different units, ignored ingredients with “None” amounts, negative amounts, and ingredients with zero calories. Each assertion checks whether the calculated total calories match the expected result. If all assertions pass, it will print “All test cases passed!” to indicate success.
def calories(ingre):
total_calories = 0
for amount, ingredient in ingre:
if amount is not None and str(amount).replace(".", "", 1).isnumeric():
total_calories += ingredient.amount_of_calories * amount
return total_calories
replace(".", "", 1)
part is used to remove the decimal point in case of floating-point numbers before checking if the string is numeric. This change ensures that the condition works correctly for both integers and floating-point numbers.
def calories(ingre):
total_calories = 0
for ingredient in ingre:
if str(ingredient[0]).replace(".", "", 1).isdecimal():
total_calories = total_calories + ingredient[1].amount_of_calories * float(ingredient[0])
else:
print(ingredient[0], ingredient[1].amount_of_calories )
return (total_calories)
Even if I found two errors in my code, it took many hours to investigate the information that chatGPT presented. You can never trust anything that chatGPT writes, as chatGPT states itself at the bottom of the tool: “chatGPT can make mistakes. Consider checking important information.” If one has a colleague that has time to review the code, it is still probably the most efficient “tool” to use.