Matrix 更新Clojure中较大矩阵中的子矩阵

Matrix 更新Clojure中较大矩阵中的子矩阵,matrix,clojure,Matrix,Clojure,如何通过在特定位置插入较小的子矩阵来更新以嵌套向量表示的大型矩阵 (def submatrix [[1 1] [1 1]]) (def matrix [[0 0 0] [0 0 0] [0 0 0]]) (def pos [1 1]) (defn update-matrix "Returns new matrix with the submatrix inserted at the [x y] pos as the top left position of the submatri

如何通过在特定位置插入较小的子矩阵来更新以嵌套向量表示的大型矩阵

(def submatrix [[1 1] [1 1]])
(def matrix [[0 0 0] [0 0 0] [0 0 0]])
(def pos [1 1])
(defn update-matrix
   "Returns new matrix with the submatrix inserted at the [x y] pos as
    the top left position of the submatrix."
   [matrix submatrix pos]
    ; implementation??
)
所需输出:(格式化为可读性)

我目前的进展:

我可以更新向量中的子向量:

(def v [0 1 2 3 4 5 6])
(def subv ["x" "y" "z"])
(def pos 2)
(concat (take pos v) subv (drop (+ pos (count subv)) v)
; [0 1 "x" "y" "z" 5 6]

但我不知道该从这里走到哪里,也不知道什么可能是最惯用的方式。

这是我的15分钟拍摄:

(defn update-matrix
  "Returns new matrix with the submatrix inserted at the [x y] pos as
  the top left position of the submatrix."
  [matrix submatrix pos]
  (let [[x y] pos
        height (count submatrix)
        width (count (get submatrix 0))]
    (loop [i 0 m matrix]
      (if (< i height)
        (let [item (vec (concat (vec (drop-last width (get matrix x))) (get submatrix i)))]
          (recur (+ 1 i) (assoc m (+ i y) item)))
        m))))
(定义更新矩阵
“返回在[x y]位置插入子矩阵的新矩阵,如下所示:
子矩阵的左上角位置。“
[矩阵子矩阵位置]
(让[[x y]位置
高度(计数子矩阵)
宽度(计数(获取子矩阵0))]
(循环[i 0 m矩阵]
(如果(

如果不起作用,请告诉我。

这是我的15分钟拍摄时间。拍摄时间:

(defn update-matrix
  "Returns new matrix with the submatrix inserted at the [x y] pos as
  the top left position of the submatrix."
  [matrix submatrix pos]
  (let [[x y] pos
        height (count submatrix)
        width (count (get submatrix 0))]
    (loop [i 0 m matrix]
      (if (< i height)
        (let [item (vec (concat (vec (drop-last width (get matrix x))) (get submatrix i)))]
          (recur (+ 1 i) (assoc m (+ i y) item)))
        m))))
(定义更新矩阵
“返回在[x y]位置插入子矩阵的新矩阵,如下所示:
子矩阵的左上角位置。“
[矩阵子矩阵位置]
(让[[x y]位置
高度(计数子矩阵)
宽度(计数(获取子矩阵0))]
(循环[i 0 m矩阵]
(如果(

如果不起作用,请告诉我。

您可以减少一系列更新坐标,在每一步将一项从子矩阵复制到较大矩阵中的适当位置:

user> (defn update-matrix [matrix submatrix [y x]]
        (reduce (fn [m [row col]]
                  (assoc-in m [(+ row y) (+ col x)] 
                            (get-in submatrix [row col])))
                matrix
                (for [y (range (count submatrix))
                      x (range (count (first submatrix)))]
                  [y x])))
#'user/update-matrix
user> (update-matrix [[0 0 0] [0 0 0] [0 0 0]] [[1 1] [1 1]] [1 1])
[[0 0 0] [0 1 1] [0 1 1]]

您可以通过一系列更新坐标进行缩减,在每一步将子矩阵中的一项复制到较大矩阵中的适当位置:

user> (defn update-matrix [matrix submatrix [y x]]
        (reduce (fn [m [row col]]
                  (assoc-in m [(+ row y) (+ col x)] 
                            (get-in submatrix [row col])))
                matrix
                (for [y (range (count submatrix))
                      x (range (count (first submatrix)))]
                  [y x])))
#'user/update-matrix
user> (update-matrix [[0 0 0] [0 0 0] [0 0 0]] [[1 1] [1 1]] [1 1])
[[0 0 0] [0 1 1] [0 1 1]]

做对了

我们可以将所需的函数定义为

(defn update-submatrix [m sub-m [x y]]
  (replace-subvec
    m
    (map (fn [l r] (replace-subvec l r y)) (subvec m x) sub-m)
    x))
。。。其中
(替换子向量v s start)
将索引
start
中的向量
v
的元素替换为序列
s
,只要
s
持续。比如说,

(replace-subvec (vec (range 10)) (range 3) 5)
; [0 1 2 3 4 0 1 2 8 9]
一个清晰但缓慢的实现是必要的

(defn replace-subvec [v s start]
  (vec (concat (subvec v 0 start) s (subvec v (+ start (count s))))))
。。。举个问题中的例子

(def submatrix [[1 1] [1 1]])
(def matrix [[0 0 0] [0 0 0] [0 0 0]])
(def pos [1 1])

(update-submatrix matrix submatrix pos)
; [[0 0 0] [0 1 1] [0 1 1]]
加快速度

加快
更新子矩阵
的关键是加快
替换子向量

我们可以通过两种方式做到这一点:

  • 通过循环递增的方式运行已更改的元素,然后
  • 在函数中使用临时集合
这给了我们

(defn replace-subvec [v s start]
  (loop [v (transient v), s s, i start]
    (if (empty? s)
      (persistent! v)
      (recur (assoc! v i (first s)) (rest s) (inc i)))))

效果是一样的。

正确处理

我们可以将所需的函数定义为

(defn update-submatrix [m sub-m [x y]]
  (replace-subvec
    m
    (map (fn [l r] (replace-subvec l r y)) (subvec m x) sub-m)
    x))
。。。其中
(替换子向量v s start)
将索引
start
中的向量
v
的元素替换为序列
s
,只要
s
持续。比如说,

(replace-subvec (vec (range 10)) (range 3) 5)
; [0 1 2 3 4 0 1 2 8 9]
一个清晰但缓慢的实现是必要的

(defn replace-subvec [v s start]
  (vec (concat (subvec v 0 start) s (subvec v (+ start (count s))))))
。。。举个问题中的例子

(def submatrix [[1 1] [1 1]])
(def matrix [[0 0 0] [0 0 0] [0 0 0]])
(def pos [1 1])

(update-submatrix matrix submatrix pos)
; [[0 0 0] [0 1 1] [0 1 1]]
加快速度

加快
更新子矩阵
的关键是加快
替换子向量

我们可以通过两种方式做到这一点:

  • 通过循环递增的方式运行已更改的元素,然后
  • 在函数中使用临时集合
这给了我们

(defn replace-subvec [v s start]
  (loop [v (transient v), s s, i start]
    (if (empty? s)
      (persistent! v)
      (recur (assoc! v i (first s)) (rest s) (inc i)))))

效果是一样的。

谢谢你给我介绍瞬变和一个很好的解释。如果我没弄错的话,它不应该是
assoc在瞬态上运行?此外,我相信您缺少关闭
assoc
的参数。感谢您向我介绍瞬变和一个很好的解释。如果我没弄错的话,它不应该是
assoc在瞬态上运行?此外,我认为您缺少关闭
assoc
的参数。