Classificare una regione in base alla sua pendenza


16

definizioni

Il k esimo anello di una matrice quadrata di dimensione N , dove 1 ≤ k ≤ soffitto (N / 2) è la lista formata dagli elementi del k esimo e (n-k + 1) th righe e colonne, ma senza la primo e ultimo elemento k-1 .

Esempio:

Matrice:

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

Delimitato in anelli:

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

Il primo squillo di quanto sopra è 1,2,3,4,5,1,4,8,3,4,5,6,7,3,8,6, il secondo è 7,8,9,5,9,1,2,7e il terzo è 6.

Una matrice N per N di numeri interi positivi è (ai fini di questa sfida):

  • concavo se tutti gli interi sul k esimo anello sono strettamente maggiore rispetto a quelli di (k + 1) esimo anello, dove k è un numero intero tra 1 e N (quelle del primo anello sono maggiori di quelle del secondo, che sono a sua volta maggiore di quelli del terzo ecc.). Esempio:

    4 5 6 4 7 -> perché 4,5,6,4,7,4,8,5,5,4,6,5,9,5,5,4 sono tutti più alti di
    4 3 2 2 4 qualsiasi di 3,2,2,3,2,3,3,2, che sono tutti superiori a 1
    5 2 1 3 8
    5 3 3 2 5
    9 5 6 4 5
    
  • piatto se tutti gli interi nella matrice sono uguali. Un altro esempio (forse ridondante):

    2 2 2 2
    2 2 2 2
    2 2 2 2
    2 2 2 2
    
  • convesso se tutti gli interi sul k esimo anello sono strettamente inferiore rispetto a quelli di (k + 1) esimo anello, dove k è un numero intero tra 1 e N (quelli del primo anello sono inferiori a quelli del secondo, che sono a sua volta inferiore a quelli del terzo ecc.). Esempio:

    1 2 1 -> perché 1 e 2 sono entrambi inferiori a 6
    2 6 2
    1 2 1
    
  • miscelato se la matrice non soddisfa nessuno dei criteri sopra indicati. Esempio:

    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
    

Sfida

Data una matrice quadrata di numeri interi positivi di dimensione almeno 3 , classificarla secondo le definizioni sopra. Ossia, genera uno dei quattro diversi valori coerenti in base al fatto che la matrice sia concava, piatta, convessa o mista.

Puoi competere in qualsiasi linguaggio di programmazione e prendere input e fornire output attraverso qualsiasi metodo standard e in qualsiasi formato ragionevole, tenendo presente che queste scappatoie sono vietate per impostazione predefinita. Questo è , quindi vince l'invio più breve (in byte) per ogni lingua .

Casi test

Ecco un sacco di esempi tra cui scegliere: ne ho selezionati 6 per ogni categoria.

Concavo

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

Piatto

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

Convesso

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

Misto

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

Questa sfida è stata precedentemente pubblicata nella Sandbox . Grazie a coloro che hanno dato un prezioso feedback lì.
Mr. Xcoder,

2
Ragazzo, non sarebbe bello avere una conversione di stringa array-of-array in / da funzioni matrice utile per elaborare tutti quei casi di test in una varietà di lingue :)
ngm

@ngm Non osare pensare che non ne abbiamo già uno ! : P
Mr. Xcoder,

Risposte:


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

Provalo online!

Uscite:

  • 1 per "concavo"
  • 2 per "piatto"
  • 3 per "convesso"
  • 4 per "misto"

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

Gelatina ,  18 17  16 byte

Credo che ci sia un grande potenziale per questo sforzo da superare

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

Un collegamento monadico che accetta un elenco di elenchi di numeri che restituisce un elenco di numeri interi:

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

Provalo online! Oppure vedi la suite di test .

L‘Hpotrebbe essere sostituito con il meno efficiente ma atomicamente più breve JÆm.

Come?

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

Provalo online!

Uscite set([1]), set([0]), set([-1]),o Falseper concavo, piatto, convesso o misto, rispettivamente.

Grazie per: un enorme 27 byte da alcune ottimizzazioni di ovs . E poi altri 13 byte dopo.

La comprensione dell'elenco A(dovuta a ovs) crea un elenco degli elementi di ciascun anello, ordinati.

Successivamente, confrontiamo i valori maxe mintra gli anelli adiacenti osservando gli elementi 0th e -1th di ciascun elenco ordinato in A. Nota che se, per esempio, Mè concavo, minogni anello esterno deve essere maggiore maxdel successivo anello più interno ; e quindi segue che maxogni anello esterno sarà anche maggiore mindel successivo anello più interno.

Se Mè concavo, piatto o convesso, l'insieme di questi min/maxconfronti avrà solo 1 elemento da {-1, 0, 1}; se è misto, ci saranno due o più elementi.


@ovs: Questo è piuttosto col; Ho salvato un altro byte trasformandolo in una comprensione dell'elenco (e pensando che questa potrebbe essere una tecnica molto utile per altre sfide simili).
Chas Brown,

Forse c'è un modo per abbreviare la comprensione dell'elenco, ma un ciclo while sembra ancora essere più breve: 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: Hai omesso ,A=()il conteggio dei byte ...
Chas Brown

Ottengo 174 byte conA=()
ovs il

Ah! Mi scuso, ho capito male. Questo è diverso rispetto la versione precedente, che è stato di forma: while M: A+= (some expression).
Chas Brown,


4

JavaScript (ES6), 168 byte

Ritorna:

  • -1 per appartamento
  • 0 per misto
  • 1 per convesso
  • 2 per concavo
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)

Provalo online!

Come?

Minimo e massimo su ciascun anello

Calcoliamo il minimo me il massimo M su ogni anello.

Testiamo se una cella si trova su un determinato anello calcolando la distanza quadrata dal centro della matrice su ciascun asse. Prendere il valore assoluto funzionerebbe altrettanto bene, ma la quadratura è più breve.

Una cella in (x, y) si trova sull'anello n -esimo (0-indicizzato, a partire da quello più esterno) se la seguente formula è falsa :

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

dove:

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

Esempio: la cella (1, 2) si trova sul 2 ° anello di una matrice 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

bandiere

Alla fine di ogni iterazione, confrontiamo m e M con il minimo p e il massimo P dell'anello precedente e aggiorniamo la variabile flag i di conseguenza:

  • i |= 1se m> P
  • i |= 2se M <p
  • impostiamo bit più alti di i se M! = m

Alla fine del processo, convertiamo il valore finale di i come segue:

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

Provalo online!

restituisce 1= concavo, ::= piatto, -1= convesso, 0= misto

( ::viene utilizzato come segnaposto per i valori mancanti in k)


Una strategia diversa, usando oK:&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/*:'(|+:)\)'-1_(-1_1_+-1_1_)\
zgrep,

@zgrep nice! :) sentiti libero di postare come una risposta separata e prendere le mie idee se vuoi - per esempio sembra che la mia divisione in anelli sia più breve, ma non l'ho ancora provata in oK
ngn


Ooh, è una divisione molto ordinata! Mi piace.
zgrep,

2

ok , 56 byte

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

Basato sulla risposta di Ngn .

Provalo online!

concave:1 0 0
   flat:0 0 1
 convex:0 1 0
  mixed:0 0 0

non c'è bisogno di @ se trasformi tutto in un'unica grande lambda:{&/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;};

Un nuovo punteggio elevato! (almeno al momento della pubblicazione) Oh beh, è ​​un po 'elegante, ma comunque C ++.

Provalo online!

Lambda Cprende a std::vector<std::vector<int>>e restituisce 1 per concavo, 2 per convesso, 3 per piatto o 0 per misto.

Una versione più leggibile del codice, con identificativi descrittivi, commenti, R-> returneI -> intscritti, ecc .:

#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
Non credo che "elegante" significhi ciò che pensi significhi
ASCII, solo il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.