Классифицируйте регион по наклону


16

Определения

К е кольцо квадратной матрицы размера N , где 1 ≤ K ≤ потолок (N / 2) представляет собой список , образованный элементами к - й и (N-K + 1) й строки и столбцы, но без первый и последний к-1 элементов.

Пример:

Матрица:

1 2 3 4 5
6 7 8 9 1
8 7 6 5 4
3 2 1 9 8
7 6 5 4 3

Разграничены в кольцах:

+ ------------------- +
| 1 2 3 4 5 |
| + ----------- + |
| 6 | 7 8 9 | 1 |
| | + --- + | |
| 8 | 7 | 6 | 5 | 4 |
| | + --- + | |
| 3 | 2 1 9 | 8 |
| + ----------- + |
| 7 6 5 4 3 |
+ ------------------- +

Первое кольцо из вышесказанного 1,2,3,4,5,1,4,8,3,4,5,6,7,3,8,6, второе 7,8,9,5,9,1,2,7и третье 6.

N на N матрицы положительных целых чисел (для целей этой задачи):

  • вогнутыми, если все целые числа в k- м кольце строго больше, чем целые в (k + 1) кольце, где k - любое целое число от 1 до N (те, что в первом кольце, больше, чем во втором в свою очередь больше, чем на третьем и т. д.). Пример:

    4 5 6 4 7 -> потому что 4,5,6,4,7,4,8,5,5,4,6,5,9,5,5,4 все выше, чем
    4 3 2 2 4 любая из 3,2,2,3,2,3,3,2, которые все выше 1
    5 2 1 3 8
    5 3 3 2 5
    9 5 6 4 5
    
  • плоский, если все целые числа в матрице равны. Другой пример (возможно, избыточный):

    2 2 2 2
    2 2 2 2
    2 2 2 2
    2 2 2 2
    
  • выпуклые, если все числа в k- м кольце строго ниже, чем в (k + 1) кольце, где k - любое целое число между 1 до N (те, что в первом кольце, меньше, чем во втором, что в свою очередь ниже, чем на третьем и т. д.). Пример:

    1 2 1 -> потому что 1 и 2 ниже 6
    2 6 2
    1 2 1
    
  • смешивается, если матрица не удовлетворяет ни одному из вышеуказанных критериев. Пример:

    3 3 3 3 3
    3 2 2 2 3
    3 2 3 2 3
    3 2 2 2 3
    3 3 3 3 3
    

Вызов

Учитывая квадратную матрицу натуральных чисел размером не менее 3 , классифицируйте ее в соответствии с определениями выше. То есть выведите одно из четырех различных последовательных значений на основе того, является ли матрица вогнутой, плоской, выпуклой или смешанной.

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

Контрольные примеры

Вот несколько примеров для выбора - я выбрал 6 из каждой категории.

вогнутый

[[3, 3, 3], [3, 1, 3], [3, 3, 3]]
[[2, 3, 4], [5, 1, 6], [7, 8, 9]]
[[19, 34, 45], [34, 12, 14], [13, 13, 13]]
[[3, 4, 3, 4], [4, 2, 1, 3], [3, 1, 2, 4], [4, 3, 4, 3]]
[[4, 5, 6, 4, 7], [4, 3, 2, 2, 4], [5, 2, 1, 3, 8], [5, 3, 3, 2, 5], [9, 5, 6, 4, 5]]
[[7, 7, 7, 7, 7], [7, 6, 6, 6, 7], [7, 6, 5, 6, 7], [7, 6, 6, 6, 7], [7, 7, 7, 7, 7]]

Плоский

[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
[[2, 2, 2], [2, 2, 2], [2, 2, 2]]
[[8, 8, 8], [8, 8, 8], [8, 8, 8]]
[[120, 120, 120], [120, 120, 120], [120, 120, 120]]
[[10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10]]
[[5, 5, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5]]

выпуклость

[[1, 2, 1], [2, 6, 2], [1, 2, 1]]
[[1, 1, 1], [1, 2, 1], [1, 1, 1]]
[[19, 34, 45], [34, 76, 14], [13, 6, 13]]
[[3, 3, 3, 3], [3, 4, 4, 3], [3, 4, 4, 3], [3, 3, 3, 3]]
[[192, 19, 8, 6], [48, 324, 434, 29], [56, 292, 334, 8], [3, 4, 23, 23]]
[[291, 48, 7, 5], [47, 324, 454, 30], [58, 292, 374, 4], [9, 2, 53, 291]]

смешанный

[[1, 2, 3], [4, 5, 9], [6, 7, 8]]
[[10, 14, 21], [100, 8, 3], [29, 2, 19]]
[[5, 5, 5, 5], [5, 4, 4, 5], [5, 4, 6, 5], [5, 5, 5, 5]]
[[3, 3, 3, 3], [3, 1, 2, 3], [3, 3, 2, 3], [3, 3, 3, 3]]
[[12, 14, 15, 16], [12, 18, 18, 16], [12, 11, 11, 16], [12, 14, 15, 16]]
[[5, 5, 5, 5, 5], [5, 4, 4, 4, 5], [5, 4, 6, 4, 5], [5, 4, 4, 4, 5], [5, 5, 5, 5, 5]]

Этот вызов ранее был размещен в Песочнице . Спасибо тем, кто дал ценные отзывы там.
г-н Xcoder

2
Боже, разве не было бы неплохо иметь какое -либо преобразование строк из массива в / из матричных функций, пригодное для обработки всех этих тестов на разных языках :)
ngm

@ngm Не смей думать, что у нас его еще нет ! : P
Mr. Xcoder

Ответы:


5

Java (JDK 10) , 247 232 220 байт

x->{int i=0,j=x.length,k,m,M,p=0,P=0,r=0;for(;i<j;){for(M=m=x[k=i][--j];k<=j;)for(int q:new int[]{x[i][k],x[j][k],x[k][i],x[k++][j]}){m=m<q?m:q;M=M<q?q:M;}r=i++>0?(k=P<m?3:p>M?1:P==m?2:4)*r!=r*r?4:k:0;p=m;P=M;}return r;}

Попробуйте онлайн!

Выходы:

  • 1 для "вогнутой"
  • 2 для "квартиры"
  • 3 для "выпуклой"
  • 4 для "смешанных"

Ungolfed:

x -> { // lambda that takes in the input int[][]
  int i = 0, // index of right bound of ring
      j = x.length, // index of left bound of ring
      k, // index of row-column-pair in ring
      m, // minimum of ring
      M, // maximum of ring
      p = 0, // minimum of previous ring
      P = 0, // maximum of previous ring
      r = 0; // result
  for (; i < j; ) { // iterate the rings from outside inwards
    // set both min and max to be to top right corner of the ring (and sneakily set some loop variables to save space)
    for (M = m = x[k = i][--j]; k <= j; ) // iterate the row-column pairs of the ring from top-right to bottom-left
      for (int q : new int[] {x[i][k], x[j][k], x[k][i], x[k++][j]}) { // iterate all of the cells at this row-column pair (and sneakily increment the loop variable k)
        // find new minimum and maximum
        m = m < q ? m : q;
        M = M < q ? q : M;
      }
    r = // set the result to be...
      i++ > 0 ? // if this is not the first ring... (and sneakily increment the loop variable i)
              // if the new result does not match the old result...
              (k = P < m ? // recycling k here as a temp variable to store the new result, computing the result by comparing the old and new mins/maxes
                         3
                         : p > M ?
                                 1
                                 : P == m ? 
                                          2
                                          : 4) * r != r * r ? // multiplying by r here when comparing because we want to avoid treating the case where r = 0 (unset) as if r is different from k
                                                            4 // set the result to "mixed"
                                                            : k // otherwise set the result to the new result
              : 0; // if this is the first ring just set the result to 0
    // set the old ring mins/maxes to be the current ones
    p = m; 
    P = M;
  }
  return r; // return the result
}

5

Желе ,  18 17  16 байт

Я считаю, что есть большие возможности для того, чтобы это усилие было в гольфе

L‘HạŒỤṀ€IṠQṢ«FE$

Монадическая ссылка, принимающая список списков чисел, который возвращает список целых чисел:

Concave ->  [0, 0]
Flat    ->  [-1, 0, 1]
Convex  ->  [-1, 0]
Mixed   ->  [-1, 0, 0]

Попробуйте онлайн! Или посмотрите набор тестов .

L‘Hможет быть заменен на менее эффективный, но атомно короче JÆm.

Как?

L‘HạŒỤṀ€IṠQṢ«FE$ - Link: list of (equal length) lists of numbers
L                - length
 ‘               - increment
  H              - halve
                 -   = middle 1-based index (in both dimensions as the input is square)
    ŒỤ           - sort multi-dimensional indices by their corresponding values
                 -   = a list of pairs of 1-based indexes
   ạ             - absolute difference (vectorises)
                 -   = list of [verticalDistanceToMiddle, horizontalDistanceToMiddle] pairs
      Ṁ€         - maximum of €ach
                 -   each = N/2-k (i.e. 0 as middle ring and N/2 as outermost)
        I        - incremental deltas (e.g. [3,2,2,3,1]->[3-2,2-2,3-2,1-3]=[-1,0,1,-2])
         Ṡ       - sign (mapping -n:-1; 0:0; and +n:1)
          Q      - de-duplicate
           Ṣ     - sort
                 -   = concave:[0, 1]; convex:[-1, 0]; flatOrMixed:[-1, 0, 1]
               $ - last two links as a monad
             F   -   flatten
              E  -   all equal? (1 if flat otherwise 0)
            «    - minimum (vectorises)
                 -   = concave:[0, 0]; convex:[-1, 0]; mixed:[-1, 0, 0]; flat:[-1, 0, 1]

5

Python 2 , 219 216 189 176 байт

def g(M):A=[sorted((M[1:]and M.pop(0))+M.pop()+[i.pop(j)for j in[0,-1]for i in M])for k in M[::2]];S={cmp(x[j],y[~j])for x,y in zip(A,A[1:])for j in[0,-1]};return len(S)<2and S

Попробуйте онлайн!

Выходы set([1]), set([0]), set([-1]),или Falseдля вогнутых, плоских, выпуклых или смешанных соответственно.

Спасибо за: колоссальные 27 байтов из нескольких оптимизаций по ovs . А потом еще 13 байтов после.

AПонимание списка (из-за ovs) создает список элементов каждого кольца, отсортированных.

Далее мы сравниваем maxи minзначение между соседними кольцами, глядя на 0го и-1 й элементы каждого отсортированного списка в A. Заметим , что если, например, Mимеет вогнутую форму, minкаждого наружного кольца должна быть больше maxследующего внутреннего кольца-самые ; и из этого следует, что maxкаждого внешнего кольца также будет больше, чем minследующего самого внутреннего кольца.

Если Mвогнутый, плоский или выпуклый, набор этих min/maxсравнений будет иметь только 1 элемент из{-1, 0, 1} ; если это смешано, будет два или более элементов.


@ovs: это очень ценно; Я сохранил еще один байт, превратив его в понимание списка (и подумал, что это может быть очень полезным приемом для других подобных задач).
Час Браун

Может быть, есть способ сократить понимание списка, но цикл while все еще кажется короче: while M:k=M[0]+M[-1];M=M[1:-1];A+=sorted(k+[i.pop(j)for j in[0,-1]for i in M]),(174 байта)
ovs

@ovs: Вы пропустили ,A=()из своего числа байтов ...
Час Браун

Я получаю 174 байта сA=()
ovs

Ах! Извинения, я неправильно понял. Это отличается от вашей предыдущей версии, которая была в виде: while M: A+= (some expression).
Час Браун


4

JavaScript (ES6), 168 байт

Возвращает:

  • -1 для квартиры
  • 0 для смешанного
  • 1 для выпуклой
  • 2 для вогнутой
f=(a,k=w=~-a.length/2,p,P,i,m,M,y=w)=>k<0?i%4%3-!i:a.map(r=>r.map(v=>Y|(X=k*k-x*x--)<0&&X|Y<0||(m=v>m?m:v,M=v<M?M:v),x=w,Y=k*k-y*y--))|f(a,k-1,m,M,i|M-m<<2|2*(M<p)|m>P)

Попробуйте онлайн!

Как?

Минимум и максимум на каждом кольце

Вычисляем минимум m и максимум M на каждом кольце.

Мы проверяем, расположена ли ячейка в данном кольце, вычисляя квадратное расстояние от центра матрицы на каждой оси. Взятие абсолютного значения будет работать так же хорошо, но квадрат короче.

Ячейка в точке (x, y) расположена в n-м кольце (с индексами 0, начиная с самого дальнего), если следующая формула неверна :

((Y != 0) or (X < 0)) and ((X != 0) or (Y < 0))

где:

  • X = k² - (x - w) ²
  • Y = k² - (y - w) ²
  • w = (длина a - 1) / 2
  • k = w - n

Пример: находится ли ячейка (1, 2) на втором кольце матрицы 6x6?

  | 0 1 2 3 4 5   w = (6 - 1) / 2 = 2.5
--+------------   (x, y) --> ( x-w,  y-w) --> ((x-w)²,(y-w)²)
0 | 0 0 0 0 0 0   (1, 2) --> (-1.5, -0.5) --> (  2.25,   0.5)
1 | 0 1 1 1 1 0   
2 | 0[1]0 0 1 0   k = w - 1 = 1.5
3 | 0 1 0 0 1 0   k² = 2.25
4 | 0 1 1 1 1 0   X = 2.25 - 2.25 = 0 / Y = 2.25 - 0.5 = 1.75
5 | 0 0 0 0 0 0   ((X != 0) or (Y < 0)) is false, so (1,2) is on the ring

Флаги

В конце каждой итерации мы сравниваем m и M с минимальным p и максимальным P предыдущего кольца и соответствующим образом обновляем переменную флага i :

  • i |= 1если m> P
  • i |= 2если М <р
  • мы устанавливаем старшие биты i, если M! = m

В конце процесса мы конвертируем окончательное значение i следующим образом:

i % 4  // isolate the 2 least significant bits (for convex and concave)
% 3    // convert 3 to 0 (for mixed)
- !i   // subtract 1 if i = 0 (for flat)

4

K (нгн / к) , 100 71 69 байт

{$[1=#?,/a:(,/x)@.=i&|i:&/!2##x;;(&/m>1_M,0)-&/(m:&/'a)>-1_0,M:|/'a]}

Попробуйте онлайн!

возвращает 1= вогнутый, ::= плоский, -1= выпуклый, 0= смешанный

( ::используется как заполнитель для пропущенных значений в k)


Другая стратегия, использующая ОК:&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/*:'(|+:)\)'-1_(-1_1_+-1_1_)\
zgrep

@zgrep приятно! :) не стесняйтесь публиковать в качестве отдельного ответа и брать идеи от меня, если хотите - например, кажется, что мое расщепление на кольца короче, но я еще не пробовал в ОК
ngn


О, это очень аккуратный раскол кольца! Мне это нравится.
zgrep


1

C ++ 17 (gcc) , 411 байт

#import<map>
#define R return
#define T(f,s)X p,c;for(auto&e:r){c=e.second;if(p.a&&!p.f(c)){s;}p=c;}R
using I=int;struct X{I a=0;I z=0;I f(I n){R!a||n<a?a=n:0,n>z?z=n:0;}I
l(X x){R z<x.a;}I g(X x){R a>x.z;}I e(X x){R a==z&a==x.a&z==x.z;}};I
N(I i,I j,I s){i*=s-i;j*=s-j;R i<j?i:j;}auto C=[](auto&&m){I
s=size(m),i=-1,j;std::map<I,X>r;for(;++i<s;)for(j=-1;++j<s;)r[N(i,j,s-1)].f(m[i][j]);T(g,T(l,T(e,R 0)3)2)1;};

Новый рекорд! (во время публикации, по крайней мере) Ну, это немного изящно, но все же C ++.

Попробуйте онлайн!

Лямбда Cберетstd::vector<std::vector<int>> и возвращает 1 для вогнутой, 2 для выпуклой, 3 для плоской или 0 для смешанной.

Более разборчивая версия кода с описательными идентификаторами, комментариями, R-> returnи I-> intнаписано и т.д .:

#include <map>

// Abbreviation for golfing. Spelled out below.
#define R return

// Macro to test whether all pairs of consecutive Ranges in `rings`
// satisfy a condition.
// func: a member function of Range taking a second Range.
// stmts: a sequence of statements to execute if the condition is
//        not satisfied. The statements should always return.
//        May be missing the final semicolon.
// Expands to a statement, then the return keyword.
// The value after the macro will be returned if all pairs of Ranges
// satisfy the test.
#define TEST(func, stmts)                                     \
    Range prev, curr;                                         \
    for (auto& elem : rings) {                                \
        curr = elem.second;                                   \
        // The first time through, prev.a==0; skip the test.  \
        if (prev.a && !prev.func(curr))                       \
        { stmts; }                                            \
        prev = curr;                                          \
    }                                                         \
    return

// Abbreviation for golfing. Spelled out below.
using I = int;

// A range of positive integers.
// A default-constructed Range is "invalid" and has a==0 && z==0.
struct Range
{
    int a = 0;
    int z = 0;
    // Add a number to the range, initializing or expanding.
    // The return value is meaningless (but I is shorter than void for golfing).
    int add(int n) {
        return !a||n<a ? a=n : 0, n>z ? z=n : 0;
        /* That is:
        // If invalid or n less than previous min, set a.
        if (a==0 || n<a)
            a = n;
        // If invalid (z==0) or n greater than previous max, set z.
        if (n>z)
            z = n;
        return dummy_value;
        */
    }

    // Test if all numbers in this Range are strictly less than
    // all numbers in Range x.
    int less(Range x)
    { return z < x.a; }

    // Test if all numbers in this Range are strictly greater than
    // all numbers in Range x.
    int greater(Range x)
    { return a > x.z; }

    // Test if both this Range and x represent the same single number.
    int equal(Range x)
    { return a==z && a==x.a && z==x.z; }
};

// Given indices into a square matrix, returns a value which is
// constant on each ring and increases from the first ring toward the
// center.
// i, j: matrix indices
// max: maximum matrix index, so that 0<=i && i<=max && 0<=j && j<=max
int RingIndex(int i, int j, int max)
{
    // i*(max-i) is zero at the edges and increases toward max/2.0.
    i *= max - i;
    j *= max - j;
    // The minimum of these values determines the ring.
    return i < j ? i : j;
}

// Takes a container of containers of elements convertible to int.
// Must represent a square matrix with positive integer values.
// Argument-dependent lookup on the outer container must include
// namespace std, and both container types must have operator[] to
// get an element.  (So std::vector or std::array would work.)
// Returns:
//   1 for a concave matrix
//   2 for a convex matrix
//   3 for a flat matrix
//   0 for a mixed matrix
auto C /*Classify*/ = [](auto&& mat)
{
    int mat_size=size(mat), i=-1, j;
    std::map<int, Range> rings;

    // Populate rings with the range of values in each ring.
    for (; ++i<mat_size;)
        for (j=-1; ++j<mat_size;)
            rings[RingIndex(i, j, mat_size-1)].add(mat[i][j]);

    // Nested macros expand to
    // Range prev, curr; for ... if (...) {
    //   Range prev, curr; for ... if (...) {
    //     Range prev, curr; for ... if (...) {
    //       return 0;
    //     } return 3;
    //   } return 2;
    // } return 1
    // Note each scope declares its own prev and curr which hide
    // outer declarations.
    TEST(greater, TEST(less, TEST(equal, return 0) 3) 2) 1;
};

1
Я не думаю, что «изящный» означает то, что вы думаете, это означает
только ASCII
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.