- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在为这个程序生成正确的输出时遇到了一些问题。我的输出几乎是正确的,但缺少一些步骤。我的代码如下:
(defun kt (x y m n) ;set the board
(setq totalmoves (* m n)) ;find the total moves
(setq steps 1) ;count steps
(setq lst (list (list x y))) ;list visited with initial points
(findPath x y totalmoves steps m n lst) ;start tour with initial points
)
(defun findPath (x y totalMoves steps m n lst)
(cond
((null lst) NIL)
((= steps totalMoves) lst) ;if steps equals than total moves, then solution is complete
;try to solve the rest recursively
;1- down and right
((canMove (+ x 2) (+ y 1) m n lst)
(findPath (+ x 2) (+ y 1) totalMoves (+ steps 1) m n (appendList (+ x 2) (+ y 1) lst))
)
;2- right and down
((canMove (+ x 1) (+ y 2) m n lst)
(findPath (+ x 1) (+ y 2) totalMoves (+ steps 1) m n (appendList (+ x 1) (+ y 2) lst))
)
;3- right ups
((canMove (- x 1) (+ y 2) m n lst)
(findPath (- x 1) (+ y 2) totalMoves (+ steps 1) m n (appendList(- x 1) (+ y 2) lst))
)
;4- up and right
((canMove(- x 2) (+ y 1) m n lst)
(findPath(- x 2) (+ y 1) totalMoves (+ steps 1) m n (appendList(- x 2) (+ y 1) lst))
)
;5 - up and left
((canMove(- x 2) (- y 1) m n lst)
(findPath(- x 2) (- y 1) totalMoves (+ steps 1) m n (appendList(- x 2) (- y 1) lst))
)
;6- left and up
((canMove(- x 1) (- y 2) m n lst)
(findPath(- x 1) (- y 2) totalMoves (+ steps 1) m n (appendList(- x 1) (- y 2) lst))
)
;7- left and down
((canMove(+ x 1) (- y 2) m n lst)
(findPath(+ x 1) (- y 2) totalMoves (+ steps 1) m n (appendList(+ x 1) (- y 2) lst))
)
;8- down and left
((canMove(+ x 2) (- y 1) m n lst)
(findPath(+ x 2) (- y 1) totalMoves (+ steps 1) m n (appendList(+ x 2) (- y 1) lst))
)
(t
(findPath (car(car(reverse lst))) (car(cdr(car(reverse lst)))) totalMoves steps m n (reverse(cdr (reverse lst))))
)
)
)
(defun appendList (x y lst)
(setq lst (reverse(append (list (list x y)) (reverse lst))))
)
(defun check-visited (x y lst)
(cond
((null lst) 1) ;if nth else to check in list
((equal (list x y) (car lst)) NIL) ;check if curr is visited
((check-visited x y (cdr lst))) ;recurse
)
)
(defun canMove (x y m n lst)
(if (and (<= 1 x) ;for the correct state, all conditions below must be met
(<= x m) ;height is more than or equal to x
(<= 1 y)
(<= y n) ;width is more than or equal to y
(equal (check-visited x y lst) 1)
)
1 NIL ;if all above conds are true, return true else return nil
)
)
测试代码为
kt 1 1 5 5
输出是((1 1) (3 2) (5 3) (4 5) (2 4) (1 2) (3 3) (5 4) (3 5) (1 4) (2 2) (4 3) (5 5) (3 4) (1 5) (2 3) (4 4) (2 5) (1 3) (2 1) (4 2))
这里列出了 21 个步骤,但应该有 25 个。
最佳答案
你的方法是不正确的,因为函数 findPath
并没有尝试在特定位置的所有可能的移动,但是,使用 cond
,只尝试 第一个 可能的移动(在 cond
中,执行第一个非 nil
分支并通过返回对应的值终止语句 findPath
称呼)。因此,您的函数仅产生没有回溯的最长行程,正好是 21 步。
为了得到正确的解决方案,您必须尝试所有 可能的移动,返回第一个通过对 findPath
的递归调用产生正确的移动移动次数。在 Common Lisp 中,这可以通过使用 or
和 and
运算符来完成:
or
,有n个操作数,返回第一个不为nil
的操作数的值,如果存在,否则返回nil
:所以如果我们安排放入或
所有findPath
的递归调用,如果其中一个返回正确的最终值或
表达式终止返回该值;
and
返回 nil
如果它的任何操作数是 nil
,否则,如果它们都不是 nil
,它返回最后一个操作数的值。所以我们可以通过首先检查移动是否可能来使用它,如果是,则通过递归调用 findPath
来执行移动。如果调用返回 nil
,则该移动没有用,否则我们找到了正确的路线。
这是新功能:
(defun findPath (x y totalMoves steps m n lst)
(if (= steps totalMoves)
lst ; if the steps are equal to total moves, then a solution is found
; else try recursively all the possible moves from x y
; 1- down and right
(or (and (canMove (+ x 2) (+ y 1) m n lst)
(findPath (+ x 2) (+ y 1) totalMoves (+ steps 1) m n (appendList (+ x 2) (+ y 1) lst)))
; 2- right and down
(and (canMove (+ x 1) (+ y 2) m n lst)
(findPath (+ x 1) (+ y 2) totalMoves (+ steps 1) m n (appendList (+ x 1) (+ y 2) lst)))
; 3- right ups
(and (canMove (- x 1) (+ y 2) m n lst)
(findPath (- x 1) (+ y 2) totalMoves (+ steps 1) m n (appendList (- x 1) (+ y 2) lst)))
; 4- up and right
(and (canMove (- x 2) (+ y 1) m n lst)
(findPath (- x 2) (+ y 1) totalMoves (+ steps 1) m n (appendList (- x 2) (+ y 1) lst)))
; 5 - up and left
(and (canMove (- x 2) (- y 1) m n lst)
(findPath (- x 2) (- y 1) totalMoves (+ steps 1) m n (appendList (- x 2) (- y 1) lst)))
; 6- left and up
(and (canMove (- x 1) (- y 2) m n lst)
(findPath (- x 1) (- y 2) totalMoves (+ steps 1) m n (appendList (- x 1) (- y 2) lst)))
; 7- left and down
(and (canMove (+ x 1) (- y 2) m n lst)
(findPath (+ x 1) (- y 2) totalMoves (+ steps 1) m n (appendList (+ x 1) (- y 2) lst)))
; 8- down and left
(and (canMove (+ x 2) (- y 1) m n lst)
(findPath (+ x 2) (- y 1) totalMoves (+ steps 1) m n (appendList (+ x 2) (- y 1) lst))))))
最后,关于代码的一些注释。
不要使用 setq
来初始化之前未声明的变量
let
可以用来声明和初始化局部变量,所以函数kt
可以这样定义:
(defun kt (x y m n) ; set the board
(let ((totalmoves (* m n)) ; find the total moves
(steps 1) ; count steps
(lst (list (list x y)))) ; list visited with initial points
(findPath x y totalmoves steps m n lst))) ; start tour with initial points
尽量保持代码简单
函数 appendList
是通过将一个单元素列表追加到另一个列表的反面,然后反转结果来定义的。这相当于简单地将第一个列表附加到第二个列表,即:
(defun appendList (x y lst)
(append lst (list (list x y))))
使用 generalized booleans简化条件
例如,函数 check-visited
和 canMove
可以集成到一个更简单的函数中:
(defun canMove (x y m n lst)
(and (<= 1 x m) ;for the correct state, all conditions below must be met
(<= 1 y n)
(not (member (list x y) lst :test 'equal))))
尝试分解您的代码,或者在不必要时不要重复类似的代码
findPath
函数有很多重复,可以使用 loop
消除。 (thereis
相当于 loop
中的 or
):
(defun findPath (x y totalMoves steps m n lst)
(if (= steps totalMoves)
lst
(loop for (x-inc y-inc) in '((+2 +1) (+1 +2) (-1 +2) (-2 +1) (-2 -1) (-1 -2) (+1 -2) (+2 -1))
for x1 = (+ x x-inc)
for y1 = (+ y y-inc)
thereis (and (canMove x1 y1 m n lst)
(findPath x1 y1 totalMoves (1+ steps) m n (appendList x1 y1 lst))))))
使用所用语言的典型约定
在 Common Lisp 中,避免了驼峰命名法,更喜欢用破折号分隔的名称和动词的经典表示法,比如 find-path
而不是 findPath
,或者 can-move
而不是 canMove
等
关于lisp - 骑士之旅回溯 Lisp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35584216/
在我的类里面,我学习了 Prolog 回溯算法和 Rete forprop 算法,但我也被告知 Rete 可用于进行反向传播。 这是如何运作的?它在哪些方面与 Prolog 回溯相似/不同? 例如,这
两个 friend P1 和 P2 向共同的 friend P3 发送相同的消息 M。 然而由于一些网络损坏,P3 一次只能接收一个字符不知道接收到的字符是属于 P1 还是 P2。 此外,P3 可能会
我最近发了几个理解递归和回溯的问题,我觉得我现在得到了一些东西,并尝试编写一个测试,我确实解决了数独问题,但是当我以另一种格式编写代码时,代码卡了一会儿,返回False,说明这个问题无解。 grid
有人可以指导我或解释如何在 LISP 中执行回溯吗?任何示例或链接将不胜感激。我确实尝试过谷歌,但是他们都没有足够简单的例子让我理解。 谢谢 最佳答案 典型的方法是将不可变状态向下传递到调用堆栈,辅助
我正在使用 apache 2.2.14 运行 Backtrack 5 R2 (ubuntu) 的完全库存安装。我尝试运行一个简单的 index.html 文件,其中包含一些 javascript 代码
如何在 Javascript 中获取回溯? 理想的特征: 入口函数名称,或匿名函数的一些有意义的标识符, 每个级别的参数列表, 行号。 这可以用标准的 ECMAScript 完成吗? 如果没有,是否可
本文首发公众号:小码A梦 回溯算法是一种常见的算法,常见用于解决排列组合、排列问题、搜索问题等算法,在一个搜索空间中寻找所有的可能的解。通过向分支不断尝试获取所有的解,然后找到合适的
Python 是否支持为每个异常/引发/断言显示相同的自定义错误消息(无论代码在哪里中断)? 我目前对它的破解使用了一个装饰器。我有一个函数main它显示回溯很好,但我希望它也打印my_var (在函
输入: 3,4,8,7,3 5,S,7,2,3, 8,5,5,8,10 9,3,3,8,7 6,10,3,G,1 目标是找到从起点(S)到目标(G)的最佳路径。 我们可以向上、向下、向左、向右移动。
我想匹配一个包含“json”(出现超过 2 次)且两个“json”之间没有字符串“from”的字符串。 For example(what I want the string match or not)
我正在尝试使用回溯方法找到熄灯游戏的解决方案。我无法理解此过程的算法。我的方法是枚举从 0 到 2n2 - 1 的所有整数,并将每个整数转换为具有 n*n 位的二进制数。然后,将其分成n2个二进制数字
所以我正在阅读这本书《服从测试山羊》,在学习 Python 时我在第六章中遇到了一个问题。它说我应该能够运行我们在本章和前一章中设置的功能测试,没有错误;但是,我不断收到我不知道如何修复的回溯。 Tr
我需要一些关于 Android 日志文件反混淆的帮助。 问题是如果我有这样的异常: ... 10-16 10:03:10.488: E/AndroidRuntime(25723): Cau
我有一个看起来像这样的表: here | there | -------+-------+ {1,1} | {1,1} | {1,1} | {2,1} | {1,1} | {1,2} |
我写了一小段代码,它应该接受一个字符数组并让它看起来像计算机正在输入文本。很简单,对吧?但是当我运行它时,Terminal 告诉我: *** stack smashing detected ***:
Python 中的堆栈跟踪显示文件路径。有什么方法可以让它们显示完全限定的函数名称吗? 例子: class Foo(object): def bar(self): raise
我决定深入学习回溯的概念,我有以下任务: 给定N个投资者,M个城市,N×M个投资者偏好矩阵P(P[i,j]=1,当第i个投资者希望在第j个城市建矿池;P[i, j] = 0 那么他是中立的,当 P[i
设 E - 图 G 中所有边的集合问题是从G中找到顶点的最小子集S,它满足条件:S = E 中每个顶点的所有出边的总和 换句话说:边是街道,我们可以在顶点上放置路灯。如果我们在一个顶点上放置一盏路灯—
我正在尝试做这个我在查找面试问题时遇到的问题。我们被问及将 r 个硬币放置在 n*m 网格上的方法数量,使得每行和每列至少包含一个硬币。 我想到了一个回溯解决方案,按行主要顺序处理网格中的每个单元格,
我使用 DexGuard混淆。我有来自崩溃日志和映射文件的堆栈跟踪。当我运行 retrace.bat 并为其提供堆栈跟踪和映射文件时,输出仍然是混淆格式。 最佳答案 您是否在使用 ProGuard 的
我是一名优秀的程序员,十分优秀!