Classer une région par sa pente

16

Définitions

Le k ème anneau d'une matrice carrée de taille N , où 1 ≤ k ≤ plafond (N / 2) est la liste formée par les éléments des k ème et (N-k + 1) ème lignes et colonnes, mais sans le premier et dernier éléments k-1 .

Exemple:

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

Délimité en anneaux:

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

Le premier anneau de ce qui précède est 1,2,3,4,5,1,4,8,3,4,5,6,7,3,8,6, le deuxième est 7,8,9,5,9,1,2,7et le troisième est 6.

Une matrice N par N d'entiers positifs est (pour les besoins de ce défi):

  • concave si tous les entiers du k ème anneau sont strictement supérieurs à ceux du (k + 1) e anneau, où k est tout entier compris entre 1 et N (ceux du premier anneau sont supérieurs à ceux du second, qui sont tour à tour supérieur à ceux du troisième, etc.). Exemple:

    4 5 6 4 7 -> parce que 4,5,6,4,7,4,8,5,5,4,6,5,9,5,5,4 sont tous supérieurs à
    4 3 2 2 4 l'un des 3,2,2,3,2,3,3,2, qui sont tous supérieurs à 1
    5 2 1 3 8
    5 3 3 2 5
    9 5 6 4 5
    
  • plat si tous les entiers de la matrice sont égaux. Un autre exemple (peut-être redondant):

    2 2 2 2
    2 2 2 2
    2 2 2 2
    2 2 2 2
    
  • convexe si tous les entiers du k ème anneau sont strictement inférieurs à ceux du (k + 1) e anneau, où k est tout entier compris entre 1 et N (ceux du premier anneau sont inférieurs à ceux du second, qui sont à son tour inférieur à ceux du troisième, etc.). Exemple:

    1 2 1 -> car 1 et 2 sont tous deux inférieurs à 6
    2 6 2
    1 2 1
    
  • mélangé si la matrice ne satisfait à aucun des critères ci-dessus. Exemple:

    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
    

Défi

Étant donné une matrice carrée d'entiers positifs de taille au moins 3 , classez-la selon les définitions ci-dessus. C'est-à-dire, produire l'une des quatre valeurs cohérentes différentes selon que la matrice est concave, plate, convexe ou mixte.

Vous pouvez concurrencer dans n'importe quel langage de programmation et pouvez prendre des entrées et fournir des sorties par n'importe quelle méthode standard et dans n'importe quel format raisonnable, tout en prenant note que ces failles sont interdites par défaut. Il s'agit de , donc la soumission la plus courte (en octets) pour chaque langue l' emporte.

Cas de test

Voici un tas d'exemples parmi lesquels vous pouvez choisir - j'ai sélectionné 6 de chaque catégorie.

Concave

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

Plat

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

Convexe

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

Mixte

[[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]]
M. Xcoder
la source
Ce défi a déjà été publié dans le bac à sable . Merci à ceux qui y ont donné de précieux commentaires.
M. Xcoder
2
Ce ne serait pas bien d'avoir une conversion de chaîne de tableau vers / depuis les fonctions matricielles à portée de main pour traiter tous ces cas de test dans une variété de langues :)
ngm
@ngm N'ose pas penser que nous n'en avons pas déjà ! : P
M. Xcoder

Réponses:

5

Java (JDK 10) , 247 232 220 octets

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

Essayez-le en ligne!

Les sorties:

  • 1 pour "concave"
  • 2 pour "plat"
  • 3 pour "convexe"
  • 4 pour "mixte"

Non golfé:

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
la source
5

Gelée ,  18 17  16 octets

Je crois qu'il y a beaucoup de potentiel pour que cet effort soit hors-golf

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

Un lien monadique acceptant une liste de listes de nombres qui renvoie une liste d'entiers:

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

Essayez-le en ligne! Ou consultez la suite de tests .

L‘Hpourrait être remplacé par le moins efficace mais atomiquement plus court JÆm.

Comment?

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
la source
5

Python 2 , 219 216 189 176 octets

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

Essayez-le en ligne!

Sorties set([1]), set([0]), set([-1]),ou Falsepour concave, plat, convexe ou mixte, respectivement.

Thx pour: Un énorme 27 octets à partir de quelques optimisations par ovs . Et puis encore 13 octets.

La compréhension de la liste A(due aux ovs) crée une liste des éléments de chaque anneau, triés.

Ensuite, nous comparons les valeurs maxet minentre les anneaux adjacents en examinant les éléments 0th et -1th de chaque liste triée en A. Notez que si, par exemple, Mest concave, minde chaque anneau extérieur doit être supérieur à celui maxde l'anneau le plus intérieur suivant ; et il s'ensuit que celui maxde chaque anneau extérieur sera également supérieur à celui minde l'anneau intérieur suivant.

Si Mest concave, plat ou convexe, l'ensemble de ces min/maxcomparaisons n'aura qu'un seul élément de {-1, 0, 1}; s'il est mélangé, il y aura deux éléments ou plus.

Chas Brown
la source
@ovs: C'est assez col; J'ai sauvé un autre octet en le transformant en une liste de compréhension (et en pensant que cela pourrait être une technique très utile pour d'autres défis similaires).
Chas Brown
Il existe peut-être un moyen de raccourcir la compréhension de la liste, mais une boucle while semble toujours plus courte: 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 octets)
ovs
@ovs: Vous avez omis ,A=()de votre nombre d'octets ...
Chas Brown
Je reçois 174 octets avecA=()
ovs
Ah! Toutes mes excuses, j'ai mal compris. Ceci est différent de votre version antérieure, qui était de la forme: while M: A+= (some expression).
Chas Brown
4

Gelée , 17 octets

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

Renvoie 1 pour concave , 0 pour plat , -1 pour convexe et rien pour mixte .

Essayez-le en ligne!

Dennis
la source
4

JavaScript (ES6), 168 octets

Retour:

  • -1 pour plat
  • 0 pour mixte
  • 1 pour convexe
  • 2 pour concave
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)

Essayez-le en ligne!

Comment?

Minimum et maximum sur chaque anneau

Nous calculons le minimum m et le maximum M sur chaque anneau.

Nous testons si une cellule est située sur un anneau donné en calculant la distance au carré du centre de la matrice sur chaque axe. Prendre la valeur absolue fonctionnerait tout aussi bien, mais la quadrature est plus courte.

Une cellule à (x, y) est situé sur le n anneau -ième (0-indexés, à partir du plus à l'extérieur) , si la formule suivante est fausse :

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

où:

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

Exemple: la cellule (1, 2) est-elle sur le 2ème anneau d'une 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

Drapeaux

À la fin de chaque itération, nous comparons m et M au minimum p et au maximum P de l'anneau précédent et mettons à jour la variable indicateur i en conséquence:

  • i |= 1si m> P
  • i |= 2si M <p
  • nous définissons des bits plus élevés de i si M! = m

À la fin du processus, nous convertissons la valeur finale de i comme suit:

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
la source
4

K (ngn / k) , 100 71 69 octets

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

Essayez-le en ligne!

renvoie 1= concave, ::= plat, -1= convexe, 0= mixte

( ::est utilisé comme espace réservé pour les valeurs manquantes en k)

ngn
la source
Une stratégie différente, utilisant oK:&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/*:'(|+:)\)'-1_(-1_1_+-1_1_)\
zgrep
@zgrep nice! :) n'hésitez pas à poster une réponse séparée et à prendre des idées de la mienne si vous le souhaitez - par exemple, il semble que ma division en anneaux soit plus courte, mais je ne l'ai pas encore essayée en
ok
Ooh, c'est une bague très soignée! Je l'aime.
zgrep
2

oK , 56 octets

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

Basé sur la réponse de ngn .

Essayez-le en ligne!

concave:1 0 0
   flat:0 0 1
 convex:0 1 0
  mixed:0 0 0
zgrep
la source
pas besoin de @ si vous transformez tout en un seul grand lambda:{&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/x)@.=i&|i:&/!2##x}
ngn
1

C ++ 17 (gcc) , 411 octets

#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 nouveau meilleur score! (au moment de la publication, au moins) Oh bien, c'est un peu astucieux, mais toujours en C ++.

Essayez-le en ligne!

Lambda C prend un std::vector<std::vector<int>>et renvoie 1 pour concave, 2 pour convexe, 3 pour plat ou 0 pour mixte.

Une version plus lisible du code, avec des identifiants descriptifs, des commentaires, R-> returnet I-> intécrits, etc.:

#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
la source
1
Je ne pense pas que «astucieux» signifie ce que vous pensez que cela signifie
ASCII uniquement