トラック
/
F#
F#
/
演習
/
ティズベリーの宝探し
ティズベリーの宝探し

ティズベリーの宝探し

学習演習

はじめに

タプル

タプルは、名前を持たないけれど順序のある値をまとめた、_不変_のグループです。 タプルには、どんなデータ型でも(複数でも)入れることができます。別のタプルを入れることもできます。

タプルは、(と)の文字の間にカンマで区切った値を並べて定義します:(<element_1>, ... , <element_n>)。

("one", 2) // Tuple pair (2 values)
("one", 2, true) // Tuple triplet (3 values)

比較できるのは、同じ長さで同じ型を(同じ順序で)持つタプル同士だけです。 タプルは構造的等価性を持ちます。つまり、すべての値が等しいときに_だけ_、2つのタプルは等しいとみなされます。

(1, 2) = (1, 2) // Same length, same types, same values, same order
// => true

(1, 2) = (2, 1) // Same length, same types, same values, different order
// => false

(1, 2) = (1, "2") // Same length, different types
// compiler error

(1, 2) = (1, 2, 3) // Different length
// compiler error

タプルから値を取り出す方法は、次の3つです:

  • fstとsndの関数
  • タプルの分解
  • パターンマッチング
let person = ("Jordan", 170)

// Option 1: fst/snd
let name1 = fst person
let length2 = snd person

// Option 2: deconstruction
let (name2, length2) = person
// => name2 = "Jordan"
// => length2 = 170

// Option 3: pattern matching
match person with
| name3, length3 -> printf "%s: %d" name3 length3

説明

AzaraとRuiは、海賊をテーマにした宝探しで競い合うチームメイトです。 片方は宝の名前と地図上の座標のリストを、もう片方は場所の名前と地図上の座標のリストを持っています。 二人には、出発地点にYOU ARE HEREと記された白地図も渡されています。

Azaraのリスト Ruiのリスト
宝物 座標
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
場所の名前 座標 区域
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

でも、少し整理されていません。Azaraの座標は、Ruiのものとは形式も並び順も違うようで、どの宝がどの場所に対応するのかを知るには、二つのリストを何度も見比べなければなりません。 そこで、F#を学び始めたばかりの二人が、宝探しの情報をうまく整理するために、小さなプログラム(というより、いくつかの関数)を書くのを手伝ってほしいと頼みに来ました。

1. 座標を取り出す

Azaraのリストから(treasure, coordinate)のペアを受け取り、抽出した地図上の座標だけを返すgetCooordinate()関数を実装しましょう。

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

2. 座標を整形する

"2A"という形式の座標を受け取り、(2, 'A')という形式のタプルを返すconvertCoordinate()関数を実装しましょう。

convertCoordinate "2A"
// (2, 'A')

3. 座標を照合する

(treasure, coordinate)のペアと、(location, coordinate, quadrant)のレコードを受け取り、それぞれの座標を比較するcompareRecords()関数を実装しましょう。 座標が「一致」すれば**trueを返し、一致しなければfalse**を返します。 正確に比較できるように、必要に応じて座標の形式を整えましょう。

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. 一致したレコードを組み合わせる

Azaraのリストの(treasure, coordinate)のペアと、Ruiのリストの(location, coordinate, quadrant)のレコードを受け取り、座標が一致すれば(coordinate, location, quadrant, treasure)を返すcreaterecord()関数を実装しましょう。 座標が_一致しなければ_、同じ形で""で埋めたタプルを返します。 正確に比較できるように、必要に応じて座標の形式を整えましょう。

createRecord ("Brass Spyglass", "4B") ("Abandoned Lighthouse", (4, 'B'), "Blue")
// ("4B", "Abandoned Lighthouse", "Blue", "Brass Spyglass")

createRecord ("Brass Spyglass", "4B") ("Seaside Cottages", (1, 'C'), "Blue")
// ("", "", "", "")
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
F# Exercism

ティズベリーの宝探しを始める準備はできましたか?

Exercismに登録すれば、18個のコンセプト148個の演習、そして本物の人間によるメンタリングとともに、F#を学んでマスターできます。すべて無料です。