Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,18 @@
"control_flow_loops"
]
}
],
"concept": [
{
"slug": "lasagna",
"name": "Lasagna",
"uuid": "96c38bfb-4282-4de1-8995-23704d863e0f",
"concepts": [
"basics"
],
"prerequisites": [],
"status": "wip"
}
]
},
"concepts": [
Expand Down
26 changes: 26 additions & 0 deletions exercises/concept/lasagna/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Hints

To repeat: please do not alter the `lasagna.h` file or the `#include` line.

These are designed to make this introductory exercise simpler for students.

## 1. Define the expected oven time in minutes

- This is an assignment outside of any function.
- The type is `int`.
- The value should not change, so mark it as `const`.

## 2. Calculate the remaining oven time in minutes

- C understands common arithmetic operators: `+`, `-`, `*`, `/`.
- The argument passed to the function can be accessed by name, in this case giving the elapsed time.
- Remember that C functions generally need a `return` keyword (_though `void` functions will be an exception, in later concepts_).

## 3. Calculate the preparation time in minutes

- You can call other functions and use the returned value like variables: `return 22 * myOtherCalculation();`

## 4. Calculate the elapsed time in minutes

- The output should combine the time for the preparation and the time the lasagna has already been in the oven.

53 changes: 53 additions & 0 deletions exercises/concept/lasagna/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Instructions

Lucian's girlfriend is on her way home and he hasn't cooked their anniversary dinner!

In this exercise, you're going to write some code to help Lucian cook an exquisite lasagna from his favorite cookbook.

~~~~exercism/note
The `lasagna.h` file, and the `#import` at the top of `lasagna.c` will be explained in later Concepts.

For now, please just leave these parts unchanged.
~~~~

You have four tasks, all related to the time spent cooking the lasagna.

All numerical values are of type `int`.

## 1. Define the expected oven time in minutes

Define `expected_minutes_in_oven` as a `const int`, representing how many minutes the lasagna should be in the oven.
According to the cookbook, the expected oven time is 40 minutes:

```c
expected_minutes_in_oven;
// => 40
```

## 2. Calculate the remaining oven time in minutes

Define the `remaining_minutes_in_oven(int actual_minutes_in_oven)` function that takes the actual minutes the lasagna has been in the oven as an argument and returns how many minutes the lasagna still has to remain in the oven, based on the expected oven time in minutes from the previous task.

```c
remaining_minutes_in_oven(30);
// => 10
```

## 3. Calculate the preparation time in minutes

Define the `preparation_time_in_minutes(int number_of_layers)` function that takes the number of layers you added to the lasagna as an argument and returns how many minutes you spent preparing the lasagna, assuming each layer takes you 2 minutes to prepare.

```c
preparation_time_in_minutes(2);
// => 4
```

## 4. Calculate the elapsed time in minutes

Define the `elapsed_time_in_minutes(int number_of_layers, int actual_minutes_in_oven)` function that takes two arguments: the first argument is the number of layers you added to the lasagna, and the second argument is the number of minutes the lasagna has been in the oven.
The function should return how many minutes you've worked on cooking the lasagna, which is the sum of the preparation time in minutes, and the time in minutes the lasagna has spent in the oven at the moment.

```c
elapsed_time_in_minutes(3, 20);
// => 26
```
81 changes: 81 additions & 0 deletions exercises/concept/lasagna/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Introduction

C is a statically typed language, which means that everything has a type at compile-time.
Choosing a name for a variable and setting its type is referred to as declaring a variable.

A variable is declared by explicitly specifying its type.
A variable name can start with either a letter or an underscore.

Some names cannot be used as they are reserved [for keywords][reserved-keywords] or [other identifiers][reserved-identifiers].

Setting or updating the variable is done by variable assignment.
Setting the value defines that variable.
Defining the variable is also known as initialization.

```c
int foo; // Declare an integer named var
foo = 10; // Define the variable

int bar = 15; // Both can also be done in a single statement
```

The value of a variable can be assigned and updated using the `=` simple assignment operator.
Once defined, a variable's type can never change.

```c
int foo = 10; // Assign initial value
foo = 25; // Update to new value

foo = false; // Compiler error when assigning value of a different type
```

If a value should not be changed after initialization, it can be declared as `const`.
Attempted reassignment will then be flagged as an error.

```c
const int baz = 42;

// changes not allowed!
baz = 43
// => Error
```

C is an imperative procedural language.
All computation is carried out as part a series of statements that are part of a function or multiple functions.

Each function can have zero or more parameters.
When defining a function all parameters, and the return value must be explicitly typed.

Values are returned from functions using the `return` keyword.

Functions have `external storage class` by default, meaning that it exists for the lifetime of the program and can be visible externally to the file.

To prevent this, the `static` keyword can be added to specify visibility only within the current file.

```c
static int add(int x, int y) {
return x + y;
}
```

In the above example, the variables `x` and `y` can only be used within the function that is, they have function scope.

Scope is the idea that the value associated with a name (of a program element) is only accessible within the code "area" where it is defined.

The principal code areas in C are:

- file
- function
- block (such as within loops and other constructs)

Functions are invoked by specifying the function name and passing arguments for each of the function parameters.

```c
int sum = add(1, 2);
```

C supports two types of comments.
Single line comments are preceded by `//` (since C99) and multi-line comments are inserted between `/*` and `*/`.

[reserved-keywords]: https://en.cppreference.com/w/c/keyword
[reserved-identifiers]: https://en.cppreference.com/w/c/language/identifier
25 changes: 25 additions & 0 deletions exercises/concept/lasagna/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"authors": [
"wolf99"
],
"contributors": [
"colinleach"
],
"files": {
"solution": [
"lasagna.h",
"lasagna.c"
],
"test": [
"test_lasagna.c"
],
"exemplar": [
".meta/exemplar.c"
]
},
"language_versions": "c99",
"forked_from": [
"csharp/lucians-luscious-lasagna"
],
"blurb": "Learn about the basics of C by following a lasagna recipe."
}
28 changes: 28 additions & 0 deletions exercises/concept/lasagna/.meta/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Design

## Learning objectives

- Know what a variable is
- Know how to declare and initialize a variable
- Know how to update a variable
- Know how to declare a constant
- Know how to define a function
- Know how to call a function
- Know how to return a value from a function
- Know how to use mathematical operators on integers
- Know how to define single- and multiline comments

## Out of scope

- Memory and performance characteristics
- Optional parameters
- Organizing code in different files
- Organizing code with header files

## Concepts

- `basics`

## Prerequisites

There are no prerequisites.
20 changes: 20 additions & 0 deletions exercises/concept/lasagna/.meta/exemplar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Please do not alter the include line below
#include "lasagna.h"

const int expected_minutes_in_oven = 40;

int remaining_minutes_in_oven(int actual_minutes_in_oven)
{
return expected_minutes_in_oven - actual_minutes_in_oven;
}

int preparation_time_in_minutes(int number_of_layers)
{
return number_of_layers * 2;
}

int elapsed_time_in_minutes(int number_of_layers, int actual_minutes_in_oven)
{
return preparation_time_in_minutes(number_of_layers) +
actual_minutes_in_oven;
}
10 changes: 10 additions & 0 deletions exercises/concept/lasagna/lasagna.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Please do not alter the include line below
#include "lasagna.h"

// TODO: define the expected_minutes_in_oven variable

// TODO: define the remaining_minutes_in_oven() function

// TODO: define the preparation_time_in_minutes() function

// TODO: define the elapsed_time_in_minutes() function
14 changes: 14 additions & 0 deletions exercises/concept/lasagna/lasagna.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Please do not edit this file. It will be explained in a later Concept.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about not providing this file at all and instead putting the declarations into test_lasagna.c? Alternatively, we could just #include "lasagna.c" from test_lasagna.c (that's what the C++ version does). Students would see only the lasagna.c template, so it doesn't matter which approach we use. But not having a header file would lower the chance for confusion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wolf99 @ryanplusplus What do you think?

Copy link
Member

@ryanplusplus ryanplusplus Aug 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ahans I haven't read through all the comments yet... is the intent to avoid introducing headers at this point? If so, I think this makes sense. It's weird to do either of these workarounds, but only to someone who is already familiar enough with C to be able to reason through the weirdness. I expect anyone who's just learning C to not even notice because they're focused on the basics.

I'd prefer including lasagna.c in the test file if we have to pick a path.


#ifndef LASAGNA_H
#define LASAGNA_H

extern const int expected_minutes_in_oven;

int remaining_minutes_in_oven(int actual_minutes_in_oven);

int preparation_time_in_minutes(int number_of_layers);

int elapsed_time_in_minutes(int number_of_layers, int actual_minutes_in_oven);

#endif
37 changes: 37 additions & 0 deletions exercises/concept/lasagna/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
### If you wish to use extra libraries (math.h for instance),
### add their flags here (-lm in our case) in the "LIBS" variable.

LIBS = -lm

###
CFLAGS = -std=c99
CFLAGS += -g
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -pedantic
CFLAGS += -Werror
CFLAGS += -Wmissing-declarations
CFLAGS += -DUNITY_SUPPORT_64 -DUNITY_OUTPUT_COLOR

ASANFLAGS = -fsanitize=address
ASANFLAGS += -fno-common
ASANFLAGS += -fno-omit-frame-pointer

.PHONY: test
test: tests.out
@./tests.out

.PHONY: memcheck
memcheck: ./*.c ./*.h
@echo Compiling $@
@$(CC) $(ASANFLAGS) $(CFLAGS) test-framework/unity.c ./*.c -o memcheck.out $(LIBS)
@./memcheck.out
@echo "Memory check passed"

.PHONY: clean
clean:
rm -rf *.o *.out *.out.dSYM

tests.out: ./*.c ./*.h
@echo Compiling $@
@$(CC) $(CFLAGS) test-framework/unity.c ./*.c -o tests.out $(LIBS)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure all non-empty files end with an EOL character.

Loading
Loading