在这个答案中,我们将写 puzzle 来像这样工作 -
const q =
0
puzzle
( q
, [ 1, 2, 0, 0, 3, 4, 0, 1 ]
, printf (`${q} appeared %s times. The result is %s`)
)
// 0 appeared 3 times. The result is 3,0,7,0,1
puzzle
( q
, [ 1, 2, 0, 0, 3, 4, 0, 0, 0, 5, 6, 7, 8, 0 ]
, printf (`${q} appeared %s times. The result is %s`)
)
// 0 appeared 6 times. The result is 3,0,7,0,26,0
puzzle
( 5
, [ 1, 2, 0, 0, 3, 4, 0, 0, 0, 5, 6, 7, 8, 0 ]
, printf (`5 appeared %s times. The result is %s`)
)
// 5 appeared 1 times. The result is 10,5,21
我可以分享这个,因为它可以教给你很多东西,但你的老师不太可能接受;不是因为它是一个糟糕的程序,而是初学者不可能自己编写它。
这个程序的独特之处在于它同时完成所有 3 个步骤,只使用一次通过您的输入数组 -
const None =
Symbol ('None')
const puzzle = (query, [ a = None, b = None, ...rest ], then) =>
a === None # 1
? then (0, [])
: b === None # 2
? then
( Number (query === a)
, [ a ]
)
: query === a && query === b # 3
? puzzle
( query
, [ b, ...rest ]
, (count, result) =>
then
( count + 1
, result
)
)
: query !== a && query !== b # 4
? puzzle
( query
, [ a + b, ...rest ]
, then
)
: puzzle # 5
( query
, [ b, ...rest ]
, (count, result) =>
then
( count + Number (query === a)
, [ a, ...result ]
)
)
puzzle 被定义为使用mathematical induction 的递归函数,我们在其中推断我们以特定方式处理的值。请参考上面编号的 cmets,我们将其分解如下:
(base) 当我们没有a时,表示输入是一个空数组;没有什么可以计算,没有要加在一起的值,没有要折叠的重复值。在这种情况下,返回 empty 结果:0 表示计数,[] 表示输出数组。
(inductive: a is not none) 当我们有一个a 但没有b,这意味着我们只剩下一项了; singleton 数组。在这里,我们不能将两个值相加或折叠重复值,因为我们只有 一个 值。在这种情况下,返回 singleton 结果:Number (query === a) 用于计数,它将布尔值转换为数字,以及 singleton 输出数组,[ a ]
(归纳:a 不是 none,b is not none) 当我们有一个 a 和一个 b 时,这意味着我们有足够的值来开始处理我们函数的更复杂的操作。我不想添加与查询匹配的数字,也不想在结果中添加a 如果它是重复的,所以我必须先检查一下。当查询同时匹配a 和 b 时,已找到重复项。在这种情况下,请在没有a 的情况下重复拼图。当我们得到较小拼图的结果时,我们使用count + 1 增加计数,因为我们的查询匹配a。此代码分支处理重复元素的删除,因此没有新内容可添加到输出数组result。
(归纳:a 不是 none,b 不是 none,query 不匹配两者) 我们有一个 a 和一个 b 和查询不匹配两者。如果它匹配都不匹配,那么我们知道我们可以将a 和b 加在一起。在这种情况下,用a + b 重复这个谜题。由于查询也不匹配,我们知道没有要更新的计数。输出数组也没有改变,因为我们创建的新数字可能会在出现在输出之前被添加到更多相邻的元素中。因为count和result在这个代码分支中没有变化,所以直接通过then。
(归纳:a 不是 none,b 不是 none,query 匹配 a 或 b) 我们有一个 a 和b 并且我们知道查询匹配一个或另一个。哪一个匹配并不重要。无论哪种方式,这些值都不是重复的,不应被删除,也不能将这些值相加。在这种情况下,使用b 重复拼图,如果a 匹配查询,则增加计数,并将a 添加到结果中。这是将值插入输出数组的唯一代码分支。
printf 为演示目的定义为 -
const printf = f =>
console.log .bind (console, f)
展开下面的sn-p,在自己的浏览器中验证结果-
const printf = f =>
console.log .bind (console, f)
const None =
Symbol ('None')
const puzzle = (query, [ a = None, b = None, ...rest ], then) =>
a === None
? then (0, [])
: b === None
? then
( Number (query === a)
, [ a ]
)
: query === a && query === b
? puzzle
( query
, [ b, ...rest ]
, (count, result) =>
then (count + 1, result)
)
: query !== a && query !== b
? puzzle
( query
, [ a + b, ...rest ]
, then
)
: puzzle
( query
, [ b, ...rest ]
, (count, result) =>
then
( count + Number (query === a)
, [ a, ...result ]
)
)
const q =
0
puzzle
( q
, [ 1, 2, 0, 0, 3, 4, 0, 1 ]
, printf (`${q} appeared %s times. The result is %s`)
)
// 0 appeared 3 times. The result is 3,0,7,0,1
puzzle
( q
, [ 1, 2, 0, 0, 3, 4, 0, 0, 0, 5, 6, 7, 8, 0 ]
, printf (`${q} appeared %s times. The result is %s`)
)
// 0 appeared 6 times. The result is 3,0,7,0,26,0
puzzle
( 5
, [ 1, 2, 0, 0, 3, 4, 0, 0, 0, 5, 6, 7, 8, 0 ]
, printf (`5 appeared %s times. The result is %s`)
)
// 5 appeared 1 times. The result is 10,5,21