轨道
/
F#
F#
/
练习
/
蒂斯伯里寻宝
蒂斯伯里寻宝

蒂斯伯里寻宝

学习练习

简介

元组

元组是一组不可变的、未命名但有序的值。元组可以包含任意(或多种)数据类型,包括其他元组。

元组定义为 ( 和 ) 字符之间的逗号分隔值:(<element_1>, ... , <element_n>)。

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

只有长度相同且类型相同(顺序也相同)的元组才能比较。元组具有结构相等性,这意味着只有当所有值都相等时,它们才相等。

(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

有三种方法可以从元组中提取值:

  • 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 是队友,正在参加一场海盗主题的寻宝比赛。 一个人手里有一份带地图坐标的宝物清单,另一个人手里有一份带地图坐标的地点名称清单。 他们还拿到了空白地图,起点处标着“你在这里”。

Azara 的清单 Rui 的清单
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
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

不过情况有点乱:Azara 的坐标格式和排序似乎跟 Rui 的不一样,两人只能来回对照两份清单,才能弄清楚哪些宝物对应哪些地点。 作为初露头角的 F# 爱好者,他们来找你帮忙,想写一个小程序(确切地说,是一组函数),把寻宝信息整理得更有条理。

1. 提取坐标

实现 getCooordinate() 函数,它接收 Azara 清单中的一个 (treasure, coordinate) 二元组,只返回提取出的地图坐标。

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

2. 格式化坐标

实现 convertCoordinate() 函数,它接收一个 "2A" 格式的坐标,返回一个 (2, 'A') 格式的元组。

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

3. 匹配坐标

实现 compareRecords() 函数,它接收一个 (treasure, coordinate) 二元组和一个 (location, coordinate, quadrant) 记录,并比较两者的坐标。 如果坐标“匹配”,返回 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. 合并匹配的记录

实现 createrecord() 函数,它接收 Azara 清单中的一个 (treasure, coordinate) 二元组和 Rui 清单中的一个 (location, coordinate, quadrant) 记录;如果坐标匹配,返回 (coordinate, location, quadrant, treasure)。 如果坐标不匹配,返回一个形状相同、但各项都填 "" 的元组。 为了准确比较,按需重新格式化坐标。

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#,全部免费。