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

elyses-analytic-enchantments concept exercise #262

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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 @@ -66,6 +66,18 @@
"prerequisites": [],
"status": "wip"
},
{
"slug": "elyses-analytic-enchantments",
"name": "Elyses Analytic Enchantments",
"uuid": "2d6c9880-efce-4e57-8abf-d702087b6082",
"concepts": [
"vector-filtering"
],
"prerequisites": [
"vectors"
],
"status": "wip"
},
{
"slug": "cars-assemble",
"name": "Cars, Assemble",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Hints
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Instructions
#
Elyse, magician-to-be, continues her training. She will be given several stacks of cards that she needs to perform her tricks.
To make things a bit easier, she only uses the cards 1 to 10.

In this exercise, use built-in methods to analyse the contents of a vector.

## 1. Determine if a card is present

Elyse wants to determine if a card is present in the stack -- in other words, if the stack contains a specific number.

```R
card = 3;
does_stack_include_card(c(2, 3, 4, 5), card);
# => TRUE
```

## 2. Find the position of a card

Elyse wants to know the position (index) of a card in the stack.
If the card is not in the stack, return `-1`.

```R
card = 2;
get_card_position(c(9, 7, 3, 2), card);
# => 4
```

## 3. Determine if each card is even

Elyse wants to know if every card is even -- in other words, if each number in the stack is an even number.

```R
is_each_card_even(c(2, 4, 6, 7));
# => FALSE
```

## 4. Check if the stack contains an odd-value card

Elyse wants to know if there is an odd number in the stack.

```R
does_stack_include_odd_card(c(3, 2, 6, 4, 8));
# => TRUE
```

## 5. Get the first odd card from the stack

Elyse wants to know the value of the first card that is odd.
If there is no odd card in the stack, return `-1`.

```R
get_first_odd_card(c(4, 2, 8, 7, 9));
# => 7
```

## 6. Determine the position of the first card that is even

Elyse wants to know the position of the first card that is even.
If there is no even card in the stack, return `-1`.

```R
get_first_even_card_position(c(5, 2, 3, 1));
# => 2
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Introduction

We saw in the `vectors` concept that a vector can be used in a conditional expression, giving a vector of booleans. This in turn can be used in functions such as `all()` and `any()`.

```R
> v <- c(4, 7, 10)
> v >= 6
[1] FALSE TRUE TRUE
> all(v > 6)
[1] FALSE # not all elements match this condition
> any(v > 6)
[1] TRUE # at least one element matches
```

The technique is much more powerful than this.

## Array subsets

Selected elements of an array can be pulled out with an index number or a vector of indices:

```R
> v <- 5:10
> v
[1] 5 6 7 8 9 10
> v[3]
[1] 7
> v[c(2, 4)]
[1] 6 8
```

Alternatively, use a vector of booleans to filter the original vector, returning a subset of entries matched to a `TRUE` value:

```R
> v <- 1:3
> bools <- c(FALSE, TRUE, TRUE)
> v[bools]
[1] 2 3
```

It is a small step from there to generating the boolean vector with a conditional expression:

```R
> v[v >= 2]
[1] 2 3
```

## Finding indices

The `which()` function takes a boolean argument and returns a vector of indices that yield `TRUE`.

```R
> v
[1] 2 7 9

> v[v > 5] # returns values
[1] 7 9

> which(v > 5) # returns indices
[1] 2 3
```
11 changes: 11 additions & 0 deletions exercises/concept/elyses-analytic-enchantments/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"authors": ["colinleach"],
"contributors": [],
"files": {
"solution": ["elyses-analytic-enchantments.R"],
"test": ["test_elyses-analytic-enchantments.R"],
"exemplar": [".meta/exemplar.R"]
},
"forked_from": ["javascript/elyses-analytic-enchantments"],
"blurb": "Explore vector filtering as you help Elyse continue her training as a magician"
}
25 changes: 25 additions & 0 deletions exercises/concept/elyses-analytic-enchantments/.meta/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Design

## Goal

The goal of this exercise is to build on the `vectors` concept by teaching the student more about vector filtering/subsetting in R.

## Learning objectives

- Understand the use of conditional expressions to get a subset of the original vector.
- Understand the use of `which()` to get indices of elements that match a condition.

## Out of scope

- Recycling is not mentioned within this exercise, though it is explained in `vector-filtering/about.md` which unlocks on completing this exercise.

## Concepts

The Concepts this exercise unlocks are:

- `vector-functions`
- `nothingness`

## Prerequisites

- `vectors`
25 changes: 25 additions & 0 deletions exercises/concept/elyses-analytic-enchantments/.meta/exemplar.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
does_stack_include_card <- function(stack, card) {
card %in% stack
}

get_card_position <- function(stack, card) {
ifelse(does_stack_include_card(stack, card), which(stack == card), -1)
}

is_each_card_even <- function(stack) {
all(stack %% 2 == 0)
}

does_stack_include_odd_card <- function(stack) {
any(stack %% 2 != 0)
}

get_first_odd_card <- function(stack) {
odds <- stack[stack %% 2 != 0]
ifelse(length(odds) > 0, odds[1], -1)
}

get_first_even_card_position <- function(stack) {
even_index <- which(stack %% 2 == 0)
ifelse(length(even_index) > 0, even_index[1], -1)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
does_stack_include_card <- function(stack, card) {
}

get_card_position <- function(stack, card) {
}

is_each_card_even <- function(stack) {
}

does_stack_include_odd_card <- function(stack) {
}

get_first_odd_card <- function(stack) {
}

get_first_even_card_position <- function(stack) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
source("./elyses-analytic-enchantments.R")
library(testthat)

# does_stack_include_card

test_that("when it is the first card", {
stack <- c(1, 2, 3)
card <- 1
expect_equal(does_stack_include_card(stack, card), TRUE)
})

test_that("when there is a card found", {
stack <- c(1, 2, 3)
card <- 4
expect_equal(does_stack_include_card(stack, card), FALSE)
})

# get_card_position

test_that("when it is the first card", {
stack <- c(1, 2, 3)
card <- 1
expect_equal(get_card_position(stack, card), 1)
})

test_that("when the card is not found", {
stack <- c(1, 2, 3)
card <- 4
expect_equal(get_card_position(stack, card), -1)
})

# is_each_card_even

test_that("when all cards are even", {
stack <- c(2, 4, 6)
expect_equal(is_each_card_even(stack), TRUE)
})

test_that("when any card is odd", {
stack <- c(2, 5, 6)
expect_equal(is_each_card_even(stack), FALSE)
})

# does_stack_include_odd_card

test_that("should be true if odd number card is found", {
stack <- c(2, 5, 6)
expect_equal(does_stack_include_odd_card(stack), TRUE)
})

test_that("should be false if no odd number card is found", {
stack <- c(2, 4, 6)
expect_equal(does_stack_include_odd_card(stack), FALSE)
})

# get_first_odd_card

test_that("should return the first odd card found", {
stack <- c(2, 4, 1, 3)
expect_equal(get_first_odd_card(stack), 1)
})

test_that("should return -1 if odd card is not found", {
stack <- c(4, 2, 6)
expect_equal(get_first_odd_card(stack), -1)
})

# get_first_even_card_position

test_that("should return position of first even card", {
stack <- c(2, 4, 1, 3)
expect_equal(get_first_even_card_position(stack), 1)
})

test_that("should return -1 when the card is not found", {
stack <- c(1, 3, 5)
expect_equal(get_first_even_card_position(stack), -1)
})