Klasifikasi suatu wilayah berdasarkan kemiringannya

16

Definisi

The k th cincin dari matriks persegi ukuran N , di mana 1 ≤ k ≤ langit-langit (N / 2) adalah daftar yang dibentuk oleh unsur-unsur dari k th dan (N-k + 1) th baris dan kolom, tetapi tanpa elemen k-1 pertama dan terakhir .

Contoh:

Matriks:

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

Dibatasi dalam cincin:

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

Cincin pertama di atas adalah 1,2,3,4,5,1,4,8,3,4,5,6,7,3,8,6, yang kedua adalah 7,8,9,5,9,1,2,7dan yang ketiga adalah 6.

Sebuah N oleh N matriks bilangan bulat positif adalah (untuk tujuan tantangan ini):

  • cekung jika semua bilangan bulat pada k th cincin secara ketat lebih besar dari orang-orang di (k + 1) th cincin, di mana k adalah setiap bilangan bulat antara 1 dan N (orang-orang pada deringan pertama adalah lebih besar dibandingkan pada kedua, yang pada gilirannya lebih besar dari pada yang ketiga dll) Contoh:

    4 5 6 4 7 -> karena 4,5,6,4,7,4,8,5,5,4,6,5,9,5,5,4 semuanya lebih tinggi dari
    4 3 2 2 4 mana saja dari 3,2,2,3,2,3,3,2, yang semuanya lebih tinggi dari 1
    5 2 1 3 8
    5 3 3 2 5
    9 5 6 4 5
    
  • datar jika semua bilangan bulat dalam matriks sama. Contoh lain (mungkin berlebihan):

    2 2 2 2
    2 2 2 2
    2 2 2 2
    2 2 2 2
    
  • cembung jika semua bilangan bulat pada cincin k th benar-benar lebih rendah daripada yang ada di cincin (k + 1) th , di mana k adalah bilangan bulat antara 1 dan N (yang pada cincin pertama lebih rendah dari pada yang kedua, yang merupakan pada gilirannya lebih rendah dari pada yang ketiga dll). Contoh:

    1 2 1 -> karena 1 dan 2 keduanya lebih rendah dari 6
    2 6 2
    1 2 1
    
  • tercampur jika matriks tidak memenuhi salah satu kriteria di atas. Contoh:

    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
    

Tantangan

Diberikan matriks kuadrat dari bilangan bulat positif dengan ukuran minimal 3 , mengklasifikasikannya sesuai dengan definisi di atas. Yaitu, mengeluarkan satu dari empat nilai konsisten berbeda berdasarkan apakah matriks itu cekung, datar, cembung atau campuran.

Anda dapat bersaing dalam bahasa pemrograman apa pun dan dapat mengambil input dan memberikan output melalui metode standar apa pun dan dalam format apa pun yang wajar, sambil memperhatikan bahwa celah ini dilarang secara default. Ini adalah , jadi pengiriman terpendek (dalam byte) untuk setiap bahasa menang.

Uji kasus

Berikut adalah banyak contoh untuk Anda pilih - Saya memilih 6 dari setiap kategori.

Cekung

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

Datar

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

Cembung

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

Campuran

[[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]]
Tuan Xcoder
sumber
Tantangan ini sebelumnya telah diposting di Sandbox . Terima kasih kepada mereka yang telah memberikan umpan balik yang berharga di sana.
Tn. Xcoder
2
Boy, bukankah menyenangkan untuk memiliki beberapa konversi string array-of-array ke / dari fungsi matriks berguna untuk memproses semua kasus uji dalam berbagai bahasa :)
ngm
@ ngm Jangan berani-berani berpikir kita belum memilikinya ! : P
Mr. Xcoder

Jawaban:

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

Cobalah online!

Output:

  • 1 untuk "cekung"
  • 2 untuk "flat"
  • 3 untuk "cembung"
  • 4 untuk "campur"

Tidak Terkumpul:

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
}
SamYonnou
sumber
5

Jelly ,  18 17  16 byte

Saya percaya ada banyak potensi untuk upaya ini untuk bermain golf

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

Tautan monadik yang menerima daftar daftar angka yang mengembalikan daftar bilangan bulat:

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

Cobalah online! Atau lihat test-suite .

L‘Hbisa diganti dengan yang kurang efisien tetapi secara atom lebih pendek JÆm.

Bagaimana?

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]
Jonathan Allan
sumber
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

Cobalah online!

Output set([1]), set([0]), set([-1]),atauFalse untuk cekung, datar, cembung, atau campuran, masing-masing.

Terima kasih untuk: Kekalahan 27 byte dari beberapa optimisasi oleh ovs . Lalu satu lagi 13 byte setelah itu.

Pemahaman daftar A (karena ovs) membuat daftar elemen setiap cincin, diurutkan.

Selanjutnya, kami membandingkan maxdan minnilai antara cincin yang berdekatan dengan melihat0-1 elemen th dan th dari setiap daftar yang disortir dalam A. Perhatikan bahwa jika, misalnya, Mcekung, minsetiap cincin luar harus lebih besar daripada maxcincin paling dalam berikutnya ; dan kemudian mengikuti bahwa maxdari setiap cincin luar juga akan lebih besar dari mincincin paling dalam berikutnya.

Jika Mcekung, datar, atau cembung, himpunan min/maxperbandingan ini hanya memiliki 1 elemen{-1, 0, 1} ; jika dicampur, akan ada dua elemen atau lebih.

Chas Brown
sumber
@ovs: Itu cukup col; Saya menyimpan byte lain dengan mengubahnya menjadi daftar pemahaman (dan berpikir bahwa ini mungkin teknik yang sangat berguna untuk tantangan serupa lainnya).
Chas Brown
Mungkin ada cara untuk memperpendek pemahaman daftar, tetapi perulangan sementara tampaknya masih lebih pendek: 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: Anda telah menghilangkan ,A=()jumlah byte Anda ...
Chas Brown
Saya mendapatkan 174 byte denganA=()
ovs
Ah! Maaf, saya salah paham. Hal ini berbeda dari versi sebelumnya Anda, yang dalam bentuk: while M: A+= (some expression).
Chas Brown
4

Jelly , 17 byte

ŒDŒH€ẎUÐeZ_þƝṠFf/

Mengembalikan 1 untuk cekung , 0 untuk flat , -1 untuk cembung , dan tidak untuk campuran .

Cobalah online!

Dennis
sumber
4

JavaScript (ES6), 168 byte

Pengembalian:

  • -1 untuk flat
  • 0 untuk campuran
  • 1 untuk cembung
  • 2 untuk cekung
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)

Cobalah online!

Bagaimana?

Minimum dan maksimum pada setiap dering

Kami menghitung m minimum dan M maksimum pada setiap cincin.

Kami menguji apakah sel terletak pada cincin yang diberikan dengan menghitung jarak kuadrat dari pusat matriks pada setiap sumbu. Mengambil nilai absolut akan berhasil juga, tetapi mengkuadratkan lebih pendek.

Sel di (x, y) terletak di cincin ke- n (diindeks 0, dimulai dari yang terluar) jika rumus berikut salah :

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

dimana:

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

Contoh: apakah sel (1, 2) pada cincin ke-2 dari matriks 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

Bendera

Pada akhir setiap iterasi, kami membandingkan m dan M terhadap p minimum dan P maksimum dari cincin sebelumnya dan memperbarui variabel flag i sesuai:

  • i |= 1jika m> P
  • i |= 2jika M <p
  • kami menetapkan bit i yang lebih tinggi jika M! = m

Pada akhir proses, kami mengonversi nilai akhir i sebagai berikut:

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)
Arnauld
sumber
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]}

Cobalah online!

pengembalian 1= cekung, ::= datar, -1= cembung,0 = campuran

( ::digunakan sebagai pengganti untuk nilai yang hilang dalam k)

ngn
sumber
Strategi yang berbeda, menggunakan oK:&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/*:'(|+:)\)'-1_(-1_1_+-1_1_)\
zgrep
@ zgrep bagus! :) jangan ragu untuk memposting sebagai jawaban yang terpisah dan mengambil ide dari saya jika Anda mau - misalnya sepertinya membagi saya menjadi lebih pendek, tapi saya belum mencobanya di oK
ngn
Ooh, itu ring split yang sangat rapi! Saya suka itu.
zgrep
2

OK , 56 byte

&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':{(,/x)@.=i&|i:&/!2##x}@

Didasarkan atas jawaban ngn .

Cobalah online!

concave:1 0 0
   flat:0 0 1
 convex:0 1 0
  mixed:0 0 0
zgrep
sumber
tidak perlu untuk @ jika Anda mengubah semuanya menjadi satu lambda besar:{&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/x)@.=i&|i:&/!2##x}
ngn
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;};

Skor tinggi baru! (pada saat posting, setidaknya) Oh well, ini agak bagus, tapi masih C ++.

Cobalah online!

Lambda Cmengambilstd::vector<std::vector<int>> dan mengembalikan 1 untuk cekung, 2 untuk cembung, 3 untuk flat, atau 0 untuk campuran.

Versi kode yang lebih mudah dibaca, dengan pengidentifikasi deskriptif, komentar, R-> returndan I-> intdituliskan, dll .:

#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;
};
aschepler
sumber
1
Saya tidak berpikir 'bagus' berarti apa yang Anda pikirkan artinya
ASCII