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

[Annalyns Infiltration] concept exercise #782

Merged
merged 8 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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 @@ -45,6 +45,18 @@
],
"prerequisites": [],
"status": "wip"
},
{
"slug": "annalyns-infiltration",
"name": "annalyns-infiltration",
"uuid": "603c7f88-5250-427e-b5d8-f8306fdd9b03",
"concepts": [
"booleans"
],
"prerequisites": [
"basics"
],
"status": "wip"
}
],
"practice": [
Expand Down
1 change: 1 addition & 0 deletions exercises/concept/annalyns-infiltration/.docs/hints.md
colinleach marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Hints
65 changes: 65 additions & 0 deletions exercises/concept/annalyns-infiltration/.docs/instructions.md
colinleach marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Instructions

In this exercise, you'll be writing some logic for a video game a friend is developing. The game's main character is Annalyn, a brave girl with a fierce and loyal pet dog. Unfortunately, disaster strikes, as her best friend Nóra is kidnapped while searching for berries in the forest. Annalyn will try to find and free Nóra, optionally taking her dog with her on this quest.

Annalyn eventually finds the camp in which Nóra is imprisoned and it turns out there are two kidnappers: a mighty knight and a cunning archer.
The player is presented with some options for what to do next.
For each of the four possible options you need to write a function that tells the game whether it should show that option or not.

## 1. Check if the 'Fast Attack' option should be shown

If the knight is sleeping, then Annalyn will be able to make a quick attack into the camp before he can wake up properly and get his armour on.

Implement a function named `can_do_fast_attack` that takes a boolean value which indicates if the knight is awake. This function returns `true` if the 'Fast Attack' action is available based on the state of the character. Otherwise, returns `false`:

```julia-repl
julia> knight_awake = true;

julia> can_do_fast_attack(knight_awake)
false
```

<!-- _Note: A trailing semicolon suppresses the output of an expression in the top level of the REPL or other interactive contexts (such as Jupyter notebook cells). The output of an expression is only printed by default in the top level of the REPL, not within functions, scripts or other files._ (unlike what you may expect if you've used Matlab in the past)._ TODO: Move this to the exercise where the semicolon is first used in examples. Somehow show the Matlab hint only to students who have used Matlab before, when that'll be possible.-->

## 2. Check if the 'Spy' option should be shown

The group can be spied upon if at least one of them is awake. Otherwise, spying is a waste of time.

Implement a function named `can_spy` that takes three boolean values, indicating if the knight, archer and Nóra, respectively, are awake. The function returns `true` if the 'Spy' action is available based on the state of the characters. Otherwise, returns `false`:

```julia-repl
julia> knight_awake = false; archer_awake = true; nóra_awake = false;

julia> can_spy(knight_awake, archer_awake, nóra_awake)
true
```

## 3. Check if the 'Signal Prisoner' option should be shown

Nóra can be signalled using bird sounds if she is awake and the archer is sleeping. If the archer is awake then Nóra can't be safely signaled because the archer is also trained in bird signalling!

Implement a function named `can_signal_prisoner` that takes two boolean values, indicating if the archer and Nóra, respectively, are awake. The function returns `true` if the 'Signal Prisoner' action is available based on the state of the characters. Otherwise, returns `false`:

```julia-repl
julia> archer_awake = false; nóra_awake = true;

julia> can_signal_prisoner(archer_awake, nóra_awake)
true
```

## 4. Check if the 'Free Prisoner' option should be shown

Annalyn can try sneaking into the camp to free Nóra. This is a risky thing to do and can only succeed in one of two ways:
- If Annalyn has her pet dog with her she can rescue Nóra if the archer is asleep.
The knight is scared of the dog and the archer will not have time to get ready before Annalyn and Nóra can escape.
- If Annalyn does not have her dog then she and Nóra must be very sneaky!
Annalyn can free Nóra if they are awake and the knight and archer are both sleeping, but if Nóra is sleeping they can't be rescued: they would be startled by Annalyn's sudden appearance and wake up the knight and archer.

Implement a function named `can_free_prisoner` that takes four boolean values. The first three parameters indicate if the knight, archer and Nóra, respectively, are awake. The last parameter indicates if Annalyn's pet dog is present. The function returns `true` if the 'Free Prisoner' action is available based on the state of the characters. Otherwise, it returns `false`:

```julia-repl
julia> knight_awake = false; archer_awake = true; nóra_awake = false; dog_present = false;

julia> can_free_prisoner(knight_awake, archer_awake, nóra_awake, dog_present)
false
```
83 changes: 83 additions & 0 deletions exercises/concept/annalyns-infiltration/.docs/introduction.md
colinleach marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Introduction

## Booleans in Julia

True or false values are represented by the `Bool` type.
It contains only two values: `true` and `false`.

```julia-repl
julia> true
true

julia> false
false

julia> typeof(true)
Bool
```

## Boolean logic

Imagine we have the following Boolean expressions in Julia: `5 > x` and `x != 0`.
If `x` was 3 they would both be `true`.
We can express statements like "is x less than 5 and not equal to y?" using [Boolean operators](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Boolean-Operators): `!` (not), `&&` (and), `||` (or).

In Julia (and many other programming languages), `&&` has a [higher precedence][operator-precedence] than `||` (in the same way that `*` is applied before `+`).
This means that `true || false && true` evaluates to `true` because it is parsed as `(true || false) && true`.
It is common to include explicit brackets anyway so that the reader doesn't need to think about this.

### Logical _not_

`!` represents the logical "not" operation in Julia.
Not is also called negation.

```julia-repl
julia> !false
true

julia> false != true
true

julia> 3 != "apple"
true

julia> !(false == true)
true

julia> !(1 < 7)
false
```

### Logical _and_

`&&` (two ampersands) represents logical "and" in Julia.

```julia-repl
julia> 5 > 3
true

julia> 1 != 0
true

julia> (5 > 3) && (1 != 0)
true
```

Parentheses are optional and can make the code easier to read.

### Logical _or_

`||` (two pipe characters) represents logical "or" in Julia.

```julia-repl
julia> 5 * 5 == 25
true

julia> 2 < 1
false

julia> (5 * 5 == 25) || (2 < 1)
true
```

[operator-precedence]: https://docs.julialang.org/en/v1/manual/mathematical-operations/#Operator-Precedence-and-Associativity
7 changes: 7 additions & 0 deletions exercises/concept/annalyns-infiltration/.docs/source.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Source

This exercise is based on the ["Booleans" exercise][source] of the Javascript track, designed by [Rishi Kothari][rishiosaur] and [Derk-Jan Karrenbeld][sleepless].

[source]: https://github.com/exercism/v3/tree/1b7c392e1cc576f3948ed55216611c42fabb19b1/languages/javascript/exercises/concept/booleans
[rishiosaur]: https://github.com/rishiosaur
[sleepless]: https://github.com/SleeplessByte
23 changes: 23 additions & 0 deletions exercises/concept/annalyns-infiltration/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"blurb": "Learn about boolean expressions by implementing the quest logic for a new RPG.",
"language_versions": "≥1.0",
"files": {
"exemplar": [
".meta/exemplar.jl"
],
"test": [
"runtests.jl"
],
"solution": [
"annalyns-infiltration.jl"
]
},
"authors": [
"SaschaMann"
],
"contributors": [
"cmcaine",
"colinleach"
],
"forked_from": ["javascript/annalyns-infiltration"]
}
28 changes: 28 additions & 0 deletions exercises/concept/annalyns-infiltration/.meta/exemplar.jl
colinleach marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
can_do_fast_attack(knight_awake)

Return if a fast attack is possible.
"""
can_do_fast_attack(knight_awake) = !knight_awake

"""
can_spy(knight_awake, archer_awake, prisoner_awake)

Return if the spy action is possible.
"""
can_spy(knight_awake, archer_awake, prisoner_awake) = knight_awake || archer_awake || prisoner_awake

"""
can_signal_prisoner(archer_awake, prisoner_awake)

Return if signaling the prisoner is possible.
"""
can_signal_prisoner(archer_awake, prisoner_awake) = prisoner_awake && !archer_awake

"""
can_free_prisoner(knight_awake, archer_awake, prisoner_awake, dog_present)

Return if the prisoner can be freed.
"""
can_free_prisoner(knight_awake, archer_awake, prisoner_awake, dog_present) =
!knight_awake && !archer_awake && prisoner_awake || dog_present && !archer_awake
11 changes: 11 additions & 0 deletions exercises/concept/annalyns-infiltration/annalyns-infiltration.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function can_do_fast_attack(knight_awake)
end

function can_spy(knight_awake, archer_awake, nóra_awake)
end

function can_signal_prisoner(archer_awake, nóra_awake)
end

function can_free_prisoner(knight_awake, archer_awake, nóra_awake, dog_present)
end
71 changes: 71 additions & 0 deletions exercises/concept/annalyns-infiltration/runtests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using Test

include("annalyns-infiltration.jl")

# Julia 1.0 compat
# The function definition of eachrow is taken from Julia Base,
# released under the MIT license: https://julialang.org/license
if VERSION < v"1.1"
@eval eachrow(A) = (view(A, i, :) for i in axes(A, 1))
end

@testset verbose = true "tests" begin
@testset "fast attack" begin
@test !can_do_fast_attack(true)
@test can_do_fast_attack(false)
end

@testset "spying" begin
character_state_combinations = Bool[
0 0 0 0;
0 0 1 1;
0 1 0 1;
0 1 1 1;
1 0 0 1;
1 0 1 1;
1 1 1 1;
]

for state in eachrow(character_state_combinations)
@test can_spy(state[1:3]...) == state[4]
end
end

@testset "signaling prisoner" begin
character_state_combinations = Bool[
0 0 0;
0 1 1;
1 0 0;
1 1 0;
]

for state in eachrow(character_state_combinations)
@test can_signal_prisoner(state[1:2]...) == state[3]
end
end

@testset "freeing prisoner" begin
character_state_combinations = Bool[
0 0 0 0 0;
0 0 0 1 1;
0 0 1 0 1;
0 0 1 1 1;
0 1 0 0 0;
0 1 0 1 0;
0 1 1 0 0;
0 1 1 1 0;
1 0 0 0 0;
1 0 0 1 1;
1 0 1 0 0;
1 0 1 1 1;
1 1 0 0 0;
1 1 0 1 0;
1 1 1 0 0;
1 1 1 1 0;
]

for state in eachrow(character_state_combinations)
@test can_free_prisoner(state[1:4]...) == state[5]
end
end
end
Loading