Skip to content

Implement new Concept Exercise: tuples #1009

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

Merged
merged 36 commits into from
Nov 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7d947f3
Concept is ready, and exercise just copy paste
Grenkin1988 Oct 22, 2021
8f66fcf
Merge branch 'exercism:main' into tuples-concept-create
Grenkin1988 Oct 22, 2021
e74d509
Add concept slug - tuples
Grenkin1988 Oct 22, 2021
49282cd
Merge branch 'tuples-concept-create' of https://github.com/Grenkin198…
Grenkin1988 Oct 22, 2021
9e07ed0
Update design, introduction and add Exemplar
Grenkin1988 Oct 22, 2021
3fb4075
Finish the exercise?
Grenkin1988 Oct 22, 2021
4e54dc4
Fix typo
Grenkin1988 Oct 22, 2021
4969e89
Modify sln
Grenkin1988 Oct 22, 2021
5cad567
Merge remote-tracking branch 'origin/main' into tuples-concept-create
Grenkin1988 Oct 26, 2021
5b9b6ec
Fix concept
Grenkin1988 Oct 26, 2021
24f89f4
fix instructions
Grenkin1988 Oct 26, 2021
99a8774
fix config
Grenkin1988 Oct 26, 2021
e07de40
Apply suggestions from code review
Grenkin1988 Oct 26, 2021
dba112e
Tubles no longer all string
Grenkin1988 Oct 26, 2021
69ea0c3
Update exercises/concept/tisbury-treasure-hunt/.meta/Exemplar.fs
Grenkin1988 Oct 26, 2021
78daf9c
Update hints
Grenkin1988 Oct 26, 2021
2e3525a
Update exercises/concept/tisbury-treasure-hunt/TisburyTreasureHunt.fs
Grenkin1988 Oct 27, 2021
b8ec116
Update exercises/concept/tisbury-treasure-hunt/.meta/Exemplar.fs
Grenkin1988 Oct 27, 2021
792022e
Update exercises/concept/tisbury-treasure-hunt/.meta/config.json
Grenkin1988 Oct 27, 2021
94135e2
Fix tests
Grenkin1988 Oct 27, 2021
8cb0763
Provide hint for parsing
Grenkin1988 Oct 27, 2021
d5a0332
Update concepts/tuples/about.md
Grenkin1988 Oct 28, 2021
0509d1a
Update exercises/concept/tisbury-treasure-hunt/.docs/introduction.md
Grenkin1988 Oct 28, 2021
35f0994
Update concepts/tuples/about.md
Grenkin1988 Oct 28, 2021
d4a93b3
Update exercises/concept/tisbury-treasure-hunt/.docs/instructions.md
Grenkin1988 Oct 28, 2021
aa334d3
Update exercises/concept/tisbury-treasure-hunt/.docs/instructions.md
Grenkin1988 Oct 28, 2021
2f7e5b5
Update exercises/concept/tisbury-treasure-hunt/.docs/instructions.md
Grenkin1988 Oct 28, 2021
a3f5008
Update exercises/concept/tisbury-treasure-hunt/.docs/instructions.md
Grenkin1988 Oct 28, 2021
268988a
Update exercises/concept/tisbury-treasure-hunt/.docs/introduction.md
Grenkin1988 Oct 28, 2021
7e84349
Update exercises/concept/tisbury-treasure-hunt/.docs/instructions.md
Grenkin1988 Oct 28, 2021
3001dcc
Update exercises/concept/tisbury-treasure-hunt/.docs/instructions.md
Grenkin1988 Oct 28, 2021
9938230
Update exercises/concept/tisbury-treasure-hunt/.docs/instructions.md
Grenkin1988 Oct 28, 2021
745d2ff
Update exercises/concept/tisbury-treasure-hunt/.docs/instructions.md
Grenkin1988 Oct 28, 2021
b621a3e
Merge branch 'exercism:main' into tuples-concept-create
Grenkin1988 Oct 28, 2021
819adca
More changes to the texts
Grenkin1988 Oct 29, 2021
40dbdf5
Update concepts/tuples/about.md
Grenkin1988 Nov 2, 2021
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
5 changes: 5 additions & 0 deletions concepts/tuples/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"blurb": "A tuple is a grouping of unnamed but ordered values, possibly of different types.",
"authors": ["Grenkin1988"],
"contributors": []
}
55 changes: 55 additions & 0 deletions concepts/tuples/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# About

A [tuple][tuple] is a _immutable_ grouping of unnamed but ordered values, possibly of different types. Tuples can either be reference types or structs.

`tuples` can hold any (or multiple) data type(s) -- including other `tuples`.

## Tuple Construction

Tuples can be created using `(<element_1>, <element_2>)` declaration.
Tuples can be pairs, triples, and so on, of the same or different types. Some examples are illustrated in the following code:

```fsharp
(1, 2)
// Triple of strings.
("one", "two", "three")
// Tuple of generic types.
(a, b)
// Tuple that has mixed types.
("one", 1, 2.0)
// Tuple of integer expressions.
(a + 1, b + 1)
```

## Obtaining Individual Values

Pattern matching

```fsharp
match tuple with
| (x,y) -> printfn "Pair %A %A" x y
```
Tuple deconstruction

```fsharp
let (a,b) = (12, "twelve")
// a = 12, b = "twelve"
```
Using helper functions

```fsharp
let tuple = (1, 2)
let c = fst tuple
let d = snd tuple
// c = 1, d = 2
```

## Key points about tuples
Some key things to know about tuples are:

* A particular instance of a tuple type is a single object, similar to a two-element array in C#, say. When using them with functions they count as a single parameter.
* Tuple types cannot be given explicit names. The “name” of the tuple type is determined by the combination of types that are multiplied together.
* The order of the multiplication is important. So `int*string` is not the same tuple type as `string*int`.
* The comma is the critical symbol that defines tuples, not the parentheses. You can define tuples without the parentheses, although it can sometimes be confusing. In F#, if you see a comma, it is probably part of a tuple.
* Tuples have structural equality. `(1, 4, 6) = (1, 4, 6) -> true`
* Tuples can be used as arguments of function and return value of function
53 changes: 53 additions & 0 deletions concepts/tuples/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Introduction

A tuple is an _immutable_ grouping of unnamed but ordered values.
Tuples can hold any (or multiple) data type(s) -- including other tuples.

Tuples support can be used when pattern matching. They can be deconstructed and constructed.

Tuples have structural equality. Tuples must be of the same length and same type in order to be equal. All value of tuple compared.
For example:

```fsharp
(1, 2) = (1, 2)
// true
(1, 2) = (2, 1)
// false
(1, 2) = (1, 2, 3)
// compiler error
(1, 2) = (1, "2")
// compiler error
```

## Tuple Construction

Tuples can be created using `(<element_1>, <element_2>)` declaration.
Tuples ca be pairs, triples, and so on, of the same or different types. Some examples are illustrated in the following code.:

```fsharp
("one", 2) // Tuple pair
("one", 2, true) // Tuple triplet
```

## Obtaining Individual Values

Pattern matching

```fsharp
match tuple with
| (x,y) -> printfn "Pair %A %A" x y
```
Tuple deconstruction

```fsharp
let (a,b) = (12, "twelve")
// a = 12, b = "twelve"
```
Using helper functions

```fsharp
let tuple = (1, 2)
let c = fst tuple
let d = snd tuple
// c = 1, d = 2
```
10 changes: 10 additions & 0 deletions concepts/tuples/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"url": "https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/tuples",
"description": "Tuples"
},
{
"url": "https://fsharpforfunandprofit.com/posts/tuples/",
"description": "Understanding tuples"
}
]
12 changes: 12 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@
"uuid": "ab0e683f-46e8-4679-99d2-def4c337e4b8",
"concepts": ["strings"],
"prerequisites": ["basics"]
},
{
"slug": "tisbury-treasure-hunt",
"name": "Tisbury Treasure Hunt",
"uuid": "2d397532-9c6c-473d-8af7-d14333e92a60",
"concepts": ["tuples"],
"prerequisites": ["pattern-matching", "strings"]
}
],
"practice": [
Expand Down Expand Up @@ -1614,6 +1621,11 @@
"uuid": "8a3e23fd-aa42-42c3-9dbd-c26159fd6774",
"slug": "strings",
"name": "Strings"
},
{
"uuid": "5bd49bb7-3487-4925-9c0e-866d56a880ee",
"slug": "tuples",
"name": "Tuples"
}
],
"key_features": [
Expand Down
7 changes: 7 additions & 0 deletions exercises/Exercises.sln
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TracksOnTracksOnTracks", "c
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ValentinesDay", "concept\valentines-day\ValentinesDay.fsproj", "{2276A3B7-9BB2-426D-97AC-5E90E45E0867}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TisburyTreasureHunt", "concept\tisbury-treasure-hunt\TisburyTreasureHunt.fsproj", "{7115D50D-A5D8-47FE-949E-4CB0BF57A360}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "practice", "practice", "{29984DF2-2734-483C-BC7D-F6D41599DACD}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Accumulate", "practice\accumulate\Accumulate.fsproj", "{73E8C86D-9983-4531-B125-7671EDD24382}"
Expand Down Expand Up @@ -334,6 +336,10 @@ Global
{2276A3B7-9BB2-426D-97AC-5E90E45E0867}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2276A3B7-9BB2-426D-97AC-5E90E45E0867}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2276A3B7-9BB2-426D-97AC-5E90E45E0867}.Release|Any CPU.Build.0 = Release|Any CPU
{7115D50D-A5D8-47FE-949E-4CB0BF57A360}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7115D50D-A5D8-47FE-949E-4CB0BF57A360}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7115D50D-A5D8-47FE-949E-4CB0BF57A360}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7115D50D-A5D8-47FE-949E-4CB0BF57A360}.Release|Any CPU.Build.0 = Release|Any CPU
{73E8C86D-9983-4531-B125-7671EDD24382}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73E8C86D-9983-4531-B125-7671EDD24382}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73E8C86D-9983-4531-B125-7671EDD24382}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -840,6 +846,7 @@ Global
{3F2DDCE9-69FF-4878-8578-9B02CA0AFAC8} = {9D239135-8242-4AC0-94AE-7CCD8408B531}
{CF59E47A-0F70-4868-BA7D-5282AE88C954} = {9D239135-8242-4AC0-94AE-7CCD8408B531}
{2276A3B7-9BB2-426D-97AC-5E90E45E0867} = {9D239135-8242-4AC0-94AE-7CCD8408B531}
{7115D50D-A5D8-47FE-949E-4CB0BF57A360} = {9D239135-8242-4AC0-94AE-7CCD8408B531}
{73E8C86D-9983-4531-B125-7671EDD24382} = {29984DF2-2734-483C-BC7D-F6D41599DACD}
{F1E02173-56C0-42FA-B154-97216A285B5B} = {29984DF2-2734-483C-BC7D-F6D41599DACD}
{4E137BE8-FEC7-4622-9E94-09EB95A19297} = {29984DF2-2734-483C-BC7D-F6D41599DACD}
Expand Down
26 changes: 26 additions & 0 deletions exercises/concept/tisbury-treasure-hunt/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Hints

## General

- [Tuples](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/tuples) are immutable grouping of unnamed but ordered values, possibly of different types.
- Elements within tuples can be [obtained](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/tuples#obtaining-individual-values) via pattern matching, tuple deconstruction or using helper functions.

## 1. Extract coordinates

- Remember: tuples allow access using helper functions or deconstruction.
- Check [parsing](https://docs.microsoft.com/en-us/dotnet/api/system.int32.parse?view=net-5.0) in order to get number from string.

## 2. Format coordinates

- Check [examples](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/tuples#examples) for more details on tuples creation.
- Check [string slicing](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/strings#string-indexing-and-slicing) for more details on strings.

## 3. Match coordinates

- What operators could be used here for for [testing membership](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/strings#string-indexing-and-slicing)?
- Could you re-use your `convertCoordinate()` function?

## 4. Combine matched records

- Remember that tuples support [pattern matching](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/tuples#obtaining-individual-values).
- Could you re-use your `compareRecords()` function here?
95 changes: 95 additions & 0 deletions exercises/concept/tisbury-treasure-hunt/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Instructions

Aazra and Rui are teammates competing in a pirate-themed treasure hunt.
One has a list of treasures with map coordinates, the other a list of location names with map coordinates.
They've also been given blank maps with a starting place marked YOU ARE HERE.

<table>
<tr><th>Azara's List</th><th></th><th>Rui's List</th></tr>
<tr><td>

| Treasure | Coordinates |
| --------------------------- | ----------- |
| Amethyst Octopus | 1F |
| Angry Monkey Figurine | 5B |
| Antique Glass Fishnet Float | 3D |
| Brass Spyglass | 4B |
| Carved Wooden Elephant | 8C |
| Crystal Crab | 6A |
| Glass Starfish | 6D |
| Model Ship in Large Bottle | 8A |
| Pirate Flag | 7F |
| Robot Parrot | 1C |
| Scrimshaw Whale's Tooth | 2A |
| Silver Seahorse | 4E |
| Vintage Pirate Hat | 7E |

</td><td></td><td>

| Location Name | Coordinates | Quandrant |
| ------------------------------------- | ----------- | --------- |
| Seaside Cottages | ("1", "C") | Blue |
| Aqua Lagoon (Island of Mystery) | ("1", "F") | Yellow |
| Deserted Docks | ("2", "A") | Blue |
| Spiky Rocks | ("3", "D") | Yellow |
| Abandoned Lighthouse | ("4", "B") | Blue |
| Hidden Spring (Island of Mystery) | ("4", "E") | Yellow |
| Stormy Breakwater | ("5", "B") | Purple |
| Old Schooner | ("6", "A") | Purple |
| Tangled Seaweed Patch | ("6", "D") | Orange |
| Quiet Inlet (Island of Mystery) | ("7", "E") | Orange |
| Windswept Hilltop (Island of Mystery) | ("7", "F") | Orange |
| Harbor Managers Office | ("8", "A") | Purple |
| Foggy Seacave | ("8", "C") | Purple |

</td></tr>
</table>

But things are a bit disorganized: Azara's coordinates appear to be formatted and sorted differently from Rui's, and they have to keep looking from one list to the other to figure out which treasures go with which locations.
Being budding fsharpies, they have come to you for help in writing a small program (a set of functions, really) to better organize their hunt information.

## 1. Extract coordinates

Implement the `getCooordinate()` function that takes a `(treasure, coordinate)` pair from Azaras list and returns only the extracted map coordinate.

```fsharp
getCoordinate ("Scrimshaw Whale's Tooth", "2A")
// "2A"
```

## 2. Format coordinates

Implement the `convertCoordinate()` function that takes a coordinate in the format "2A" and returns a tuple in the format `("2", "A")`.

```fsharp
convertCoordinate "2A"
// ("2", "A")
```

## 3. Match coordinates

Implement the `compareRecords()` function that takes a `(treasure, coordinate)` pair and a `(location, coordinate, quadrant)` record and compares coordinates from each.
Return **`true`** if the coordinates "match", and return **`false`** if they do not.
Re-format coordinates as needed for accurate comparison.

```fsharp
compareRecords ("Brass Spyglass", "4B") ("Seaside Cottages", ("1", "C"), "blue")
// false

compareRecords ("Model Ship in Large Bottle", "8A") ("Harbor Managers Office", ("8", "A"), "purple")
// true
```

## 4. Combine matched records

Implement the `createrecord()` function that takes a `(treasure, coordinate)` pair from Azara's list and a `(location, coordinate, quadrant)` record from Rui's list and returns `(treasure, coordinate, location, coordinate, quadrant)` **if the coordinates match**.
If the coordinates _do not_ match, return the tuple of same shape but filled with `""`
Re-format the coordinate as needed for accurate comparison.

```fsharp
createRecord ("Brass Spyglass", "4B") ("Abandoned Lighthouse", ("4", "B"), "Blue")
("Brass Spyglass", "4B", "Abandoned Lighthouse", ("4", "B"), "Blue")

createRecord ("Brass Spyglass", "4B") ("Seaside Cottages", ("1", "C"), "Blue")
("", "", "", ("", ""), "")
```
53 changes: 53 additions & 0 deletions exercises/concept/tisbury-treasure-hunt/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Introduction

A tuple is an _immutable_ grouping of unnamed but ordered values.
Tuples can hold any (or multiple) data type(s) -- including other tuples.

Tuples support can be used when pattern matching. They can be deconstructed and constructed.

Tuples have structural equality. Tuples must be of the same length and same type in order to be equal. All value of tuple compared.
For example:

```fsharp
(1, 2) = (1, 2)
// true
(1, 2) = (2, 1)
// false
(1, 2) = (1, 2, 3)
// compiler error
(1, 2) = (1, "2")
// compiler error
```

## Tuple Construction

Tuples can be created using `(<element_1>, <element_2>)` declaration.
Tuples ca be pairs, triples, and so on, of the same or different types. Some examples are illustrated in the following code.:

```fsharp
("one", 2) // Tuple pair
("one", 2, true) // Tuple triplet
```

## Obtaining Individual Values
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be nice to move the examples next to the text where the concept is explained. For example, the example of matching a tuple can be moved to the pattern matching example, possibly including the deconstruction code too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, not sure I understand what is required

Copy link
Member

Choose a reason for hiding this comment

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

No problem. I can do a follow-up PR later.


Pattern matching

```fsharp
match tuple with
| (x,y) -> printfn "Pair %A %A" x y
```
Tuple deconstruction

```fsharp
let (a,b) = (12, "twelve")
// a = 12, b = "twelve"
```
Using helper functions

```fsharp
let tuple = (1, 2)
let c = fst tuple
let d = snd tuple
// c = 1, d = 2
```
21 changes: 21 additions & 0 deletions exercises/concept/tisbury-treasure-hunt/.meta/Exemplar.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module TisburyTreasureHunt

open System

let getCoordinate (line: string * string): string = snd line

let convertCoordinate (coordinate: string): int * char =
Int32.Parse(string coordinate.[0]), coordinate.[1]
Copy link
Member

Choose a reason for hiding this comment

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

I hadn't considered the fact that we need students to convert a char to an int, which they probably don't know how to do. I do think it's worth keeping an int to really stress the "different types" feature of a tuple. Could you perhaps add a suggestion how to do this to the hints.md file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also might be worse adding parsing to the strings concept?
For example we could have some "EventId=1356" in the log message, and as last task to get EventId as an int?

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure, I'll think on it.


let compareRecords (azarasData: string * string) (ruisData: string * (int * char) * string) : bool =
let azarasCoordinate = getCoordinate azarasData
let (_, ruisCoordinate, _) = ruisData
convertCoordinate azarasCoordinate = ruisCoordinate

let createRecord (azarasData: string * string) (ruisData: string * (int * char) * string) : (string * string * string * string) =
if compareRecords azarasData ruisData then
match azarasData, ruisData with
| (treasure, coordinate), (location, _, quadrant) ->
(coordinate, location, quadrant, treasure)
else
("", "", "", "")
19 changes: 19 additions & 0 deletions exercises/concept/tisbury-treasure-hunt/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"blurb": "Learn about tuples by helping out competitors in the Tisbury Treasure Hunt.",
"icon": "proverb",
"authors": [
"Grenkin1988"
],
"files": {
"solution": [
"TisburyTreasureHunt.fs"
],
"test": [
"TisburyTreasureHuntTests.fs"
],
"exemplar": [
".meta/Exemplar.fs"
]
},
"forked_from": ["python/tisbury-treasure-hunt"]
}
Loading