Loops 如何在继续循环时将新值绑定到Racket中的变量

Loops 如何在继续循环时将新值绑定到Racket中的变量,loops,functional-programming,scheme,racket,variable-assignment,Loops,Functional Programming,Scheme,Racket,Variable Assignment,我有一个2D数字列表,以某种方式表示表中的条目,例如: '((0 2 3) (4 0 0) (7 0 9)) 目标是以一种方式标记零,即每行和每列只有一个标记为0。因此,在本例中,标记的零将是(第1列第1行)(第2列第3行)(第3列第2行)。这是第一步 我试图在Scheme中编写这段伪代码,但在不重新启动循环的情况下修改变量时遇到问题。我不知道如何更改一个变量并从该行继续 for r in rows first := true for c in cols if A(r

我有一个2D数字列表,以某种方式表示表中的条目,例如:

'((0 2 3)
  (4 0 0)
  (7 0 9))
目标是以一种方式标记零,即每行和每列只有一个标记为0。因此,在本例中,标记的零将是
(第1列第1行)(第2列第3行)(第3列第2行)
。这是第一步

我试图在Scheme中编写这段伪代码,但在不重新启动循环的情况下修改变量时遇到问题。我不知道如何更改一个变量并从该行继续

for r in rows
  first := true
  for c in cols
     if A(r, c) == 0
        if first
           A(r, c) is assigned
           first := false
           for rr in rows
              if A(rr, c) == 0 and r != rr
                 A(rr, c) is crossed out
        else
           A(r, c) is crossed out
例如,将
false
赋值给
first
,或交叉/赋值
A(r,c)
。怎么做


我曾尝试对每个循环使用命名的
let
,但我找不到另一种方法,在不重新启动
let
循环的情况下将新值绑定到变量。

我对您试图做的事情有点困惑,但我认为这是这样的:给定一些矩阵a,返回最大可能的“赋值”(r,c),其中,对于每个赋值(r,c),A(r,c)=0,并且每个r或c在集合中出现不超过一次。我将“完整”的赋值集定义为一组赋值,其中包括每行的赋值(显然,对于任何行多于列的矩阵,都不存在这样的赋值集)

若这是正确的,那个么这里有一种在球拍中完成的方法,它不使用任何赋值

首先,这里有一个小模块,可以让你构造数值矩阵:毫无疑问,Racket中包含了一个更具工业实力的数值矩阵版本,但我已经有了这个,我很懒。矩阵表示为函数

  • 无参数调用时,返回th矩阵的维数
  • 当使用两个参数调用时,返回该索引处的元素
  • (当使用单个参数调用时,执行Common Lisp的
    行主aref
    ,用于调试)
请注意,矩阵是不可变的

(模块矩阵球拍
无意识的数值矩阵
提供(承包)
(制作矩阵)
(->(列表编号?)
(案例->
(->(值自然数/c自然数/c))
(->自然数/c数?)
(->自然数/c自然数/c自然数?));(-))
(定义(生成矩阵行)
(让*([r(长度行)]
[c(如果(>R0)
(用于/折叠([cl(长度(第一行))]))
([col(在列表(其余行))中])
(如果(和cl(=cl(长度col))cl#f))
0)]
[s(*r c)])
(c)除非
(错误“使矩阵“非矩形”))
(let([v(表示*/vector([row(在列表行中)]
[e(列表行)])
e) 】)
(lambda案)
矩阵是一个函数,它。。。
[()
;;…不带参数返回其维度。。。
(r c)]
[(索引)
。。。
(当(>=索引s)
(错误“矩阵”索引超出范围)
(矢量参考v索引)]
[(第列)
。
(当(或(>=第r行)(>=第c列))
(错误“矩阵”索引超出范围)
(向量参考v(+(*行c)列))]()()))
好吧,假设我们可以写一个函数来计算赋值。几乎所有困难的部分(您可能不需要)都是,如果没有完整的赋值集(例如,如果矩阵有一行没有零),则返回它能找到的最大集。另一方面,对于具有许多可能赋值集的矩阵,下面的函数只返回一个

首先,我想要一些表示作业表的方法:我需要能够询问作业是否已经在表中,以及表有多大,并使用新作业扩展它,返回一组新作业。如果这些操作中的大多数都需要近似恒定的时间,这是很好的,但它们不必这样做。我还希望能够将一个工作分配表转换为按行排序的
(行-列)
列表

这是根据Racket的字典接口实现的:

(定义空分配’())
(定义分配计数dict计数)
(定义任务是否有col?dict是否有key?)
(定义(将指定扩展到列行)
;;返回一组新的赋值,该赋值按列和行扩展
(何时(作业有col?a col)
(添加现有分配时出现错误“扩展分配”))
(如果(空?a)
(hasheqv列)
(dict设置列)))
(定义(工作分配->列出工作分配)
(排序(dict映射分配(λ(列列列)(列列列列列列列列)))
<#:钥匙车)
最后,考虑到所有这些,这里有一个计算赋值的函数。这实际上有一个很大的技巧,即当列上的循环(内部循环)找到一个赋值时,它使用新赋值调用行循环,并添加一个restart,这只是一个可以调用的函数,用于从该列和行重新启动搜索

此函数将计算一组完整的赋值或失败:如果没有完整的赋值集,则不会返回“最佳”赋值集

(定义(分配m)
;计算m的一组赋值,或返回#f
(let值([(行列)(m)])
(让行循环([行0]
[作业-空作业]
[重新启动'()])
(如果(=行)
我们已经走到了尽头
(cond[(=(分配计数分配)行)
找到足够的任务,我们就完成了
(作业->列出作业)]
[(非(空?重新启动))
还不够