轨道
/
Elm
Elm
/
练习
/
秘密
秘密

秘密

学习练习

简介

位运算

位运算允许我们操作二进制数中的单个位。

Elm 在其 Bitwise 模块中提供了几个位运算符。

基本运算

修改数字的单个位称为_掩码操作_。 _掩码_是一个数字,其中特定的位已按特定方式设置,从而使用像 and、or 和 xor 这样的位运算符来操作另一个数字。

and

and通过只保留两个数中都是 1 的位来合并两个数。 这对于检查单个位是否已设置很有用。 例如,要检查数字的第 4 位是否设置为 1,可以用掩码01000(十进制中的8)对它进行 and 运算,然后看结果是否非零:

Bitwise.and 13 8 --> 8
--  13 = 01101
--   8 = 01000
-- and = 01000 = 8
or

or通过以下方式合并两个数:如果某一位在其中一个或两个数中为 1,就将这一位设置为 1。 这对于将特定的一位设置为 1 很有用。 例如,要将 10101 中的第 2 位设置为 1,可以用掩码00010对它进行 or 运算:

Bitwise.or 21 2 --> 23
-- 21 = 10101
--  2 = 00010
-- or = 10111 = 23
异或(xor)

xor通过以下方式合并两个数:如果某一位在一个数中为 1,而在另一个数中为 0,就将这一位设置为 1。 这对于将某一位翻转为相反值很有用:

Bitwise.xor 20 5 --> 17
--  20 = 10100
--   5 = 00101
-- xor = 10001 = 17
取反

complement会将数字的每一位取反(0 变成 1,1 变成 0)。

注意,这会导致正数变成负数,负数变成正数。 这是因为二进制中的负数在最左边的位置上用 1 表示。

Bitwise.complement 21 --> -22
--         21 = 00000000000000000000000000010101
-- complement = 11111111111111111111111111101010 = -22
位移

以下运算符将位向左或向右移动指定的位数,实际上相当于乘以或除以 2 的幂。

shiftLeftBy将位向左移动,从右侧补 0。 例如,要将 21 左移 3 位:

Bitwise.shiftLeftBy 3 21 --> 168
--  21 = 10101
-- shiftLeftBy 3 = 10101000 = 168

这相当于说21 * 2^3 = 21 * 2 * 2 * 2 = 168

shiftRightBy:将位向右移动:

Bitwise.shiftRightBy 2 21 --> 5
--  21 = 10101
-- shiftRightBy 2 = 00101 = 5

向右移动 2 位等同于整数除以 4。

注意,这个函数会复制最左边位上的值。 因此,负数仍会保持为负数:

Bitwise.shiftRightBy 3 -21 --> -3
--  -21 = 111...101011
-- shiftRightBy 3 = 111...11101 = -3

如果你想右移并用零填充,请使用 shiftRightZfBy:

Bitwise.shiftRightZfBy 3 -21 --> 536870909
--  -21 = 111...101011
-- shiftRightZfBy 3 = 00111...11101 = 536870909

说明

你的朋友刚给你发来一条带有重要秘密的消息。为了不让别人轻易读懂,这条消息经过了一系列位操作加密。你需要编写相应的函数来帮助解密这条消息。

1. 把位右移回去

解密消息的第一步,是还原加密过程中的移位,也就是把位向右移回去。解密过程的后续步骤会假定 0 是从左侧插入的。

实现 shiftBack 函数,它接受要移动的位数和一个值,并完成这次移位。

shiftBack 2 42 --> 10

2. 设置一些位

接下来,有一些位需要设置为 1。

实现 setBits 函数,它接受一个掩码和一个值,并返回把值中的某些位设置为 1 之后的结果。当掩码中的对应位也是 1 时,值中对应的位应设置为 1。其他所有位保持不变。

setBits 66 212 --> 64

3. 翻转特定的位

加密过程中有些位会被翻转。要解密消息,就需要把它们翻转回来。

实现 flipBits 函数,它接受一个掩码和一个值。掩码指明要翻转值中的哪些位。如果掩码中的某一位是 1,就翻转值中对应的位。其他所有位保持不变。

flipBits 23 157 --> 138

4. 清除特定的位

还有一些位解密后始终是 0。

实现 clearBits 函数,它接受一个掩码和一个值。当掩码中的某一位是 1 时,value 中对应的位应设置为 0。其他所有位保持不变。

clearBits 2 15 --> 13

5. 解密消息

现在你已经有了解密所需的全部函数,可以解码朋友发来的消息了。实现 decrypt 函数,它执行以下操作:

  1. 用你朋友出生的那一年(1996)来设置位
  2. 用你们初次见面的那一年(2009)来翻转结果
  3. 按你们一起上课的门数(5)把位右移回去
  4. 清除第一位和第五位。
decrypt 380182 --> 11840

请用你在前面各个任务中实现的所有函数来实现 decrypt。

通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Elm Exercism

准备好开始 秘密 了吗?

注册 Exercism,借助 28 个概念110 个练习 和真人导师指导,学习并掌握 Elm,全部免费。