Шаг 95.
Основы языка Haskell.
Моделирование массивов на языке Haskell (общие сведения)

    На этом шаге мы приведем общие сведения о массивах.

    Архитектура большинства компьютеров по технологическим причинам строится так, что программные переменные располагают в линейном (одномерном) порядке. Это имеет далеко идущие последствия, касающиеся распространённых программистских привычек. В частности, если в процессе программирования понадобилось большое количество переменных для объектов одного и того же типа, то рекомендуется использовать структуру данных "массив".

Определение.
  • Массив - это конечная последовательность индексированных переменных, называемых  элементами массива. В качестве индексов фигурируют, как правило, целые числа. В этом случае для задания диапазона индексов достаточно указать нижнюю и верхнюю границы.
  • Размерностью массива называется количество индексов его элементов.

    Одномерные массивы (или векторы) образуют важный специальный класс массивов.

    Приведем несколько демонстрационных примеров.

   -- Функция увеличивает каждый элемент числовой матрицы на 1
   -----------------------------------------------------------
   addElt:: [[Int]] -> [[Int]] 
   addElt lst = map (addEl) lst
   ---------------------------------------------------------
   -- Функция увеличивает на 1 каждый элемент одноуровневого
   -- числового списка
   ----------------------                                        
   addEl:: [Int] -> [Int]
   addEl lst = map (1+) lst
   ------------------------------
   -- Неудачные тестовые примеры:
   ----------------------------------------------
   test =   addElt [[(-9),2,-23,67],[23,3,7,675],
                    [34,2,4,7],[23,-7,6,8]]
              == [[-8,3,-22,68],[24,4,8,676],[35,3,5,8],[24,-6,7,9]]
         && addElt [[(-92)],[233],[342],[-76]]
              == [[-91],[234],[343],[-75]] 
Файл с примерами можно взять здесь.
   -- Функция вычисляет сумму значений элементов:
   -- (1) в n-ой строке; 
   -- (2) в n-ом столбце числовой матрицы.
   -- Нумерация начинается с 0
   ------------------------------
   sumStr:: Int -> [[Int]] -> Int
   sumStr n lst | null lst = 0
                | n==0     = sum (head lst)
                | True     = sumStr (n-1) (tail lst)
   -------------------------------------------------
   sumKol:: Int -> [[Int]] -> Int

   sumKol n lst | null lst || n>(length (head lst))-1
                       = 0
                | True = ((head lst)!!n)+sumKol n (tail lst)
   ---------------------------------------------------------
   -- Неудачные тестовые примеры:
   -------------------------------------------------------
   test =   sumStr 1 [[1,2,2],[23,2,21],[234,33,34]] == 46
         && sumStr 3 [[1,2,2],[23,2,21],[234,33,34],[0,9,7]] == 16 
   ---------------------------------------------------------------
   test1 =   sumKol 2 [[1,2,12,90,89]] == 12
          && sumKol 3 [[1,2,12,90,89],[23,45,(-2),9,1],
                       [23,2,1,-9,-4]] == 90
          && sumKol 4 [[1,2,12,90,89],[23,45,(-2),9,1],
                       [23,2,1,-9,-4]] == 86
   -----------------------------------------
Файл с примерами можно взять здесь.
   -- Функция определяет количество ненулевых элементов:
   --   (1) в n-ой строке заданной матрицы;
   --   (2) в n-ом столбце числовой матрицы.
   -- Нумерация начинается с 0
   ---------------------------------
   notnulStr:: Int -> [[Int]] -> Int
   notnulStr n lst | null lst || (n>(length (head lst)-1)) = 0
                   | n==0 = nenul 0 (head lst)
                   | True = notnulStr (n-1) (tail lst)
   ----------------------------------------------------
   -- Функция возвращает количество ненулевых элементов
   -- в числовом одноуровневом списке (при обращении  к 
   -- функции накапливающий параметр n=0) 
   --------------------------------------
   nenul:: Int -> [Int] -> Int
   nenul n lst | null lst      = n
               | (head lst)/=0 = nenul (n+1) (tail lst)
               | True          = nenul n (tail lst)
   ------------------------------------------------
   notnulKol:: Int -> [[Int]] -> Int
   notnulKol n lst 
      | null lst || n>length (head lst) - 1
                           = 0
      | (head lst) !! n/=0 = 1 + notnulKol n (tail lst)
      | True               = notnulKol n (tail lst) 
   -- *********************************************
   -- Неудачные тестовые примеры:
   ---------------------------------------------------------------
   test =   notnulStr 0 [[2],[3]]                             == 1
         && notnulStr 0 [[23,34,-3,0,4]]                      == 4
         && notnulStr 1 [[23,34,-3,0,4,8,9],[23,4,5,4,4,3,0]] == 6
         && notnulStr 2 [[23,34,-3,0,4,8,9],[23,4,5,4,4,3,0],
                         [7,8,7,7,0,789,6]]                   == 6  
   ---------------------------------------------------------------
   test1 =   notnulKol 1 [[3,0,56],[5,6,7],[6,7,8]] == 2
          && notnulKol 2 [[3,0,56],[5,6,7],[6,7,8]] == 3
          && notnulKol 0 [[3,0,56],[0,6,7],[6,7,8]] == 2
          && notnulKol 1 [[3,0,56]]                 == 0
Файл с примерами можно взять здесь.
   -- Функция вычисляет суммы значений элементов числовой матрицы,
   -- расположенных в первой и последней строке матрицы, а также - 
   -- в её первом и последнем столбце
   ----------------------------------
   sumElem:: [[Int]] -> Int -> Int
   sumElem lst i | null lst = 0
                 | i==0     = sum (head lst)+sumElem (tail lst) 1
                 | null (tail lst)
                            = sum (head lst)
                 | True     = head (head lst)+last (head lst)+
                              sumElem (tail lst) i
   -- ********************************************
   -- Неудачные тестовые примеры:
   ------------------------------
   test =   sumElem [[9,0]] 0                     == 9
         && sumElem [[9,0,12,8,9],[0,8,9,2,-6]] 0 == 51
         && sumElem [[9,0,12,8,9],[0,8,9,2,-6],[8,5,6,4,3]] 0 == 58
         && sumElem [[9,1],[3,2]] 0               == 15
         && sumElem [[9,1],[3,2],[23,4]] 0        == 42
         && sumElem [[9,1,3],[3,2,4],[2,23,4]] 0  == 49
Файл с примерами можно взять здесь.
   -- Функция вычисляет произведение значений элементов
   -- числовой матрицы, расположенных на её диагоналях;
   -- при вызове функции i=0
   ----------------------------------
   multy_diag:: [[Int]] -> Int -> Int
   multy_diag lst i 
        | null lst && i==0 = 0
        | null lst || i>=n = 1
        | i/=n-(i+1) = (head lst !! i) * (head lst !! (n-(i+1)))
                       * multy_diag (tail lst) (i+1)
        | True = (head lst !! i) * multy_diag (tail lst) (i+1)
     where n = length (head lst)
   -- ***************************
   -- Неудачные тестовые примеры:
   -----------------------------------------------------
   test =   multy_diag [[2,3,3],[3,1,1],[3,5,2]] 0 == 36
         && multy_diag [[2,3],[3,4]]             0 == 72
         && multy_diag [[2,3,3],[3,4,4],[1,1,1]] 0 == 24
   -----------------------------------------------------
Файл с примерами можно взять здесь.
   -- Функция, обнуляющую значение элементов (нумерация начинается
   -- с 0):
   --   (1) в n-ой строке матрицы;
   --   (2) в n-ом столбце матрицы;
   --   (3) на диагонали матрицы, начиная с элемента, находящегося 
   --       на пересечении первой строки и первого столбца матрицы
   --       (на главной диагонали)
   ----------------------------------
   nulStr:: Int -> [[Int]] -> [[Int]]
   nulStr n lst | null lst = []
                | n==0 = [replicate m 0]++(tail lst)
                | True = [head lst]++nulStr (n-1) (tail lst)
      where m = length (head lst)
   ----------------------------------
   nulKol:: Int -> [[Int]] -> [[Int]]
   nulKol n lst 
      | null lst = []
      | n>m-1 || n<0 = lst
      | True = [(take n (head lst))++[0]++(drop (n+1) (head lst))]++
               nulKol n (tail lst)
      where m = length (head lst)
   -----------------------------------------------------
   -- При обращении к функции накапливающий параметр i=0
   -----------------------------------------------------
   nulDiag:: Int -> [[Int]] -> [[Int]]
   nulDiag n lst 
      | null lst = []
      | n>((length (head lst))-1) = lst
      | True = [take n (head lst)++[0]++drop (n+1) (head lst)]++
               nulDiag (n+1) (tail lst)
   -- *********************************
   -- Неудачные тестовые примеры:
   --------------------------------------------------------------
   test1 =   nulStr 2 [[3,4],[5,6],[78,9]] == [[3,4],[5,6],[0,0]]
          && nulStr 0 [[2],[3],[4]]        == [[0],[3],[4]]
          && nulStr 1 [[2],[3],[4],[90]]   == [[2],[0],[4],[90]]
   -------------------------------------------------------------
   test2 =   nulKol 1 [[2,3,4],[4,5,4],[4,3,2]] == 
             [[2,0,4],[4,0,4],[4,0,2]]
          && nulKol 2 [[2,3,4],[4,5,4],[4,3,2]] ==
             [[2,3,0],[4,5,0],[4,3,0]]
   ------------------------------------------------------
   test3 =   nulDiag 0 [[2],[3],[4]]     == [[0],[3],[4]]
          && nulDiag 0 [[2,3,4],[4,5,6]] == [[0,3,4],[4,0,6]]
          && nulDiag 0 [[2,3,4,5]]       == [[0,3,4,5]]
          && nulDiag 0 [[23,4,5,6],[4,5,6,7],[45,6,7,7]]
                                == [[0,4,5,6],[4,0,6,7],[45,6,0,7]]
          && nulDiag 0 [[1,2,3],[4,5,6],[3,4,5]]
                                == [[0,2,3],[4,0,6],[3,4,0]]
          && nulDiag 0 [[123,45,6],[5,6,7],[7,89,90],[7,89,6],[6,7,88]]
                   == [[0,45,6],[5,0,7],[7,89,0],[7,89,6],[6,7,88]]
Файл с примерами можно взять здесь.
   -- Функция, меняющая местами n-ю и m-ю строки
   ---------------------------------------------
   swapStr:: [[Int]] -> Int -> Int -> [[Int]]
   swapStr lst i j 
           | null lst || i==j || lst !! i==lst !! j 
                  = lst
           | i<j  = take i lst ++ [lst!!j]
                    ++ take (j-i-1) (drop (i+1) lst)
                    ++ [lst !! i] ++ drop (j+1) lst
           | True = swapStr lst j i
   -- *****************************
   -- Неудачные тестовые примеры:
   ---------------------------------------------------------
   test = swapStr [[3,4,6,8],[23,1,2,3],[4,5,6,7],[8,7,6,5]] 
                  2 3
          == [[3,4,6,8],[23,1,2,3],[8,7,6,5],[4,5,6,7]]
Файл с примерами можно взять здесь.

    На следующем шаге мы приведем перечень задач для самостоятельного решения.




Предыдущий шаг Содержание Следующий шаг