Skip to content

Commit

Permalink
Add two-fer exercise (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
BNAndras authored Jul 12, 2023
1 parent 57ceff2 commit 4349902
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@
"difficulty": 3,
"status": "beta"
},
{
"slug": "two-fer",
"name": "Two Fer",
"uuid": "198c1176-536a-49db-828b-0dc1655d7da9",
"practices": [],
"prerequisites": [],
"difficulty": 1,
},
{
"slug": "space-age",
"name": "Space Age",
Expand Down
7 changes: 7 additions & 0 deletions exercises/practice/two-fer/.approaches/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"introduction": {
"authors": ["BNAndras"],
"contributors": []
},
"approaches": []
}
79 changes: 79 additions & 0 deletions exercises/practice/two-fer/.approaches/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Introduction

There are generally two approaches for solving Two Fer.
One approach would be using an [`if expression`][if-expression] to test a passed-in value.
A variant of this approach would be an [`ask expression`][ask-expression] to concisely write the `if expression`.

## General guidance

Regardless of the approach used, Pyret doesn't allow one to [re-assign a variable binding][shadowing] that is already in scope
Therefore, you can't rebind `name`.


## Approach: `if` expressions

```pyret
fun two-fer(name):
fun get-name():
if name == "":
"you"
else:
name
end
end
"One for " + get-name() + ", one for me."
end
```

## Approach: `ask` expressions

```pyret
fun two-fer(name):
fun get-name():
ask:
| name == "" then: "you"
| otherwise: name
end
end
"One for " + get-name() + ", one for me."
end
```

## Other approaches

Besides the aforementioned, idiomatic approaches, you could also approach the exercise as follows:

### Other approach: Option datatypes

Pyret provides a type of data called an [`Option`][option-datatype] that can represent a piece of data that is or is not available. The value `none` represents missing or invalid data and `some` wraps around data that is present. An empty incoming string `""` is still considered valid data so we'd need to replace it with `none`. Once we've done that, we can use [`or-else`][or-else] to either return the wrapped value or provide a default value when the Option is `none`.

```pyret
fun two-fer(name):
fun get-option():
if name == "":
none
else:
some(name)
end
end
option = get-option()
"One for " + option.or-else("you") + ", one for me."
end
```

## Which approach to use?

Either the `ask` or `if` expressions work well here and work similarly so the decision is largely stylistic.

[if-expression]: https://pyret.org/docs/latest/Expressions.html#%28elem._%28bnf-prod._%28.Pyret._if-expr%29%29%29
[ask-expression]: https://pyret.org/docs/latest/Expressions.html#%28part._s~3aask-expr%29
[shadowing]: https://pyret.org/docs/latest/Bindings.html#%28part._s~3ashadowing%29
[option-datatype]: https://pyret.org/docs/latest/option.html
[or-else]: https://pyret.org/docs/latest/option.html#%28idx._%28gentag._342%29%29
25 changes: 25 additions & 0 deletions exercises/practice/two-fer/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Instructions

Your task is to determine what you will say as you give away the extra cookie.

If your friend likes cookies, and is named Do-yun, then you will say:

```text
One for Do-yun, one for me.
```

If your friend doesn't like cookies, you give the cookie to the next person in line at the bakery.
Since you don't know their name, you will say _you_ instead.

```text
One for you, one for me.
```

Here are some examples:

| Name | Dialogue |
| :----- | :-------------------------- |
| Alice | One for Alice, one for me. |
| Bohdan | One for Bohdan, one for me. |
| | One for you, one for me. |
| Zaphod | One for Zaphod, one for me. |
8 changes: 8 additions & 0 deletions exercises/practice/two-fer/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Introduction

In some English accents, when you say "two for" quickly, it sounds like "two fer".
Two-for-one is a way of saying that if you buy one, you also get one for free.
So the phrase "two-fer" often implies a two-for-one offer.

Imagine a bakery that has a holiday offer where you can buy two cookies for the price of one ("two-fer one!").
You go for the offer and (very generously) decide to give the extra cookie to a friend.
18 changes: 18 additions & 0 deletions exercises/practice/two-fer/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"authors": [
"BNAndras"
],
"files": {
"solution": [
"two-fer.arr"
],
"test": [
"two-fer-test.arr"
],
"example": [
".meta/example.arr"
]
},
"blurb": "Create a sentence of the form \"One for X, one for me.\".",
"source_url": "https://github.com/exercism/problem-specifications/issues/757"
}
7 changes: 7 additions & 0 deletions exercises/practice/two-fer/.meta/example.arr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
provide: two-fer end

fun two-fer(name):
ask:
| name == "" then: "One for you, one for me."
| otherwise: "One for " + name + ", one for me."
end
19 changes: 19 additions & 0 deletions exercises/practice/two-fer/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[1cf3e15a-a3d7-4a87-aeb3-ba1b43bc8dce]
description = "no name given"

[b4c6dbb8-b4fb-42c2-bafd-10785abe7709]
description = "a name given"

[3549048d-1a6e-4653-9a79-b0bda163e8d5]
description = "another name given"
13 changes: 13 additions & 0 deletions exercises/practice/two-fer/two-fer-test.arr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
include file("two-fer.arr")

check "no name given":
two-fer("") is "One for you, one for me."
end

check "a name given":
two-fer("Alice") is "One for Alice, one for me."
end

check "another name given":
two-fer("Bob") is "One for Bob, one for me."
end
5 changes: 5 additions & 0 deletions exercises/practice/two-fer/two-fer.arr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
provide: two-fer end

fun two-fer(name):
panic("Please implement the two-fer function")
end

0 comments on commit 4349902

Please sign in to comment.