Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lasagna] revision to existing concept exercise #780

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
4 changes: 1 addition & 3 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@
"name": "Lasagna",
"uuid": "39ebdd04-4f84-4817-bf9d-f1f9e066c283",
"concepts": [
"functions",
"integer-introduction",
"comments"
"basics"
],
"prerequisites": [],
"status": "wip"
Expand Down
18 changes: 13 additions & 5 deletions exercises/concept/lasagna/.docs/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@

In this exercise you're going to write some code to help you cook a brilliant lasagna from your favorite cooking book.

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

## 1. Calculate the preparation time in minutes
## 1.

Define the `expected_bake_time` constant that returns how many minutes the lasagna should bake in the oven. According to the cooking book, lasagna needs to be in the oven for a total of 60 minutes.

```julia-repl
julia> expected_bake_time
60
```

## 2. Calculate the preparation time in minutes

Define the `preptime` 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.
colinleach marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -13,17 +22,16 @@ julia> preptime(4)
8
```

## 2. Calculate the remaining oven time in minutes
## 3. Calculate the remaining oven time in minutes

According to the cooking book, lasagna needs to be in the oven for a total of 60 minutes.
Define the `remaining_time` function that takes the actual minutes the lasagna has been in the oven as a parameter and returns how many minutes the lasagna still has to remain in the oven.

```julia-repl
julia> remaining_time(50)
10
```

## 3. Calculate the total working time in minutes
## 4. Calculate the total working time in minutes

Define the `total_working_time` function that takes two arguments: the first argument is the number of layers you added to the lasagna, and the second parameter is the number of minutes the lasagna has been in the oven.
colinleach marked this conversation as resolved.
Show resolved Hide resolved
The function should return how many minutes in total 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.
Expand Down
156 changes: 77 additions & 79 deletions exercises/concept/lasagna/.docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,122 +3,120 @@
The entire Julia track will require you to treat your solution like small libraries, i.e. you need to define functions, types etc. which will then be run against a test suite.
For that reason, we will introduce named functions as the very first concept.

## Functions
Julia is a dynamic, strongly-typed programming langauge.
The programming style is mainly functional, though with more flexibility than in languages such as Haskell.

### Defining functions
## Comments
colinleach marked this conversation as resolved.
Show resolved Hide resolved

There are two common ways to define a named function in Julia:
Two options are possible in Julia:
- Single-line comments start with `#`
- Multi-line comments start with `#=` and end with `=#`. Nesting is allowed.

1. Using the `function` keyword

```julia
function muladd(x, y, z)
return x * y + z
end
```
```julia
# This is a single-line comment

2. Using the "assignment form"
x = 3 # This is an inline comment

```julia
muladd(x, y, z) = x * y + z
```
#=
Multi-line comments can be used for longer explanations.

This is most commonly used for one-line function definitions or mathematical functions, where the function body is a single expression.
They are especially useful to comment out blocks of code during debugging.
=#
```

### Invoking functions
## Variables and assignment

Invoking a function is done by specifying its name and passing arguments for each of the function's parameters:
To create a variable, just assign a value to it:
colinleach marked this conversation as resolved.
Show resolved Hide resolved

```julia
# invoking a function
muladd(10, 5, 1)
```julia-repl
julia> myvar = 42 # an integer
42

# and of course you can invoke a function within the body of another function:
square_plus_one(x) = muladd(x, x, 1)
julia> name = "Maria" # strings are surrounded by double-quotes ""
"Maria"
```

## Integers and Arithmetic operations
Types are an important subject in Julia, but for now it is best to ignore them them.
colinleach marked this conversation as resolved.
Show resolved Hide resolved
The compiler will infer a suitable type for any expression you use.

Integer literals in Julia are represented in the usual way.
Underscores may be used as a digit separator.
## Constants

```julia-repl
julia> 1
1

julia> -1234
-1234
Global variables, created outside any function, are:
Copy link
Member

Choose a reason for hiding this comment

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

The heading refers to constants but we don't mention constant until later. Perhaps we should introduce what a constant is first and then discuss global variables to show why a constant is preferred.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Extensively reworded. What do you think of the new attempt?

- Allowed.
- Sometimes necessary.
- Usually discouraged (only within `*.jl` files; the REPL operates differently).

julia> 1_234_567_890
1234567890
```
If a value needs to be available throughout the program, but is not expected to change, use a constant instead.

### Arithmetic operations
Prefacing the assignemt with the `const` keyword allows the compiler to generate more efficient code.
colinleach marked this conversation as resolved.
Show resolved Hide resolved

The standard prefix and infix operations are available: `+`, `-`, `*`, `%`.
Accidentally trying to change the `const` value will give a warning:

```julia-repl
julia> +16
16
julia> const answer = 42
42

julia> -16
-16

julia> 16 + 6
22
julia> answer = 24
WARNING: redefinition of constant Main.answer. This may fail, cause incorrect answers, or produce other errors.
24
```

julia> 16 - 6
10
## Arithmetic operators

julia> 16 * 6
96
These mostly work conventionally:
Copy link
Member

Choose a reason for hiding this comment

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

This sentence is a little confusing since we don’t detail what’s not conventional in the next few lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll update tomorrow.


julia> 16 % 6
4
```julia
2 + 3 # 5 (addition)
2 - 3 # -1 (subtraction)
2 * 3 # 6 (mutlplication)
colinleach marked this conversation as resolved.
Show resolved Hide resolved
8 / 2 # 4.0 (division with floating-point result)
8 % 3 # 2 (remainder)
```

#### Division
## Functions

Dividing two numbers with the `/` operator will result in a floating point value.
To perform integer division
There are two common ways to define a named function in Julia:

- use the `div(x, y)` function, or
- use the `÷` operator (Julia source code is unicode-aware)
1. Using the `function` keyword

```julia-repl
julia> 16 / 6
2.6666666666666665
```julia
function muladd(x, y, z)
x * y + z
end
```

julia> div(16, 6)
2
Indentation by 4 spaces is conventional for readability, but the compiler ignores this.
The `end` keyword is essential: more like Ruby than like Python.
colinleach marked this conversation as resolved.
Show resolved Hide resolved

julia> 16 ÷ 6
2
```
Note that we could have written `return x * y + z`.
However, Julia functions always return the last expression evaluated, so the `return` keyword is optional.
Many programmers prefer to include it to make their intentions more explicit.

~~~~exercism/note
It's natural to use Unicode symbols in Julia source files, typically in mathematical expressions.
When using the Julia REPL, or in other Julia editing environments, the division symbol can be entered by typing `\div` followed by the `Tab` key.
More details can be found in the manual at [Unicode Input][unicode].
2. Using the "assignment form"

[unicode]: https://docs.julialang.org/en/v1/manual/unicode-input/#Unicode-Input
~~~~
```julia
muladd(x, y, z) = x * y + z
```

## Comments
This is most commonly used for one-line function definitions or mathematical functions, where the function body is a single expression.
colinleach marked this conversation as resolved.
Show resolved Hide resolved
A `return` keyword is *never* used in the assignment form.

Julia supports two kinds of comments.
Single line comments are preceded by `#` and multiline comments are inserted between `#=` and `=#`.
The two forms are equivalent, and are used in exactly the same way, so choose whichever is more readable.

Invoking a function is done by specifying its name and passing arguments for each of the function's parameters:

```julia
add(1, 3) # returns 4
# invoking a function
muladd(10, 5, 1)

#= Some random code that's no longer needed but not deleted
sub(x, y) = x - y
mulsub(x, y, z) = sub(mul(x, y), z)
=#
# and of course you can invoke a function within the body of another function:
square_plus_one(x) = muladd(x, x, 1)
```

## Types
## Naming conventions

Like many languages, Julia requires that names (of variables, functions, and many other things) start with a letter, followed by any combination of letters, digits and underscores.

By convention, variable, constant, and function names are *lowercase*, with underscores kept to a reasonable minimum.
Copy link
Member

Choose a reason for hiding this comment

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

Maybe some examples just to be clear?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This feels like something that should be expanded in basics/about.md. I'm trying hard to keep introduction.md to the bare minimum needed to solve the exercise. Jeremy has said repeatedly that this is what he wants, and I'm not disagreeing.


Depending on which other programming languages you know, you may expect parameters, variables or return values to have explicit type annotations.
For now, assume that Julia will infer the types automagically and don't worry about them, we will get to the specifics of the type system in later exercises.
However, Julia uses Unicode throughout, so "letter" is interpreted quite flexibly: not just *English* letters.
colinleach marked this conversation as resolved.
Show resolved Hide resolved
16 changes: 1 addition & 15 deletions exercises/concept/lasagna/.docs/introduction.md.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,5 @@
The entire Julia track will require you to treat your solution like small libraries, i.e. you need to define functions, types etc. which will then be run against a test suite.
For that reason, we will introduce named functions as the very first concept.

## Functions
%{concept:basics}

%{concept:functions}

## Integers and Arithmetic operations

%{concept:integer-introduction}

## Comments

%{concept:comments}

## Types

Depending on which other programming languages you know, you may expect parameters, variables or return values to have explicit type annotations.
For now, assume that Julia will infer the types automagically and don't worry about them, we will get to the specifics of the type system in later exercises.
3 changes: 2 additions & 1 deletion exercises/concept/lasagna/.meta/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
],
"contributors": [
"ErikSchierboom",
"glennj"
"glennj",
"colinleach"
],
"files": {
"solution": [
Expand Down
9 changes: 5 additions & 4 deletions exercises/concept/lasagna/.meta/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Goal

The goal of this exercise is to teach the student the fundamentals of the Concept of functions in Julia, so that they are able to understand the basic structure of Exercism exercises.
The goal of this exercise is to teach the student the fundamentals of the `basics` Concept in Julia, so that they are able to understand the basic structure of Exercism exercises.

## Learning objectives

Expand All @@ -11,17 +11,18 @@ The goal of this exercise is to teach the student the fundamentals of the Concep
- Know how to call a function.
- Know about implicit `return`s.
- Know how to define an integer.
- Know how to define a global constant.
- Know how to use mathematical operators on integers.

## Out of scope

Everthing beyond the simplest minimum for the first exercise of a novice.
colinleach marked this conversation as resolved.
Show resolved Hide resolved

## Concepts

The Concepts this exercise practices are:

- `functions`: Defining a function with one or more positional arguments that returns something. Bare minimum to be able to understand the basic structure of Exercism exercises.
- `integers-introduction`: Present integer literals and basic arithmetic operations.
- `comments`
- `basics`: Defining a constant. Defining a function with one or more positional arguments that returns something. Bare minimum to be able to understand the basic structure of Exercism exercises.

## Prerequisites

Expand Down
6 changes: 5 additions & 1 deletion exercises/concept/lasagna/.meta/exemplar.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
expected_bake_time = 60
colinleach marked this conversation as resolved.
Show resolved Hide resolved

preptime(layers) = 2 * layers
remaining_time(current_time) = 60 - current_time

remaining_time(current_time) = expected_bake_time - current_time

total_working_time(layers, current_time) = preptime(layers) + current_time
3 changes: 3 additions & 0 deletions exercises/concept/lasagna/lasagna.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Define the `expected_bake_time` constant`

# Define the `preptime(layers)` function.

# Define the `remaining_time(time_in_oven)` function.

# Define the `total_working_time(layers, time_in_oven)` function.

6 changes: 6 additions & 0 deletions exercises/concept/lasagna/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ using Test
include("lasagna.jl")

@testset verbose = true "tests" begin

@testset "expected bake time" begin
@test expected_bake_time == 60
@test isconst(typeof(expected_bake_time), expected_bake_time) == true
end

@testset "preparation time" begin
@test preptime(2) == 4
@test preptime(3) == 6
Expand Down
Loading