1
1
Fork 0
exercism/jq/lasagna
Christina Sørensen 6b317e935d
feat: lasagna
Signed-off-by: Christina Sørensen <christina@cafkafk.com>
2024-12-06 15:33:35 +01:00
..
.exercism feat: lasagna 2024-12-06 15:33:35 +01:00
bats-extra.bash feat: lasagna 2024-12-06 15:33:35 +01:00
bats-jq.bash feat: lasagna 2024-12-06 15:33:35 +01:00
HELP.md feat: lasagna 2024-12-06 15:33:35 +01:00
HINTS.md feat: lasagna 2024-12-06 15:33:35 +01:00
lasagna.jq feat: lasagna 2024-12-06 15:33:35 +01:00
README.md feat: lasagna 2024-12-06 15:33:35 +01:00
test-lasagna.bats feat: lasagna 2024-12-06 15:33:35 +01:00

Lasagna

Welcome to Lasagna on Exercism's jq Track. If you need help running the tests or submitting your code, check out HELP.md. If you get stuck on the exercise, check out HINTS.md, but try and solve it without using those first :)

Introduction

Variables

Recall that a jq program is a pipeline of expressions. Variable assigmnent follows this rule: a variable assignment is an expression that looks like:

... | expr as $varname | ...

The filter outputs the input

Like the identity expression ., the variable assignment's output is the same as its input. Setting the variable's value is a side-effect.

Example, showing . after the assignment is the same as the initial input:

$ jq -c -n '42 | (. * 2) as $double | [., $double]'
[42,84]

Variable scope

The scope of the variable is "lexical" -- the variable will be in scope for the rest of the pipeline. Variables defined in functions (we'll get to functions later) are "local" to the function.

Variable names

The variable must begin with $. The rest of the variable name is an identifier: starts with a letter or underscore followed by letters, numbers or underscores.

Destructuring assignment

From the manual:

Multiple variables may be declared using a single as expression by providing a pattern that matches the structure of the input (this is known as "destructuring").

Examples:

[1, 2, 3] as [$a, $b, $c]
| [$a, $b, $c]     # => [1, 2, 3]
{"foo": "bar", "len": [10, 20]} as {foo: $f, len: [$h, $w]}
| [$f, $h, $w]     # => ["bar", 10, 20]

Matching the variable name to the object key offers a shortcut:

{"x": 4, "y": 7} as {$x, $y}
| [$x, $y]         # => [4, 7]
{"foo": "bar", "len": [10, 20]} as {$foo, $len}
| [$foo, $len]     # => ["bar", [10, 20]]
The same shortcut works in the reverse sense for _object construction_

```jq
4 as $x | 7 as $y | {$x, $y}    # => {"x":4, "y": 7}
```

Constants

As shown in the above example, variables are handy for storing constants. It's better to give constants a name rather than have "magic numbers" show up in the code.

Often variables are not needed

It is often more readable to omit variables.

Consider calculating the average of a list of numbers

[2, 4, 8, 7]
| add as $sum
| length as $len
| $sum / $len

compared to

[2, 4, 8, 7] | add / length

This highlights one of the most powerful aspects of jq: the input to a filter is provided to every sub-expression:

  • the input array [2,4,8,7] is passed to add (which sums the numbers by applying the + operator to all the elements)
  • in parallel, [2,4,8,7] is also passed to length
  • when these sub-expressions complete, their results are then divided, returning the average value of the numbers in the input array.

jq operators you'll need for the learning exercise

Alternative operator: //

The expression a // b outputs b if a is false or null, otherwise it outputs a. In the context of setting a variable, this is very handy for providing a default value:

(.input.theAnswer // 42) as $answer | ...

Arithmetic operators

  • +, -, * are the usual numeric addition, subtraction and multiplication operators.

Instructions

In this exercise you're going to write some code to help you make a brilliant lasagna from your favorite cookbook.

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

1. Define the expected oven time in minutes

Define a constant named $expected_minutes_in_oven. According to the cookbook, the expected oven time in minutes is 40:

$ jq -n -f lasagna.jq
{
  "expected_minutes_in_oven": 40,
  ...

2. Calculate the remaining oven time in minutes

This value takes the actual minutes the lasagna has been in the oven as input 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.

$ echo '{"actual_minutes_in_oven": 18}' | jq -f lasagna.jq
{
  "expected_minutes_in_oven": 40,
  "remaining_minutes_in_oven": 22,
  ...

3. Calculate the preparation time in minutes

The preparation time is how long it takes to get the lasagna ready before it is put in the over. It takes 2 minutes to prepare each layer.

$ echo '{"number_of_layers": 3}' | jq -f lasagna.jq
{
  ...
  "preparation_time": 6,
  ...

4. Calculate the total working time in minutes

Calculate how many minutes in total you've worked on cooking the lasagna. This is the sum of the preparation time in minutes and the time in minutes the lasagna has spent in the oven at the moment.

$ echo '{"actual_minutes_in_oven": 10, "number_of_layers": 2}' | jq -f lasagna.jq
{
  ...
  "total_time": 14,
  ...

Source

Created by

  • @glennj