【问题标题】:Creating an ORD_MAP with Tupples as Key in SML在 SML 中创建以元组为键的 ORD_MAP
【发布时间】:2017-11-06 08:54:01
【问题描述】:

我正在做一个 SML 练习,我在一个网格中,从单元格 (i,j) 开始,我想转到单元格 (x,y)。为了模拟这一点,每个单元格都被视为一个状态(i,j,move),移动它是如何从前一个单元格到达那里的。然后我写了一个简单的遍历算法(更像是 dfs),它开始搜索状态,直到找到所需的状态。

请注意,对于遍历函数,我使用了一个 Map-Dictionary,它以 State 作为索引来跟踪访问过的 State。

代码:

val startp = (0,0)
val endp = (3,0)
val (N,M) = (4,4)

(*Define the Basic structures tht will be used*)
datatype movement = RIGHT | DOWN | LEFT | UP

type State = int * int * movement 

val firstState = (#1 startp,#2 startp,UP): State

structure STATES_KEY: ORD_KEY = 
  struct
    type ord_key = State
    val compare = fn (s1:State, s2:State) =>
      if (#1 s1 = #1 s2) andalso (#2 s1 = #2 s2)
      then EQUAL
      else if (#1 s1 > #1 s2) then GREATER
      else LESS
  end

structure StatesMap = SplayMapFn(STATES_KEY)

fun convert_ij id = (id div M, id mod N)

fun getNextStates ((i,j,_):State): State list = 
  [ (i,j+1,RIGHT),
    (i+1,j,DOWN),
    (i,j-1,LEFT),
    (i-1,j,UP)]

fun getPrevState ((i,j,move):State): State = 
  case move of 
       RIGHT => (i,j-1,UP)
     | LEFT => (i,j+1,UP)
     | UP => (i+1,j,UP)
     | DOWN => (i-1,j,UP)

(*True -> Invalid State*)
fun checkInvalidState ((i,j,_):State) = 
  if (i < 0 orelse i > N-1 orelse j < 0 orelse j > M-1)
  then true
  else false

fun checkEnd ((i,j,_):State) = 
  if (i = #1 endp andalso j = #2 endp)
  then true
  else false

fun traversal [] visited = visited
  | traversal (h::t) visited = 
  if (checkEnd h) then visited
  else if (checkInvalidState h) then traversal t visited
  else if (StatesMap.find (visited, h) = NONE)
  then 
    let
      val [s1,s2,s3,s4] = getNextStates h
    in
      traversal (s1::s2::s3::s4::t) (StatesMap.insert (visited, h, h))
    end
  else traversal t visited

val it = traversal [firstState] StatesMap.empty

当我运行程序时,它在执行遍历函数时进入了一个无限循环。它来自状态:(1,0)-&gt;(0,0)-&gt;(0,1)-&gt;(0,2)-&gt;(0,3)-&gt;(1,3)-&gt;(2,3)-&gt;(3,3)

从那以后,它继续在(3,3)(3,2) 之间进行。另外,当遍历函数处于 State (3,2) 并且 State (3,3) 存在于其中时,我检查了 Map 结构,这意味着它不应该再次查看它并继续检查其他状态。

究竟是什么不按我认为的方式工作并导致这个循环?

【问题讨论】:

    标签: algorithm structure sml smlnj


    【解决方案1】:

    我认为问题在于您的比较功能已损坏。 编辑: 比如它定义了

    (0, 2) < (0, 1)
    (0, 1) < (0, 2)
    

    违反反对称。但这是排序的必要属性。

    您需要正确的字典顺序:

    fun compare ((x1,y1,_), (x2,y2,_)) =
        case Int.compare (x1, x2) of
          EQUAL => Int.compare (y1, y2)
        | order => order
    

    【讨论】:

      猜你喜欢
      • 2012-08-25
      • 2017-07-05
      • 1970-01-01
      • 2017-04-25
      • 2021-10-28
      • 2012-04-02
      • 2020-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多