Phân loại một khu vực theo độ dốc của nó


16

Các định nghĩa

Các k thứ nhẫn của một ma trận vuông có kích thước N , nơi 1 ≤ k ≤ trần (N / 2) là danh sách hình thành bởi các yếu tố của k th(N-k + 1) thứ hàng và cột, nhưng không có yếu tố k-1 đầu tiên và cuối cùng .

Thí dụ:

Ma trận:

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

Giới hạn trong các vòng:

+ ------------------- +
| 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 |
+ ------------------- +

Vòng thứ nhất ở trên là 1,2,3,4,5,1,4,8,3,4,5,6,7,3,8,6, vòng thứ hai 7,8,9,5,9,1,2,7và vòng thứ ba là 6.

Một N bởi N ma trận các số nguyên dương là (đối với mục đích của thử thách này):

  • lõm nếu tất cả các số nguyên trên k thứ nhẫn Nghiêm lớn hơn những người trên (k + 1) lần thứ nhẫn, nơi k là số nguyên nằm giữa 1N (những người trên chiếc nhẫn đầu tiên là lớn hơn so với những ngày thứ hai, đó là lần lượt lớn hơn những người thứ ba, v.v.). Thí dụ:

    4 5 6 4 7 -> vì 4,5,6,4,7,4,8,5,5,4,6,5,9,5,5,4 đều cao hơn
    4 3 2 2 4 bất kỳ 3,2,2,3,2,3,3,2, tất cả đều cao hơn 1
    5 2 1 3 8
    5 3 3 2 5
    9 5 6 4 5
    
  • phẳng nếu tất cả các số nguyên trong ma trận đều bằng nhau. Một ví dụ khác (có lẽ là dư thừa):

    2 2 2 2
    2 2 2 2
    2 2 2 2
    2 2 2 2
    
  • lồi nếu tất cả các số nguyên trên k thứ nhẫn Nghiêm thấp hơn so với những người trên (k + 1) lần thứ nhẫn, nơi k là số nguyên nằm giữa 1N (những người trên chiếc nhẫn đầu tiên là thấp hơn so với ngày thứ hai, đó là lần lượt thấp hơn so với những người thứ ba, vv). Thí dụ:

    1 2 1 -> vì 1 và 2 đều thấp hơn 6
    2 6 2
    1 2 1
    
  • hỗn hợp nếu ma trận không thỏa mãn bất kỳ tiêu chí nào ở trên. Thí dụ:

    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
    

Thử thách

Cho một ma trận vuông các số nguyên dương có kích thước ít nhất là 3 , phân loại nó theo các định nghĩa ở trên. Nghĩa là, xuất một trong bốn giá trị nhất quán khác nhau dựa trên việc ma trận là lõm, phẳng, lồi hay hỗn hợp.

Bạn có thể cạnh tranh trong bất kỳ ngôn ngữ lập trình nào và có thể lấy đầu vào và cung cấp đầu ra thông qua bất kỳ phương thức tiêu chuẩn nào và ở bất kỳ định dạng hợp lý nào, trong khi lưu ý rằng các lỗ hổng này bị cấm theo mặc định. Đây là , vì vậy bài nộp ngắn nhất (tính bằng byte) cho mọi ngôn ngữ sẽ thắng.

Các trường hợp thử nghiệm

Đây là một loạt các ví dụ để bạn lựa chọn - Tôi đã chọn 6 từ mỗi loại.

Lõm

[[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]]

Bằng phẳng

[[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]]

Lồi

[[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]]

Trộn

[[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]]

Thử thách này trước đây đã được đăng trong Sandbox . Cảm ơn những người đã đưa ra phản hồi có giá trị ở đó.
Ông Xcoder

2
Boy, thật tuyệt khi có một số chuyển đổi chuỗi mảng thành / từ các hàm ma trận có ích để xử lý tất cả các trường hợp thử nghiệm đó bằng nhiều ngôn ngữ :)
ngm

@ngm Bạn không dám nghĩ chúng tôi chưa có ai ! : P
Ông Xcoder

Câu trả lời:


5

Java (JDK 10) , 247 232 220 byte

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;}

Hãy thử trực tuyến!

Đầu ra:

  • 1 cho "lõm"
  • 2 cho "căn hộ"
  • 3 cho "lồi"
  • 4 cho "hỗn hợp"

Ung dung:

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

Thạch ,  18 17  16 byte

Tôi tin rằng có rất nhiều tiềm năng cho nỗ lực này để được chơi golf

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

Một liên kết đơn âm chấp nhận danh sách các danh sách các số trả về danh sách các số nguyên:

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

Hãy thử trực tuyến! Hoặc xem bộ thử nghiệm .

L‘Hcó thể được thay thế bằng hiệu quả thấp hơn nhưng nguyên tử ngắn hơn JÆm.

Làm sao?

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 byte

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

Hãy thử trực tuyến!

Đầu ra set([1]), set([0]), set([-1]),hoặc Falsecho lõm, phẳng, lồi hoặc hỗn hợp, tương ứng.

Thx cho: Một con số khổng lồ 27 byte từ một vài tối ưu hóa của các lò nướng . Và sau đó một 13 byte sau đó.

Việc hiểu danh sách A(do lò nướng) tạo ra một danh sách các yếu tố của mỗi vòng, được sắp xếp.

Tiếp theo, chúng tôi so sánh giá trị maxmingiá trị giữa các vòng liền kề bằng cách xem xét các phần tử thứ 0-1thứ của từng danh sách được sắp xếp trong A. Lưu ý rằng, ví dụ, nếu, Mlõm, thì minmỗi vòng ngoài phải lớn hơn vòng ngoài maxcùng tiếp theo ; và sau đó theo sau maxmỗi vòng ngoài cũng sẽ lớn hơn vòng ngoài mintiếp theo.

Nếu Mlà lõm, phẳng hoặc lồi, tập hợp các phép min/maxso sánh này sẽ chỉ có 1 phần tử từ {-1, 0, 1}; nếu nó được trộn lẫn, sẽ có hai hoặc nhiều yếu tố.


@ovs: Đó là col đẹp; Tôi đã lưu một byte khác bằng cách biến nó thành một sự hiểu biết danh sách (và nghĩ rằng đây có thể là một kỹ thuật rất hữu ích cho các thách thức tương tự khác).
Chas Brown

Có thể có một cách để rút ngắn việc hiểu danh sách, nhưng một vòng lặp while dường như vẫn ngắn hơn: 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 byte)
ovs

@ovs: Bạn đã bỏ qua ,A=()số byte của mình ...
Chas Brown

Tôi nhận được 174 byte vớiA=()
ovs

Ah! Xin lỗi, tôi hiểu lầm. Điều này khác với phiên bản trước của bạn, có dạng : while M: A+= (some expression).
Chas Brown


4

JavaScript (ES6), 168 byte

Trả về:

  • -1 cho căn hộ
  • 0 cho hỗn hợp
  • 1 cho lồi
  • 2 cho lõm
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)

Hãy thử trực tuyến!

Làm sao?

Tối thiểu và tối đa trên mỗi vòng

Chúng tôi tính m tối thiểu và M tối đa trên mỗi vòng.

Chúng tôi kiểm tra xem một ô có nằm trên một vòng cho trước hay không bằng cách tính khoảng cách bình phương từ tâm của ma trận trên mỗi trục. Lấy giá trị tuyệt đối cũng sẽ hoạt động tốt, nhưng bình phương thì ngắn hơn.

Một ô tại (x, y) nằm trên vòng thứ n (được lập chỉ mục 0, bắt đầu từ ô ngoài cùng) nếu công thức sau là sai :

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

Ở đâu:

  • X = k² - (x - w) ²
  • Y = k² - (y - w) ²
  • w = (a.length - 1) / 2
  • k = w - n

Ví dụ: là ô (1, 2) trên vòng 2 của ma trận 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

Cờ

Vào cuối mỗi lần lặp, chúng ta so sánh mM với p tối thiểu và P tối đa của vòng trước đó và cập nhật biến cờ i tương ứng:

  • i |= 1nếu m> P
  • i |= 2nếu M <p
  • chúng ta đặt bit cao hơn của i nếu M! = m

Khi kết thúc quá trình, chúng tôi chuyển đổi giá trị cuối cùng của i như sau:

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 (ngn / k) , 100 71 69 byte

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

Hãy thử trực tuyến!

return 1= lõm, ::= phẳng, -1= lồi, 0= hỗn hợp

( ::được sử dụng như một trình giữ chỗ cho các giá trị bị thiếu trong k)


Một chiến lược khác, sử dụng &/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/*:'(|+:)\)'-1_(-1_1_+-1_1_)\
oK

@zgrep đẹp quá! :) vui lòng gửi bài dưới dạng một câu trả lời riêng biệt và lấy ý tưởng từ tôi nếu bạn muốn - ví dụ như có vẻ như việc chia thành các vòng của tôi ngắn hơn, nhưng tôi chưa thử nó trong
oK


Ôi, đó là một vòng chia rất gọn gàng! Tôi thích nó.
zgrep


1

C ++ 17 (gcc) , 411 byte

#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;};

Một điểm số cao mới! (ít nhất là tại thời điểm đăng bài) Ồ, nó hơi tiện lợi, nhưng vẫn là C ++.

Hãy thử trực tuyến!

Lambda Clấy a std::vector<std::vector<int>>và trả về 1 cho lõm, 2 cho lồi, 3 cho phẳng hoặc 0 cho hỗn hợp.

Một phiên bản dễ đọc hơn của mã, với các định danh mô tả, nhận xét, R-> returnI-> intđược viết ra, v.v.:

#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
Tôi không nghĩ 'tiện lợi' có nghĩa là những gì bạn nghĩ
ASCII - chỉ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.