Матрица (массивы) в Lua — поменять местами строки и применить операцию строки

#arrays #matrix #lua #row #operation

#массивы #матрица #lua #строка #операция

Вопрос:

У меня есть этот код

 --[[

Gaussian Elimination in Lua

--]]

-- print matrix
function printmatrix(m)
   for r=1,#m do
      for c=1,#m[r] do
         io.write(m[r][c])
         if c < #m[r] then io.write(", ") end
      end
      print() -- print new line
   end
end

-- read matrix in CSV format
function readcsv()
   local m = {}
   while true do
      local line = io.read("l") -- read line not including the end of line character
      if line==nil or line=="" then break end -- blank line or bad input ends matrix
      local row, index = {}, 0
      -- the next line is tricky and goes over all entries in the row
      for w in string.gmatch(line,"([^,]*),?") do
     local v = tonumber(w) -- convert entry to a number
     index = index 1
     if v==nil then
        row[index] = 0 -- default value if we coudn't read the number
     else
        row[index] = v -- if number is valid
     end
      end
      m[ #m 1 ] = row
   end
   return m
end

-- determine the size of m and check it is rectangular
function dim(m)
   local rows = #m -- number of rows
   local cols = 0  -- number of columns
   if rows > 0 then cols = #m[1] end
   -- check that matrix is rectangular
   for i=2,rows do
      if cols ~= #m[i] then error("not rectangular!") end
   end
   return rows, cols
end

-- if m[r][c] is zero swap row r with some row i>r to make m[r][c] nonzero, if possible
function swap(m,r,c)
   local nrows, ncols = dim(m)
   if r<=0 or r>nrows or c<=0 or c>ncols then error("position out of range") end
   if m[r][c] ~= 0 then
      -- nothing to do
      return
   end
   -- find a suitable row
   local i=r 1
   while i <= nrows do
      if m[i][c] ~= 0 then break end
      i = i 1
   end
   if i <= nrows then
      -- swap rows i,r
      -- DO IT!
   end
end

-- if m[r][c] is nonzero apply row operations to make each m[i][c]==0 for i>r
function clear(m,r,c)
   local nrows, ncols = dim(m)
   if r<=0 or r>nrows or c<=0 or c>ncols then error("position out of range") end
   if m[r][c] == 0 then
      -- nothing to do
      return
   end
   for i=r 1,nrows do
      local f = m[i][c] / m[r][c] do
      -- apply row_i = row_i - f*row_r
      -- DO IT!**
   end
   end
end

-- apply Gaussian elimination to m to get it into echelon form
function echelon(m)
   local nrows, ncols = dim(m)
   local r,c = 1,1 -- current position
   while r<=nrows and c<=ncols do
      -- try to get a nonzero value at this position
      swap(m,r,c)
      if m[r][c] == 0 then
     -- can't, so move right
     c = c 1
      else
     clear(m,r,c)
     -- done, so move diagonally
     r = r 1
     c = c 1
      end
   end
end

m = readcsv()
print("original:")
printmatrix(m)
echelon(m)
print("echelon form:")
printmatrix(m)
  

Я надеялся, что кто-нибудь сможет уточнить, как писать код (там, где написано --DO IT! в Lua, я довольно новичок в этом, спасибо

Для некоторого контекста я просто экспериментирую с устранением Гаусса, чтобы попытаться ускорить мою работу с помощью этого конкретного метода вычисления эшелонной формы — я не слишком беспокоюсь о том, чтобы иметь 1 в качестве первого ненулевого элемента

Он должен вернуть это

 original:
1, 3, 5, 7
2, 1, -1, 0
3, 4, 4, 7
5, 5, 3, 7
echelon form:
1, 3, 5, 7
0, -5, -11, -14
0, 0, 0, 0
0, 0, 0, 0
  

Комментарии:

1. Пожалуйста, приложите пример вашего CSV.

2. У вас есть принятый ответ с участием lua. Поэтому я отменяю изменение, которое удалило все ссылки на lua из вашего вопроса.

Ответ №1:

t.lua :

 --[[

Gaussian Elimination in Lua

--]]

-- print matrix
local function printmatrix (m)
    for _, row in ipairs (m) do
        io.write (table.concat (row, ', ') .. 'n')
   end
end

-- read matrix in CSV format
local function readcsv (file)
    io.input (file)
    local m = {columns = 0, rectangular = true}
    for line in io.lines () do
        local row = {}
        -- the next line is tricky and goes over all entries in the row
        for w in line:gmatch '[^,] ' do
            row [#row   1] = tonumber (w) or 0
        end
        m [#m   1] = row
        -- Update matrix dimensions
        m.rectangular = m.rectangular and (#row == m.columns or #m == 1)
        m.columns = #row > m.columns and #row or m.columns
    end
    return m
end

-- if m[r][c] is zero swap row r with some row i>r to make m[r][c] nonzero, if possible
local function swap (m, r, c)
    local nrows, ncols = #m, m.columns
    if r <= 0 or r > nrows or c <= 0 or c > ncols then error 'Position out of range' end
    if m [r] [c] ~= 0 then
        -- nothing to do
        return
    end
    -- find a suitable row
    local i = r   1
    while i <= nrows and m [i] [c] == 0 do
        i = i   1
    end
    if i <= nrows then
        m [r], m [i] = m [i], m [r]
    end
end

-- if m[r][c] is nonzero apply row operations to make each m[i][c]==0 for i>r
local function clear (m, r, c)
    local nrows, ncols = #m, m.columns
    if r <= 0 or r > nrows or c <= 0 or c > ncols then error 'Position out of range' end
    if m [r] [c] == 0 then
        -- nothing to do
        return
    end
    for i = r   1, nrows do
        local f = m [i] [c] / m [r] [c]
        for j = 1, #m [i] do
            m [i] [j] = m [i] [j] - f * m [r] [j]
        end
    end
end

-- apply Gaussian elimination to m to get it into echelon form
function echelon (m)
    local nrows, ncols = #m, m.columns
    local r, c = 1, 1 -- current position
    while r <= nrows and c <= ncols do
        -- try to get a nonzero value at this position
        swap (m, r, c)
        if m [r] [c] == 0 then
            -- can't, so move right
            c = c   1
        else
            clear (m, r, c)
            -- done, so move diagonally
            r = r   1
            c = c   1
        end
    end
end

local m = readcsv (arg [1])
print 'Original:'
printmatrix (m)
if m.rectangular then
    echelon (m)
    print 'Echelon form:'
    printmatrix (m)
else
    error 'Matrix not rectangular!'
end
  

t.scv :

 1,3,5,7 
2,1,-1,0
3,4,4,7 
5,5,3,7
  

lua t.lua t.csv :

 Original:
1, 3, 5, 7
2, 1, -1, 0
3, 4, 4, 7
5, 5, 3, 7
Echelon form:
1, 3, 5, 7
0, -5, -11, -14
0, 0, 0, 0
0, 0, 0, 0
  

Вы также можете использовать стандартный ввод ( lua t.lua ; введите значения, завершите с Ctrl D помощью ).

  1. Чтобы поменять что-либо в Lua, просто сделайте a, b = b, a .
  2. Я использовал простой подход к вашему второму doit (применить row_i = row_i — f * row_r): for j = 1, #m [i] do m [i] [j] = m [i] [j] - f * m [r] [j] end `,
  3. Я сделал ваш код несколько более упорядоченным и элегантным. Я также упростил регулярное выражение, используемое для анализа строк CSV,
  4. Я также рассчитал размеры и прямоугольность матрицы во время ее ввода.