Scala字符串首字符模式匹配问题求助(Advent of Code练习)
解决Scala中字符串首字符模式匹配的递归问题
我明白你想用Scala实现类似Haskell的模式匹配来处理Advent of Code的问题,这个错误的核心是类型不匹配,咱们一步步解决它:
错误原因拆解
你看到的错误提示constructor cannot be instantiated to expected type; found : scala.collection.immutable.::[B] required: Array[Char],本质是:
::是Scala中List特有的构造函数,用来匹配非空列表的头和尾(比如head :: tail)。- 你可能把字符串转成了
Array[Char],或者直接用了String类型,这两种都不支持::模式匹配。 - 另外,你写的
"^"是字符串常量,但列表里的元素是Char类型,应该用单引号的'^'。
修正后的代码方案
首先,我们需要把输入字符串转换成List[Char](因为List天生支持模式匹配),然后调整匹配逻辑:
假设你的Coord类是类似这样的(包含方向移动方法):
case class Coord(x: Int, y: Int) { def up: Coord = copy(y = y + 1) def down: Coord = copy(y = y - 1) def left: Coord = copy(x = x - 1) def right: Coord = copy(x = x + 1) }
然后修改递归函数:
def part1(visited: Set[Coord], current: Coord, directions: List[Char]): Set[Coord] = directions match { // 匹配非空列表的头是'^',递归处理剩余尾列表 case '^' :: tail => part1(visited + current, current.up, tail) case 'v' :: tail => part1(visited + current, current.down, tail) case '<' :: tail => part1(visited + current, current.left, tail) case '>' :: tail => part1(visited + current, current.right, tail) // 空列表时,把当前位置加入已访问集合后返回 case Nil => visited + current }
调用方式
当你有输入字符串时,只需要把它转成List再传入:
val input = "^>v<" // 示例输入 val initialCoord = Coord(0, 0) val result = part1(Set(initialCoord), initialCoord, input.toList)
优化建议(可选)
为了让函数调用更简洁,可以把递归逻辑封装成内部辅助函数,对外只暴露接收字符串的接口:
def part1(directions: String): Set[Coord] = { case class Coord(x: Int, y: Int) { def up: Coord = copy(y = y + 1) def down: Coord = copy(y = y - 1) def left: Coord = copy(x = x - 1) def right: Coord = copy(x = x + 1) } def helper(visited: Set[Coord], current: Coord, remaining: List[Char]): Set[Coord] = remaining match { case '^' :: tail => helper(visited + current, current.up, tail) case 'v' :: tail => helper(visited + current, current.down, tail) case '<' :: tail => helper(visited + current, current.left, tail) case '>' :: tail => helper(visited + current, current.right, tail) case Nil => visited + current } helper(Set(Coord(0, 0)), Coord(0, 0), directions.toList) } // 调用示例 println(part1("^>v<").size) // 输出 4
这样你只需要直接传入字符串,不用手动处理List转换和初始坐标,更符合Scala的简洁风格。
内容的提问来源于stack exchange,提问作者JoshOrndorff
相关产品推荐
相关产品推荐

