translated some Chinese curriculum files (#40531)
* translate task #1 - #4 * add translation of zhang-suen-thinning and markov algorithm Co-authored-by: S1ngS1ng <liuxing0514@gmail.com>
This commit is contained in:
		| @@ -7,7 +7,7 @@ videoUrl: '' | ||||
|  | ||||
| # --description-- | ||||
|  | ||||
| 到目前为止,我们已经学会了创建图表表示的不同方法。现在怎么办?一个自然的问题是图中任何两个节点之间的距离是多少?输入<dfn>图遍历算法</dfn> 。 <dfn>遍历算法</dfn>是遍历或访问图中节点的算法。一种遍历算法是广度优先搜索算法。该算法从一个节点开始,首先访问一个边缘的所有邻居,然后继续访问它们的每个邻居。在视觉上,这就是算法正在做的事情。 要实现此算法,您需要输入图形结构和要启动的节点。首先,您需要了解距起始节点的距离。这个你想要开始你所有的距离最初一些大的数字,如`Infinity` 。这为从起始节点无法访问节点的情况提供了参考。接下来,您将要从开始节点转到其邻居。这些邻居是一个边缘,此时你应该添加一个距离单位到你要跟踪的距离。最后,有助于实现广度优先搜索算法的重要数据结构是队列。这是一个数组,您可以在其中添加元素到一端并从另一端删除元素。这也称为<dfn>FIFO</dfn>或<dfn>先进先出</dfn>数据结构。 | ||||
| 到目前为止,我们已经学会了创建图表表示的不同方法。现在怎么办?一个自然的问题是图中任何两个节点之间的距离是多少?输入<dfn>图遍历算法</dfn> 。 <dfn>遍历算法</dfn>是遍历或访问图中节点的算法。一种遍历算法是广度优先搜索算法。该算法从一个节点开始,首先访问一个边缘的所有邻居,然后继续访问它们的每个邻居。在视觉上,这就是算法正在做的事情。 要实现此算法,您需要输入图形结构和要启动的节点。首先,您需要了解距起始节点的距离。这个你想要开始你所有的距离最初一些大的数字,如`Infinity` 。这为从起始节点无法访问节点的情况提供了参考。接下来,您将要从开始节点转到其邻居。这些邻居是一个边缘,此时你应该添加一个距离单位到你要跟踪的距离。最后,有助于实现广度优先搜索算法的重要数据结构是队列。这是一个数组,您可以在其中添加元素到一端并从另一端删除元素。这也称为<dfn>FIFO</dfn>或<dfn>先进先出</dfn>数据结构。 | ||||
|  | ||||
| # --instructions-- | ||||
|  | ||||
|   | ||||
| @@ -1,31 +1,31 @@ | ||||
| --- | ||||
| id: 5900f3b31000cf542c50fec6 | ||||
| title: 'Problem 71: Ordered fractions' | ||||
| title: '关卡 71:有序分数' | ||||
| challengeType: 5 | ||||
| forumTopicId: 302184 | ||||
| --- | ||||
|  | ||||
| # --description-- | ||||
|  | ||||
| Consider the fraction, `n`/`d`, where `n` and `d` are positive integers. If `n`<`d` and HCF(`n`,`d`)=1, it is called a reduced proper fraction. | ||||
| 考虑形如 `n`/`d` 的分数,其中 `n` 和 `d` 均为正整数。如果 `n`<`d`,且最大公约数 HCF(`n`,`d`)=1,则该分数被称为最简真分数。 | ||||
|  | ||||
| If we list the set of reduced proper fractions for `d` ≤ 8 in ascending order of size, we get: | ||||
| 如果我们将 `d` ≤ 8 的最简真分数构成的集合按大小升序列出,将得到: | ||||
|  | ||||
| <div style='text-align: center;'>1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, <strong>2/5</strong>, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8</div> | ||||
|  | ||||
| It can be seen that 2/5 is the fraction immediately to the left of 3/7. | ||||
| 可以看出 2/5 是 3/7 的直接左邻的分数。 | ||||
|  | ||||
| By listing the set of reduced proper fractions for `d` ≤ 1,000,000 in ascending order of size, find the numerator of the fraction immediately to the left of 3/7. | ||||
| 将所有 `d` ≤ 1,000,000 的最简真分数按大小升序排列,求此时 3/7 直接左邻的分数的分子。 | ||||
|  | ||||
| # --hints-- | ||||
|  | ||||
| `orderedFractions()` should return a number. | ||||
| `orderedFractions()` 应该返回一个数字。 | ||||
|  | ||||
| ```js | ||||
| assert(typeof orderedFractions() === 'number'); | ||||
| ``` | ||||
|  | ||||
| `orderedFractions()` should return 428570. | ||||
| `orderedFractions()` 应该返回 428570。 | ||||
|  | ||||
| ```js | ||||
| assert.strictEqual(orderedFractions(), 428570); | ||||
|   | ||||
| @@ -1,31 +1,31 @@ | ||||
| --- | ||||
| id: 5900f3b41000cf542c50fec7 | ||||
| title: 'Problem 72: Counting fractions' | ||||
| title: '关卡 72:分数计数' | ||||
| challengeType: 5 | ||||
| forumTopicId: 302185 | ||||
| --- | ||||
|  | ||||
| # --description-- | ||||
|  | ||||
| Consider the fraction, `n`/`d`, where n and d are positive integers. If `n`<`d` and HCF(`n`,`d`)=1, it is called a reduced proper fraction. | ||||
| 考虑形如 `n`/`d` 的分数,其中 n 和 d 均为正整数。如果 `n`<`d`,且最大公约数 HCF(`n`,`d`)=1,则该分数被称为最简真分数。 | ||||
|  | ||||
| If we list the set of reduced proper fractions for `d` ≤ 8 in ascending order of size, we get: | ||||
| 如果我们将 `d` ≤ 8 的最简真分数构成的集合按大小升序列出,将得到: | ||||
|  | ||||
| <div style='text-align: center;'>1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8</div> | ||||
|  | ||||
| It can be seen that there are 21 elements in this set. | ||||
| 可以看出该集合中共有 21 个元素。 | ||||
|  | ||||
| How many elements would be contained in the set of reduced proper fractions for `d` ≤ 1,000,000? | ||||
| 求 `d` ≤ 1,000,000 的最简真分数构成的集合中共有多少个元素。 | ||||
|  | ||||
| # --hints-- | ||||
|  | ||||
| `countingFractions()` should return a number. | ||||
| `countingFractions()` 应该返回一个数字。 | ||||
|  | ||||
| ```js | ||||
| assert(typeof countingFractions() === 'number'); | ||||
| ``` | ||||
|  | ||||
| `countingFractions()` should return 303963552391. | ||||
| `countingFractions()` 应该返回 303963552391。 | ||||
|  | ||||
| ```js | ||||
| assert.strictEqual(countingFractions(), 303963552391); | ||||
|   | ||||
| @@ -1,31 +1,31 @@ | ||||
| --- | ||||
| id: 5900f3b61000cf542c50fec8 | ||||
| title: 'Problem 73: Counting fractions in a range' | ||||
| title: '关卡 73:区间内的分数个数' | ||||
| challengeType: 5 | ||||
| forumTopicId: 302186 | ||||
| --- | ||||
|  | ||||
| # --description-- | ||||
|  | ||||
| Consider the fraction, `n`/`d`, where n and d are positive integers. If `n`<`d` and HCF(`n`,`d`)=1, it is called a reduced proper fraction. | ||||
| 考虑形如 `n`/`d` 的分数,其中 n 和 d 均为正整数。如果 `n`<`d`,且其最大公约数 HCF(`n`,`d`)=1,则该分数被称为最简真分数。 | ||||
|  | ||||
| If we list the set of reduced proper fractions for `d` ≤ 8 in ascending order of size, we get: | ||||
| 如果我们将 `d` ≤ 8 的最简真分数构成的集合按大小升序列出,将得到: | ||||
|  | ||||
| <div style='text-align: center;'>1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, <strong>3/8</strong>, <strong>2/5</strong>, <strong>3/7</strong>, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8</div> | ||||
|  | ||||
| It can be seen that there are 3 fractions between 1/3 and 1/2. | ||||
| 可以看出在 1/3 和 1/2 之间有3个分数。 | ||||
|  | ||||
| How many fractions lie between 1/3 and 1/2 in the sorted set of reduced proper fractions for `d` ≤ 12,000? | ||||
| 将 `d` ≤ 12,000 的最简真分数构成的集合排序后,在 1/3 和 1/2 之间有多少个分数? | ||||
|  | ||||
| # --hints-- | ||||
|  | ||||
| `countingFractionsInARange()` should return a number. | ||||
| `countingFractionsInARange()` 应该返回一个数字。 | ||||
|  | ||||
| ```js | ||||
| assert(typeof countingFractionsInARange() === 'number'); | ||||
| ``` | ||||
|  | ||||
| `countingFractionsInARange()` should return 7295372. | ||||
| `countingFractionsInARange()` 应该返回 7295372。 | ||||
|  | ||||
| ```js | ||||
| assert.strictEqual(countingFractionsInARange(), 7295372); | ||||
|   | ||||
| @@ -11,48 +11,69 @@ videoUrl: '' | ||||
|  | ||||
| 为[马尔可夫算法](<https://en.wikipedia.org/wiki/Markov algorithm> "wp:马尔可夫算法")创建解释器。 | ||||
|  | ||||
| 规则具有以下语法: | ||||
| 规则的语法如下: | ||||
|  | ||||
| :: =((<!--undefined--> | ||||
|  | ||||
| <!--undefined--> | ||||
|  | ||||
| :: =- >\[。] | ||||
|  | ||||
| :: =(|)\[] | ||||
| <pre>[ruleset] ::= (([comment] | [rule]) [newline]+)* | ||||
| [comment] ::= # {[any character]} | ||||
| [rule] ::= [pattern] [whitespace] -> [whitespace] [.] [replacement] | ||||
| [whitespace] ::= ([tab] | [space]) [[whitespace]] | ||||
| </pre> | ||||
|  | ||||
| 每行有一条规则。 | ||||
|  | ||||
| 如果有的话**。** (期间)出席之前,那么这是一个终止规则,在这种情况下,解释器必须停止执行。 | ||||
| 如果在 \[replacement] 之前有一个 `.`(句点),那么这就是一个终止规则。在这种情况下,解释器必须停止执行。 | ||||
|  | ||||
| 规则集由一系列规则和可选注释组成。 | ||||
| 规则集由一系列规则组成,可能包含一些注释。 | ||||
|  | ||||
| 规则集 | ||||
|  | ||||
| 对条目使用以下测试: | ||||
| 我们会对你提交的代码进行如下测试: | ||||
|  | ||||
| 规则集1: | ||||
| **规则集 1:** | ||||
|  | ||||
| <pre># This rules file is extracted from Wikipedia: | ||||
| <pre># 此条规则来自 Wikipedia: | ||||
| # <code>http://en.wikipedia.org/wiki/Markov_Algorithm</code> | ||||
| A -> apple | ||||
| B -> bag | ||||
| S -> shop | ||||
| T -> the | ||||
| the shop -> my brother | ||||
| a never used -> .terminating rule | ||||
| (终止规则) -> . | ||||
| </pre> | ||||
|  | ||||
| <p>示例文本: </p><p> <code>I bought a B of As from T S.</code> </p>  <p>应该生成输出: </p><p> <code>I bought a bag of apples from my brother.</code> </p>规则集2: <p>终止规则的测试</p> | ||||
| <pre># Slightly modified from the rules on Wikipedia | ||||
| 对于这段文本: | ||||
|  | ||||
| `I bought a B of As from T S.` | ||||
|  | ||||
| 应该输出: | ||||
|  | ||||
| `I bought a bag of apples from my brother.` | ||||
|  | ||||
| **规则集 2:** | ||||
|  | ||||
| 终止规则的测试 | ||||
|  | ||||
| <pre># 基于 Wikipedia 的规则稍做修改 | ||||
| A -> apple | ||||
| B -> bag | ||||
| S -> .shop | ||||
| T -> the | ||||
| the shop -> my brother | ||||
| a never used -> .terminating rule | ||||
| (终止规则) -> . | ||||
| </pre> | ||||
| <p>示例文本: </p><p> <code>I bought a B of As from T S.</code> </p>  <p>应该生成: </p><p> <code>I bought a bag of apples from T shop.</code> </p>规则集3: <p>如果没有转义特殊的正则表达式字符,这将测试正确的替换顺序并可能捕获简单的基于正则表达式的替换例程。 </p> | ||||
|  | ||||
| 对于这段文本: | ||||
|  | ||||
| `I bought a B of As from T S.` | ||||
|  | ||||
| 应该输出: | ||||
|  | ||||
| `I bought a bag of apples from T shop.` | ||||
|  | ||||
| **规则集 3:** | ||||
|  | ||||
| 这条不仅可以用来测试替换顺序是否正确,还可以测试你的代码中对正则表达式的处理是否完备。如果你的代码没有对正则表达式进行正确的转义处理,那在替换的时候就会出现问题。 | ||||
|  | ||||
| <pre># BNF Syntax testing rules | ||||
| A -> apple | ||||
| WWWW -> with | ||||
| @@ -63,77 +84,124 @@ W -> WW | ||||
| S -> .shop | ||||
| T -> the | ||||
| the shop -> my brother | ||||
| a never used -> .terminating rule | ||||
| (终止规则) -> . | ||||
| </pre> | ||||
| <p>示例文本: </p><p> <code>I bought a B of As W my Bgage from T S.</code> </p>  <p>应该生成: </p><p> <code>I bought a bag of apples with my money from T shop.</code> </p>规则集4: <p>这将测试规则扫描的正确顺序,并可能捕获以错误顺序扫描的替换例程。它实现了一般的一元乘法引擎。 (请注意,在此实现中,输入表达式必须放在下划线中。) </p><pre> ##一元乘法引擎,用于测试马尔可夫算法实现 | ||||
| ## Donal Fellows。 | ||||
| 一元加法引擎_ + 1  - > _1 + | ||||
| 1 + 1  - > 11+ | ||||
| 通过将乘法的分裂转换为普通的 | ||||
| addition1! - >!1 | ||||
| ,! - >!+ | ||||
| _! - > _ | ||||
| 通过复制左侧,右侧乘以1 * 1  - > x,@ y进行一元乘法 | ||||
| 1x  - > xX | ||||
| X, - > 1,1 | ||||
| X1  - > 1X | ||||
| _x  - > _X | ||||
| ,x  - >,X | ||||
| y1  - > 1y | ||||
| y_  - > _ | ||||
| apply1 @ 1  - > x,@ y的下一阶段 | ||||
| 1 @ _  - > @_ | ||||
| ,@ _  - >!_ | ||||
| ++  - > + | ||||
| 添加终止清除_1  - > 1 | ||||
| 1 + _  - > 1 | ||||
| _ + _  - > | ||||
| </pre><p>示例文本: </p><p> <code>_1111*11111_</code> </p>  <p>应该生成输出: </p><p> <code>11111111111111111111</code> </p>规则集5: <p>一台简单的<a href='http://en.wikipedia.org/wiki/Turing_machine' title='链接:http://en.wikipedia.org/wiki/Turing_machine'>图灵机</a> , </p><p>实施三态<a href='http://en.wikipedia.org/wiki/Busy_beaver' title='链接:http://en.wikipedia.org/wiki/Busy_beaver'>繁忙的海狸</a> 。 </p><p>磁带由0和1组成,状态为A,B,C和H(对于Halt),并且通过在头部所在的字符之前写入状态字母来指示磁头位置。 </p><p>必须在输入中给出机器操作的初始磁带的所有部分。 </p><p>除了证明Markov算法是Turing-complete之外,它还让我抓住了C ++实现中的一个错误,这个错误没有被前四个规则集捕获。 </p><pre>图灵机:三态繁忙的海狸 | ||||
| 状态A,符号0 =>写1,向右移动,新状态BA0  - > 1B | ||||
| 状态A,符号1 =>写1,向左移动,新状态C0A1  - > C01 | ||||
| 1A1  - > C11 | ||||
| 状态B,符号0 =>写1,向左移动,新状态A0B0  - > A01 | ||||
| 1B0  - > A11 | ||||
| 状态B,符号1 =>写1,向右移动,新状态BB1  - > 1B | ||||
| 状态C,符号0 =>写1,向左移动,新状态B0C0  - > B01 | ||||
|  | ||||
| 对于这段文本: | ||||
|  | ||||
| `I bought a B of As W my Bgage from T S.` | ||||
|  | ||||
| 应该输出: | ||||
|  | ||||
| `I bought a bag of apples with my money from T shop.`  | ||||
|  | ||||
| **规则集 4:** | ||||
|  | ||||
| 这条是用来测试规则扫描的顺序是否正确,并可能捕获以错误顺序扫描的替换例程。这里我们选取了通用的一元乘法引擎(请注意,在此实现中,输入的表达式必须放在两个下划线之间)。 | ||||
|  | ||||
| <pre> ##一元乘法引擎,用于测试马尔可夫算法实现 | ||||
| ### by Donal Fellows | ||||
| # 一元加法引擎 | ||||
| _+1 -> _1+ | ||||
| 1+1 -> 11+ | ||||
| # 将乘法转换为普通加法 | ||||
| 1! -> !1 | ||||
| ,! -> !+ | ||||
| _! -> _ | ||||
| # 一元乘法,左侧为被乘数,右侧为乘数 | ||||
| 1*1 -> x,@y | ||||
| 1x -> xX | ||||
| X, -> 1,1 | ||||
| X1 -> 1X | ||||
| _x -> _X | ||||
| ,x -> ,X | ||||
| y1 -> 1y | ||||
| y_ -> _ | ||||
| # 下一阶段 | ||||
| 1@1 -> x,@y | ||||
| 1@_ -> @_ | ||||
| ,@_ -> !_ | ||||
| ++ -> + | ||||
| # 加法的终止条件 | ||||
| _1 -> 1 | ||||
| 1+_ -> 1 | ||||
| _+_ -> | ||||
| </pre> | ||||
|  | ||||
| 对于这段文本: | ||||
|  | ||||
| `_1111*11111_` | ||||
|  | ||||
| 应该输出: | ||||
|  | ||||
| `11111111111111111111` | ||||
|  | ||||
| **规则集5:** | ||||
|  | ||||
| 一台简单的[图灵机](http://en.wikipedia.org/wiki/Turing_machine)包含三个状态的["忙碌海狸"](http://en.wikipedia.org/wiki/Busy_beaver)。纸带由 0 和 1 组成,状态为 A、B、C 和代表终止(Halt)的 H。通过在字符前写状态字母来的方式来指示读写头的位置。机器运行时需要的初始纸带必须通过输入在一开始全部给出。 | ||||
|  | ||||
| 这一规则集除了可以证明 Markov 算法是图灵完备的,它还帮我找出了使用 C++ 完成此题中的一个错误,而且这个错误没有被前四个规则集抓到。 | ||||
|  | ||||
| <pre># 图灵机:三个状态的"忙碌海狸" | ||||
| # 状态 A,符号 0 => 写入 1,向右移动,新状态 B | ||||
| A0 -> 1B | ||||
| # 状态 A,符号 1 => 写入 1,向左移动,新状态 C | ||||
| 0A1 -> C01 | ||||
| 1A1 -> C11 | ||||
| # 状态 B,符号 0 => 写入 1,向左移动,新状态 A | ||||
| 0B0 -> A01 | ||||
| 1B0 -> A11 | ||||
| # 状态 B,符号 1 => 写入 1,向右移动,新状态 B | ||||
| B1  - > 1B | ||||
| # 状态 C,符号 0 => 写入 1,向左移动,新状态 B | ||||
| 0C0  - > B01 | ||||
| 1C0  - > B11 | ||||
| 状态C,符号1 =>写1,向左移动,停止0C1  - > H01 | ||||
| # 状态 C,符号 1 => 写入 1,向左移动,停止 | ||||
| 0C1  - > H01 | ||||
| 1C1  - > H11 | ||||
| </pre><p>这个规则集应该转向</p><p> <code>000000A000000</code> </p>  <p>成</p><p> <code>00011H1111000</code> </p>   | ||||
| </pre> | ||||
|  | ||||
| 这个规则集应将这段输入: | ||||
|  | ||||
| `000000A000000`  | ||||
|  | ||||
| 转换成: | ||||
|  | ||||
| `00011H1111000` | ||||
|  | ||||
| # --hints-- | ||||
|  | ||||
| `markov`是一个功能。 | ||||
| `markov` 应是一个函数。 | ||||
|  | ||||
| ```js | ||||
| assert(typeof markov === 'function'); | ||||
| ``` | ||||
|  | ||||
| `markov(["A -> apple","B -> bag","S -> shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As from T S.")`应该回复“我从我兄弟那里买了一袋苹果”。 | ||||
| `markov(["A -> apple","B -> bag","S -> shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As from T S.")` 应返回 "I bought a bag of apples from my brother."。 | ||||
|  | ||||
| ```js | ||||
| assert.deepEqual(markov(rules[0], tests[0]), outputs[0]); | ||||
| ``` | ||||
|  | ||||
| `markov(["A -> apple","B -> bag","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As from T S.")`应该回来“我从T商店买了一袋苹果。” | ||||
| `markov(["A -> apple","B -> bag","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As from T S.")` 应返回 "I bought a bag of apples from T shop."。 | ||||
|  | ||||
| ```js | ||||
| assert.deepEqual(markov(rules[1], tests[1]), outputs[1]); | ||||
| ``` | ||||
|  | ||||
| `markov(["A -> apple","WWWW -> with","Bgage -> ->.*","B -> bag","->.* -> money","W -> WW","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As W my Bgage from T S.")`应该返回”我从T商店用我的钱买了一袋苹果。“ | ||||
| `markov(["A -> apple","WWWW -> with","Bgage -> ->.*","B -> bag","->.* -> money","W -> WW","S -> .shop","T -> the","the shop -> my brother","a never used -> .terminating rule"],"I bought a B of As W my Bgage from T S.")` 应返回 "I bought a bag of apples with my money from T shop."。 | ||||
|  | ||||
| ```js | ||||
| assert.deepEqual(markov(rules[2], tests[2]), outputs[2]); | ||||
| ``` | ||||
|  | ||||
| `markov(["_+1 -> _1+","1+1 -> 11+","1! -> !1",",! -> !+","_! -> _","1*1 -> x,@y","1x -> xX","X, -> 1,1","X1 -> 1X","_x -> _X",",x -> ,X","y1 -> 1y","y_ -> _","1@1 -> x,@y","1@_ -> @_",",@_ -> !_","++ -> +","_1 -> 1","1+_ -> 1","_+_ -> "],"_1111*11111_")`应返回”11111111111111111111“。 | ||||
| `markov(["_+1 -> _1+","1+1 -> 11+","1! -> !1",",! -> !+","_! -> _","1*1 -> x,@y","1x -> xX","X, -> 1,1","X1 -> 1X","_x -> _X",",x -> ,X","y1 -> 1y","y_ -> _","1@1 -> x,@y","1@_ -> @_",",@_ -> !_","++ -> +","_1 -> 1","1+_ -> 1","_+_ -> "],"_1111*11111_")` 应返回 "11111111111111111111"。 | ||||
|  | ||||
| ```js | ||||
| assert.deepEqual(markov(rules[3], tests[3]), outputs[3]); | ||||
| ``` | ||||
|  | ||||
| `markov(["A0 -> 1B","0A1 -> C01","1A1 -> C11","0B0 -> A01","1B0 -> A11","B1 -> 1B","0C0 -> B01","1C0 -> B11","0C1 -> H01","1C1 -> H11"],"")`应返回”00011H1111000“。 | ||||
| `markov(["A0 -> 1B","0A1 -> C01","1A1 -> C11","0B0 -> A01","1B0 -> A11","B1 -> 1B","0C0 -> B01","1C0 -> B11","0C1 -> H01","1C1 -> H11"],"")` 应返回 "00011H1111000"。 | ||||
|  | ||||
| ```js | ||||
| assert.deepEqual(markov(rules[4], tests[4]), outputs[4]); | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| --- | ||||
| id: 594810f028c0303b75339ad7 | ||||
| title: Zhang-Suen thinning algorithm | ||||
| title: Zhang-Suen 细化算法 | ||||
| challengeType: 5 | ||||
| forumTopicId: 302347 | ||||
| --- | ||||
|  | ||||
| # --description-- | ||||
|  | ||||
| This is an algorithm used to thin a black and white i.e. one bit per pixel images. For example, with an input image of: | ||||
| 这是一个黑白图像(二值图像)的细化算法。 例如,输入图像如下: | ||||
|  | ||||
| <!-- TODO write fully in markdown> | ||||
| <!-- markdownlint-disable --> | ||||
| @@ -31,7 +31,7 @@ This is an algorithm used to thin a black and white i.e. one bit per pixel image | ||||
|  ########     ####### ######         ############# ###### | ||||
| </pre> | ||||
|  | ||||
| It produces the thinned output: | ||||
| 细化后的输出图像为: | ||||
|  | ||||
| <pre> | ||||
|  | ||||
| @@ -52,9 +52,9 @@ It produces the thinned output: | ||||
|  | ||||
| </pre> | ||||
|  | ||||
| <h2>Algorithm</h2> | ||||
| <h2>算法</h2> | ||||
|  | ||||
| Assume black pixels are one and white pixels zero, and that the input image is a rectangular N by M array of ones and zeroes. The algorithm operates on all black pixels P1 that can have eight neighbours. The neighbours are, in order, arranged as: | ||||
| 假设黑像素点为 1,白像素点为 0;则输入图像可以用一个 N * M 的矩阵(或数组)来表示,其中,矩阵中的元素只能为 0 或 1。这个算法对所有黑像素点 P1 进行操作。每个点 P1 都可以有 8 个相邻的点,分别是: | ||||
|  | ||||
| <table border="3"> | ||||
|   <tr><td style="text-align: center;">P9</td><td style="text-align: center;">P2</td><td style="text-align: center;">P3</td></tr> | ||||
| @@ -62,70 +62,70 @@ Assume black pixels are one and white pixels zero, and that the input image is a | ||||
|   <tr><td style="text-align: center;">P7</td><td style="text-align: center;">P6</td><td style="text-align: center;">P5</td></tr> | ||||
| </table> | ||||
|  | ||||
| Obviously the boundary pixels of the image cannot have the full eight neighbours. | ||||
| 显然,对于图像边框上的像素点,与它们相邻的点的数量是小于 8 的。 | ||||
|  | ||||
| <ul> | ||||
|   <li>Define $A(P1)$ = the number of transitions from white to black, (0 -> 1) in the sequence P2, P3, P4, P5, P6, P7, P8, P9, P2. (Note the extra P2 at the end - it is circular).</li> | ||||
|   <li>Define $B(P1)$ = the number of black pixel neighbours of P1. ( = sum(P2 .. P9) )</li> | ||||
|   <li>令 $A(P1)$ 为需要变为黑点的白点数量,即在 P2, P3, P4, P5, P6, P7, P8, P9, P2 这一序列中,(0 -> 1) 的操作次数(注意:为了表示循环/闭环,我们在序列的结尾特地多加了一个 P2)</li> | ||||
|   <li>令 $B(P1)$ 为与 P1 相邻的点中,黑点的数量(即 sum(P2 .. P9))</li> | ||||
| </ul> | ||||
|  | ||||
| <h3>Step 1:</h3> | ||||
| <h3>步骤一:</h3> | ||||
|  | ||||
| All pixels are tested and pixels satisfying all the following conditions (simultaneously) are just noted at this stage. | ||||
| 选出同时满足以下列出条件的所有像素点: | ||||
|  | ||||
|   <ol> | ||||
|     <li>The pixel is black and has eight neighbours</li> | ||||
|     <li>像素点为黑色,且有 8 个点与之相邻</li> | ||||
|     <li>$2 <= B(P1) <= 6$</li> | ||||
|     <li>$A(P1) = 1$</li> | ||||
|     <li>At least one of <strong>P2, P4 and P6</strong> is white</li> | ||||
|     <li>At least one of <strong>P4, P6 and P8</strong> is white</li> | ||||
|     <li><strong>P2, P4 and P6</strong> 中至少有一个是白点</li> | ||||
|     <li><strong>P4, P6 and P8</strong> 中至少有一个是白点</li> | ||||
|   </ol> | ||||
|  | ||||
| After iterating over the image and collecting all the pixels satisfying all step 1 conditions, all these condition satisfying pixels are set to white. | ||||
| 在对图像进行迭代并选出所有符合这一步所述条件的点后,把这些点都设置为白色。 | ||||
|  | ||||
| <h3>Step 2:</h3> | ||||
| <h3>步骤二:</h3> | ||||
|  | ||||
| All pixels are again tested and pixels satisfying all the following conditions are just noted at this stage. | ||||
| 选出同时满足以下列出条件的所有像素点: | ||||
|  | ||||
|   <ol> | ||||
|     <li>The pixel is black and has eight neighbours</li> | ||||
|     <li>像素点为黑色,且有 8 个点与之相邻</li> | ||||
|     <li>$2 <= B(P1) <= 6$</li> | ||||
|     <li>$A(P1) = 1$</li> | ||||
|     <li>At least one of <strong>P2, P4 and P8</strong> is white</li> | ||||
|     <li>At least one of <strong>P2, P6 and P8</strong> is white</li> | ||||
|     <li><strong>P2, P4 and P6</strong> 中至少有一个是白点</li> | ||||
|     <li><strong>P2, P6 and P8</strong> 中至少有一个是白点</li> | ||||
|   </ol> | ||||
|    | ||||
| After iterating over the image and collecting all the pixels satisfying all step 2 conditions, all these condition satisfying pixels are again set to white. | ||||
| 在对图像进行迭代并选出所有符合这一步所述条件的点后,把这些点都设置为白色。 | ||||
|  | ||||
| <h3>Iteration:</h3> | ||||
| <h3>迭代:</h3> | ||||
|  | ||||
| If any pixels were set in this round of either step 1 or step 2 then all steps are repeated until no image pixels are so changed. | ||||
| 只要在步骤一或步骤二,有黑色点被选出并设置成了白色,则继续重复步骤一和步骤二,直到没有黑色点被选出并更改为止。 | ||||
|  | ||||
| # --instructions-- | ||||
|  | ||||
| Write a routine to perform Zhang-Suen thinning on the provided image matrix. | ||||
| 基于输入图像(以矩阵的形式给出),实现 Zhang-suen 细化算法。 | ||||
|  | ||||
| # --hints-- | ||||
|  | ||||
| `thinImage` should be a function. | ||||
| `thinImage` 应为函数。 | ||||
|  | ||||
| ```js | ||||
| assert.equal(typeof thinImage, 'function'); | ||||
| ``` | ||||
|  | ||||
| `thinImage` should return an array. | ||||
| `thinImage` 应返回数组。 | ||||
|  | ||||
| ```js | ||||
| assert(Array.isArray(result)); | ||||
| ``` | ||||
|  | ||||
| `thinImage` should return an array of strings. | ||||
| `thinImage` 应返回字符串数组。 | ||||
|  | ||||
| ```js | ||||
| assert.equal(typeof result[0], 'string'); | ||||
| ``` | ||||
|  | ||||
| `thinImage` should return an array of strings. | ||||
| `thinImage` 应返回预计的结果。 | ||||
|  | ||||
| ```js | ||||
| assert.deepEqual(result, expected); | ||||
|   | ||||
| @@ -107,7 +107,8 @@ _+1 -> _1+ | ||||
| 1! -> !1 | ||||
| ,! -> !+ | ||||
| _! -> _ | ||||
| # Unary multiplication by duplicating left side, right side times1*1 -> x,@y | ||||
| # Unary multiplication by duplicating left side, right side times | ||||
| 1*1 -> x,@y | ||||
| 1x -> xX | ||||
| X, -> 1,1 | ||||
| X1 -> 1X | ||||
| @@ -115,11 +116,13 @@ _x -> _X | ||||
| ,x -> ,X | ||||
| y1 -> 1y | ||||
| y_ -> _ | ||||
| # Next phase of applying1@1 -> x,@y | ||||
| # Next phase of applying | ||||
| 1@1 -> x,@y | ||||
| 1@_ -> @_ | ||||
| ,@_ -> !_ | ||||
| ++ -> + | ||||
| # Termination cleanup for addition_1 -> 1 | ||||
| # Termination cleanup for addition | ||||
| _1 -> 1 | ||||
| 1+_ -> 1 | ||||
| _+_ -> | ||||
| </pre> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user