Sklasyfikuj region według jego nachylenia

16

Definicje

K p pierścienia kwadratowej macierzy o rozmiarze N , gdzie 1 ≤ k ≤ sufitu (N / 2) lista tworzą pierwiastków z k th i (N-k + 1), TH wierszy i kolumn, ale bez pierwszy i ostatni element k-1 .

Przykład:

Matryca:

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

Ograniczone w pierścieniach:

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

Pierwszy pierścień powyższego jest 1,2,3,4,5,1,4,8,3,4,5,6,7,3,8,6, drugi jest, 7,8,9,5,9,1,2,7a trzeci jest 6.

N o N macierzy liczb naturalnych jest (dla celów tego wyzwania)

  • wklęsła , gdy wszystkie liczby całkowite na k -tego pierścienia jest bezwzględnie większy niż na (k + 1) XX pierścień, gdzie k jest dowolną liczbą całkowitą pomiędzy 1 i N (tych, w pierwszym sygnale są większe niż te, na sekundę, co jest z kolei większe niż te na trzecim itd.). Przykład:

    4 5 6 4 7 -> ponieważ 4,5,6,4,7,4,8,5,5,4,6,5,9,5,5,4 są wyższe niż
    4 3 2 2 4 dowolne z 3,2,2,3,2,3,3,2, które są wyższe niż 1
    5 2 1 3 8
    5 3 3 2 5
    9 5 6 4 5
    
  • płaskie, jeśli wszystkie liczby całkowite w macierzy są równe. Kolejny przykład (być może zbędny):

    2 2 2 2
    2 2 2 2
    2 2 2 2
    2 2 2 2
    
  • wypukły , jeżeli wszystkie liczby całkowite na k p pierścienia są ściśle niższe niż na (k + 1) XX pierścień, gdzie k jest dowolną liczbą całkowitą pomiędzy 1 i N (ci pierwszego pierścienia jest mniejsza, niż na drugim, które są z kolei niższe niż te na trzecim itd.). Przykład:

    1 2 1 -> ponieważ oba 1 i 2 są mniejsze niż 6
    2 6 2
    1 2 1
    
  • mieszane, jeśli matryca nie spełnia żadnego z powyższych kryteriów. Przykład:

    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
    

Wyzwanie

Biorąc pod uwagę kwadratową macierz dodatnich liczb całkowitych o wielkości co najmniej 3 , sklasyfikuj ją zgodnie z powyższymi definicjami. Oznacza to, że wyprowadza jedną z czterech różnych spójnych wartości na podstawie tego, czy macierz jest wklęsła, płaska, wypukła czy mieszana.

Możesz konkurować w dowolnym języku programowania i odbierać dane wejściowe i dostarczać dane wyjściowe dowolną standardową metodą w dowolnym rozsądnym formacie, zwracając uwagę, że te luki są domyślnie zabronione. To jest , więc wygrywa najkrótsze przesłanie (w bajtach) dla każdego języka .

Przypadki testowe

Oto kilka przykładów do wyboru - wybrałem 6 z każdej kategorii.

Wklęsły

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

Mieszkanie

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

Wypukły

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

Mieszany

[[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]]
Pan Xcoder
źródło
To wyzwanie zostało wcześniej opublikowane w piaskownicy . Dziękujemy tym, którzy udzielili tam cennych informacji zwrotnych.
Pan Xcoder
2
Chłopcze, czy nie byłoby miło mieć jakąś konwersję łańcucha tablic na macierz funkcji do przetwarzania wszystkich przypadków testowych w różnych językach :)
ngm
@ngm Nie waż się myśleć, że jeszcze go nie mamy ! : P
Pan Xcoder

Odpowiedzi:

5

Java (JDK 10) , 247 232 220 bajtów

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

Wypróbuj online!

Wyjścia:

  • 1 dla „wklęsłych”
  • 2 dla „płaskiego”
  • 3 dla „wypukłego”
  • 4 dla „mieszanych”

Nie golfowany:

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
źródło
5

Galaretka ,  18 17  16 bajtów

Uważam, że istnieje duży potencjał, aby ten wysiłek został wyeliminowany

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

Monadyczny link akceptujący listę list liczb, który zwraca listę liczb całkowitych:

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

Wypróbuj online!Lub zobacz pakiet testowy .

L‘H można zastąpić mniej wydajnym, ale atomowo krótszymJÆm.

W jaki sposób?

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
źródło
5

Python 2 , 219 216 189 176 bajtów

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

Wypróbuj online!

Wyjścia set([1]), set([0]), set([-1]),lub odpowiednio Falsewklęsłe, płaskie, wypukłe lub mieszane.

Dzięki za: Aż 27 bajtów z kilku optymalizacji przez ovs . A potem kolejne 13 bajtów.

AZrozumienie listy (ze względu na ovs) tworzy listę elementów każdego posortowanego pierścienia.

Następnie porównujemy wartości maxi minmiędzy sąsiadującymi pierścieniami, patrząc na elementy 0th i -1th każdej listy posortowanej w A. Zauważ, że jeśli na przykład Mjest wklęsły, minkażdy pierścień zewnętrzny musi być większy niż maxnastępnego pierścienia najbardziej wysuniętego do środka ; a następnie wynika, że maxkażdy pierścień zewnętrzny będzie także większy niż minnastępnego pierścienia najbardziej wewnętrznego.

Jeśli Mjest wklęsły, płaski lub wypukły, zestaw tych min/maxporównań będzie zawierał tylko 1 element {-1, 0, 1}; jeśli jest mieszany, będą dwa lub więcej elementów.

Chas Brown
źródło
@ovs: To dość kol; Zaoszczędziłem kolejny bajt, przekształcając go w zrozumienie listy (i myśląc, że może to być bardzo przydatna technika dla innych podobnych wyzwań).
Chas Brown,
Być może istnieje sposób na skrócenie rozumienia listy, ale pętla while wydaje się być krótsza: 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 bajtów)
dniu
@ovs: Pominąłeś ,A=()liczbę bajtów ...
Chas Brown
Otrzymuję 174 bajtów zA=()
OVS
Ach! Przepraszam, źle zrozumiałem. To jest inna niż poprzedniej wersji, która była w postaci: while M: A+= (some expression).
Chas Brown,
4

Galaretka , 17 bajtów

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

Zwraca 1 dla wklęsłego , 0 dla płaskiego , -1 dla wypukłego i nic dla mieszanego .

Wypróbuj online!

Dennis
źródło
4

JavaScript (ES6), 168 bajtów

Zwroty:

  • -1 na mieszkanie
  • 0 dla mieszanych
  • 1 dla wypukłych
  • 2 na wklęsłe
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)

Wypróbuj online!

W jaki sposób?

Minimum i maksimum na każdym pierścieniu

Obliczamy minimalną mi maksymalną M dla każdego pierścienia.

Sprawdzamy, czy komórka znajduje się na danym pierścieniu, obliczając kwadratową odległość od środka matrycy na każdej osi. Przyjmowanie wartości bezwzględnej również by działało, ale kwadratowanie jest krótsze.

Komórka w (x, y) znajduje się na n-tym pierścieniu (indeksowany od 0, zaczynając od skrajnego), jeśli następująca formuła jest fałszywa :

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

gdzie:

  • X = k² - (x - w) ²
  • Y = k² - (y - w) ²
  • w = (a. długość - 1) / 2
  • k = w - n

Przykład: czy komórka (1, 2) na drugim pierścieniu matrycy 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

Flagi

Na końcu każdej iteracji porównujemy m i M z minimalnym p i maksymalnym P poprzedniego pierścienia i odpowiednio aktualizujemy zmienną flagi i :

  • i |= 1jeśli m> P
  • i |= 2jeśli M <p
  • ustawiamy wyższe bity i, jeśli M! = m

Na koniec procesu przekształcamy końcową wartość i w następujący sposób:

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
źródło
4

K (ngn / k) , 100 71 69 bajtów

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

Wypróbuj online!

zwraca 1= wklęsły, ::= płaski, -1= wypukły,0 = mieszany

( ::służy jako symbol zastępczy dla brakujących wartości w k)

ngn
źródło
Inna strategia, wykorzystująca ok:&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/*:'(|+:)\)'-1_(-1_1_+-1_1_)\
zgrep
@zgrep nice! :) nie krępuj się pisać jako osobną odpowiedź i czerpać pomysły z moich, jeśli chcesz - na przykład wydaje się, że mój podział na pierścienie jest krótszy, ale jeszcze tego nie próbowałem
ngn
Och, to bardzo fajny podział pierścienia! Lubię to.
zgrep
2

ok , 56 bajtów

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

Na podstawie odpowiedzi ngn .

Wypróbuj online!

concave:1 0 0
   flat:0 0 1
 convex:0 1 0
  mixed:0 0 0
zgrep
źródło
nie ma potrzeby @, jeśli {&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/x)@.=i&|i:&/!2##x}
zamienisz
1

C ++ 17 (gcc) , 411 bajtów

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

Nowy najlepszy wynik! (przynajmniej w momencie publikowania) No cóż, to trochę fajne, ale wciąż C ++.

Wypróbuj online!

Lambda Cbierzestd::vector<std::vector<int>> i zwraca 1 dla wklęsłego, 2 dla wypukłego, 3 dla płaskiego lub 0 dla mieszanego.

Bardziej czytelna wersja kodu, zawierająca opisowe identyfikatory, komentarze, R-> returni I-> intspisane itp .:

#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
źródło
1
Nie sądzę, żeby „fajne” znaczyło, co według ciebie oznacza
tylko