Klassifizieren Sie eine Region anhand ihrer Neigung

16

Definitionen

Der k- te Ring einer quadratischen Matrix der Größe N , wobei 1 ≤ k ≤ Decke (N / 2) die Liste ist, die durch die Elemente der k- ten und (N-k + 1) -ten Zeilen und Spalten gebildet wird, jedoch ohne die erstes und letztes k-1 Element.

Beispiel:

Matrix:

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

In Ringen getrennt:

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

Der erste Ring von oben ist 1,2,3,4,5,1,4,8,3,4,5,6,7,3,8,6, der zweite ist 7,8,9,5,9,1,2,7und der dritte ist 6.

Eine N x N- Matrix positiver Ganzzahlen ist (für die Zwecke dieser Herausforderung):

  • konkav, wenn alle ganzen Zahlen im k- ten Ring genau größer sind als die im (k + 1) -ten Ring, wobei k eine ganze Zahl zwischen 1 und N ist (die im ersten Ring sind größer als die im zweiten Ring) wiederum größer als die auf der dritten usw.). Beispiel:

    4 5 6 4 7 -> weil 4,5,6,4,7,4,8,5,5,4,6,5,9,5,5,4 alle höher sind als
    4 3 2 2 4 beliebig von 3,2,2,3,2,3,3,2, die alle höher als 1 sind
    5 2 1 3 8
    5 3 3 2 5
    9 5 6 4 5
    
  • flach, wenn alle ganzen Zahlen in der Matrix gleich sind. Ein anderes Beispiel (vielleicht überflüssig):

    2 2 2 2
    2 2 2 2
    2 2 2 2
    2 2 2 2
    
  • konvex, wenn alle ganzen Zahlen im k- ten Ring genau niedriger sind als die im (k + 1) -ten Ring, wobei k eine ganze Zahl zwischen 1 und N ist (die im ersten Ring sind niedriger als die im zweiten Ring) wiederum niedriger als beim dritten usw.). Beispiel:

    1 2 1 -> weil 1 und 2 beide kleiner als 6 sind
    2 6 2
    1 2 1
    
  • gemischt, wenn die Matrix keines der oben genannten Kriterien erfüllt. Beispiel:

    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
    

Herausforderung

Bei einer quadratischen Matrix positiver Ganzzahlen mit einer Größe von mindestens 3 klassifizieren Sie diese gemäß den obigen Definitionen. Das heißt, Sie können einen von vier verschiedenen konsistenten Werten ausgeben, je nachdem, ob die Matrix konkav, flach, konvex oder gemischt ist.

Sie können in jeder Programmiersprache antreten und Eingaben und Ausgaben mit jeder Standardmethode und in jedem vernünftigen Format vornehmen. Beachten Sie jedoch, dass diese Lücken standardmäßig verboten sind. Dies ist , daher gewinnt die kürzeste Übermittlung (in Bytes) für jede Sprache .

Testfälle

Hier sind einige Beispiele zur Auswahl - ich habe aus jeder Kategorie 6 ausgewählt.

Konkav

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

Eben

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

Konvex

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

Gemischt

[[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]]
Mr. Xcoder
quelle
Diese Herausforderung wurde zuvor in der Sandbox veröffentlicht . Vielen Dank an alle, die dort wertvolles Feedback gegeben haben.
Mr. Xcoder
2
Junge, wäre es nicht schön, eine Array-of-Array-String-Konvertierung in / aus Matrix- Funktionen zur Verfügung zu haben, um all diese Testfälle in einer Vielzahl von Sprachen zu verarbeiten :)
ngm
@ngm Wagen Sie es nicht glauben wir eine noch nicht haben ! : P
Mr. Xcoder

Antworten:

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

Probieren Sie es online!

Ausgänge:

  • 1 für "konkav"
  • 2 für "flat"
  • 3 für "konvex"
  • 4 für "gemischt"

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

Jelly ,  18 17  16 Bytes

Ich glaube, es gibt viel Potenzial für diese Bemühungen, um herausgolfen zu werden

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

Ein monadischer Link, der eine Liste von Zahlenlisten akzeptiert, die eine Liste von ganzen Zahlen zurückgibt:

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

Probieren Sie es online! Oder sehen Sie sich die Testsuite an .

L‘Hkönnte durch die weniger effiziente, aber atomar kürzere ersetzt werden JÆm.

Wie?

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
quelle
5

Python 2 , 219 216 189 176 Bytes

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

Probieren Sie es online!

Ausgänge set([1]), set([0]), set([-1]),oder Falsefür konkav, flach, konvex oder gemischt.

Thx für: Satte 27 Bytes aus ein paar Optimierungen durch Ovs . Und danach noch 13 Bytes.

Das Listenverständnis A(aufgrund von ovs) erstellt eine Liste der Elemente jedes Rings, sortiert.

Als nächstes vergleichen wir die Werte maxund minzwischen benachbarten Ringen, indem wir uns die 0th- und -1th-Elemente jeder sortierten Liste in A ansehen. Wenn beispielsweise Mkonkav ist, minmuss jeder äußere Ring größer sein als maxder des nächst innersten Rings ; und es folgt dann, dass maxjeder äußere Ring auch größer sein wird als minder nächst innerste Ring.

Wenn Mkonkav, flach oder konvex ist, enthält die Menge dieser min/maxVergleiche nur 1 Element von {-1, 0, 1}; Wenn es gemischt ist, gibt es zwei oder mehr Elemente.

Chas Brown
quelle
@ovs: Das ist ziemlich col; Ich habe ein weiteres Byte gespeichert, indem ich es in ein Listenverständnis umgewandelt habe (und dachte, dass dies eine sehr nützliche Technik für andere ähnliche Herausforderungen sein könnte).
Chas Brown
Vielleicht gibt es eine Möglichkeit, das Listenverständnis zu verkürzen, aber eine while-Schleife scheint immer noch kürzer zu sein: 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: Sie haben ,A=()von Ihrer Byteanzahl weggelassen ...
Chas Brown
Ich bekomme 174 Bytes mitA=()
ovs
Ah! Entschuldigung, ich habe es falsch verstanden. Dies ist anders als die ältere Version, die von der Form war: while M: A+= (some expression).
Chas Brown
4

Gelee , 17 Bytes

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

Gibt 1 für konkav , 0 für flach , -1 für konvex und nichts für gemischt zurück .

Probieren Sie es online!

Dennis
quelle
4

JavaScript (ES6), 168 Byte

Kehrt zurück:

  • -1 für wohnung
  • 0 für gemischt
  • 1 für konvex
  • 2 für konkav
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)

Probieren Sie es online!

Wie?

Minimum und Maximum bei jedem Ring

Wir berechnen das Minimum m und das Maximum M für jeden Ring.

Wir testen, ob sich eine Zelle auf einem bestimmten Ring befindet, indem wir den quadratischen Abstand vom Mittelpunkt der Matrix auf jeder Achse berechnen. Den absoluten Wert zu nehmen würde genauso gut funktionieren, aber das Quadrieren ist kürzer.

Eine Zelle bei (x, y) befindet sich auf dem n- ten Ring (0-indiziert, beginnend mit dem äußersten), wenn die folgende Formel falsch ist :

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

wo:

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

Beispiel: Befindet sich die Zelle (1, 2) im 2. Ring einer 6x6-Matrix?

  | 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

Flaggen

Am Ende jeder Iteration vergleichen wir m und M mit dem Minimum p und dem Maximum P des vorherigen Rings und aktualisieren die Flag-Variable i entsprechend:

  • i |= 1wenn m> P
  • i |= 2wenn M <p
  • wir setzen höhere Bits von i, wenn M! = m

Am Ende des Prozesses konvertieren wir den Endwert von i wie folgt:

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
quelle
4

K (ngn / k) , 100 71 69 Bytes

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

Probieren Sie es online!

Gibt 1= konkav, ::= flach, -1= konvex, 0= gemischt zurück

( ::wird als Platzhalter für fehlende Werte in k verwendet)

ngn
quelle
Eine andere Strategie mit oK:&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/*:'(|+:)\)'-1_(-1_1_+-1_1_)\
zgrep
@zgrep schön! :) Fühlen Sie sich frei, als separate Antwort zu posten und Ideen von mir zu übernehmen, wenn Sie möchten - zum Beispiel scheint es, dass meine Aufteilung in Ringe kürzer ist, aber ich habe es noch nicht in
OK
Oh, das ist eine sehr schöne Ringteilung! Ich mag das.
zgrep
2

in Ordnung , 56 bytes

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

Basierend auf der Antwort von ngn .

Probieren Sie es online!

concave:1 0 0
   flat:0 0 1
 convex:0 1 0
  mixed:0 0 0
zgrep
quelle
@ ist nicht erforderlich, wenn Sie alles in einen großen Lambda {&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/x)@.=i&|i:&/!2##x}
verwandeln
1

C ++ 17 (gcc) , 411 Bytes

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

Ein neuer Highscore! (Zum Zeitpunkt der Veröffentlichung zumindest) Na ja, es ist ein bisschen raffiniert, aber immer noch C ++.

Probieren Sie es online!

Lambda Cnimmt a std::vector<std::vector<int>>und gibt 1 für konkav, 2 für konvex, 3 für flach oder 0 für gemischt zurück.

Eine besser lesbare Version des Codes mit beschreibenden Bezeichnern, Kommentaren, R-> returnund I-> intausgeschriebenen usw .:

#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
quelle
1
Ich denke nicht, dass 'nifty' bedeutet, was Sie denken, dass es bedeutet
ASCII