Dobre uma matriz!

13

Dada uma matriz, some seus valores para cima / baixo ou esquerda / direita para formar um X, dobre-o e retorne a lista. Eu descrevo o algoritmo aqui:

Algoritmo

Sua entrada será uma matriz quadrada de números ímpares dentro da capacidade numérica razoável do seu idioma.

Vamos tomar a seguinte matriz como exemplo:

1 2 3 2 1
0 3 2 3 0
4 2 5 6 3
7 4 7 9 4
0 6 7 2 5

Primeiro, adicione todos os números ao número mais próximo que estiver na diagonal principal ou antidiagonal. Ou seja, divida a matriz em quatro seções ao longo da diagonal principal e antidiagonal e, em seguida, some todos os números em cada seção em direção ao centro, da seguinte forma:

1   2   3   2   1
    ↓   ↓   ↓    
0 → 3   2   3 ← 0
        ↓        
4 → 2 → 5 ← 6 ← 3
        ↑        
7 → 4   7   9 ← 4
    ↑   ↑   ↑    
0   6   7   2   5

Esta etapa fornece o seguinte resultado:

1        1
  5    5
    39
  17  15
0        5

Em seguida, dobramos, achatando o X e entrelaçando os elementos com a parte superior esquerda primeiro e a parte inferior esquerda por último. Isso fornece o seguinte resultado:

1, 0, 5, 17, 39, 5, 15, 1, 5

Você pode imaginar isso esticando a diagonal principal e girando-a no sentido anti-horário.

Esse é o resultado final.

Desafio

Implemente esse algoritmo. Aplicam-se brechas padrão. Todos os formatos razoáveis ​​de E / S são aceitáveis.

Casos de teste

Input
Output

1 2 3 2 1
0 3 2 3 0
4 2 5 6 3
7 4 7 9 4
0 6 7 2 5

1, 0, 5, 17, 39, 5, 15, 1, 5

1 2 3 4 5
5 4 3 2 1
1 3 5 7 9
0 9 8 7 6
6 7 8 9 0

1, 6, 11, 16, 47, 7, 22, 5, 0

1 3 7 4 8 5 3
8 4 7 5 3 8 0
0 6 3 6 9 8 4
2 6 5 8 7 4 2
0 6 4 3 2 7 5
0 6 7 8 5 7 4
8 5 3 2 6 7 9

1, 8, 15, 11, 23, 20, 62, 32, 25, 13, 18, 3, 9
HyperNeutrino
fonte
Você pode adicionar um caso de teste de matriz "não 5 × 5"?
totallyhuman
1
@icrieverytim aqui vai você
HyperNeutrino 11/11

Respostas:

7

JavaScript, 113 bytes

s=>(l=s.length-1,a=[],s.map((v,y)=>v.map((n,x)=>a[q=2*[x,y,l-y].sort((u,v)=>u-v)[1]+(y>l/2),q-=q>l]=~~a[q]+n)),a)

tsh
fonte
Umm .. por que o ~~? Eles se neutralizam, então não há necessidade deles.
Kevin Cruijssen 11/11
2
@KevinCruijssen ~~undefined==0, então isso é mais do que golfe (a[q]||0).
Neil
@ Neil Ah, não tinha pensado undefined. Quando copiei o caso de teste tsh usado, notei que funcionava sem o ~~. E como ~~xé semelhante a -(-x)neutralizar um ao outro, achei que de alguma forma foi colocado ali por acidente. Obrigado pela correção.
Kevin Cruijssen
5

Geléia , 25 23 21 bytes

AṂ×ṠṚ
LHŒRṗ2Ç€ḅLĠịFS€

Experimente online!

Versão alternativa, 19 bytes

AṂ×ṠṚ
LHŒRṗ2Ç€ĠịFS€

Isso não costumava funcionar porque se Ġcomportava incorretamente para matrizes aninhadas. A única diferença é que os pares [q, p] mencionados em Como funciona são classificados lexicograficamente em vez de os mapear para p + nq antes da classificação.

Experimente online!

fundo

Começamos substituindo seus elementos por coordenadas, aumentando para a esquerda e para baixo e colocando (0, 0) no centro da matriz.

Para uma matriz 7x7 M , obtemos as seguintes coordenadas.

(-3,-3) (-3,-2) (-3,-1) (-3, 0) (-3, 1) (-3, 2) (-3, 3)
(-2,-3) (-2,-2) (-2,-1) (-2, 0) (-2, 1) (-2, 2) (-2, 3)
(-1,-3) (-1,-2) (-1,-1) (-1, 0) (-1, 1) (-1, 2) (-1, 3)
( 0,-3) ( 0,-2) ( 0,-1) ( 0, 0) ( 0, 1) ( 0, 2) ( 0, 3)
( 1,-3) ( 1,-2) ( 1,-1) ( 1, 0) ( 1, 1) ( 1, 2) ( 1, 3)
( 2,-3) ( 2,-2) ( 2,-1) ( 2, 0) ( 2, 1) ( 2, 2) ( 2, 3)
( 3,-3) ( 3,-2) ( 3,-1) ( 3, 0) ( 3, 1) ( 3, 2) ( 3, 3)

Agora calculamos o valor absoluto mínimo de cada par de coordenadas e multiplicamos os sinais de ambas as coordenadas por ele, mapeando (i, j) para (sinal (i) m, sinal (j) m) , em que m = min (| i | , | j |) .

(-3,-3) (-2,-2) (-1,-1) ( 0, 0) (-1, 1) (-2, 2) (-3, 3)
(-2,-2) (-2,-2) (-1,-1) ( 0, 0) (-1, 1) (-2, 2) (-2, 2)
(-1,-1) (-1,-1) (-1,-1) ( 0, 0) (-1, 1) (-1, 1) (-1, 1)
( 0, 0) ( 0, 0) ( 0, 0) ( 0, 0) ( 0, 0) ( 0, 0) ( 0, 0)
( 1,-1) ( 1,-1) ( 1,-1) ( 0, 0) ( 1, 1) ( 1, 1) ( 1, 1)
( 2,-2) ( 2,-2) ( 1,-1) ( 0, 0) ( 1, 1) ( 2, 2) ( 2, 2)
( 3,-3) ( 2,-2) ( 1,-1) ( 0, 0) ( 1, 1) ( 2, 2) ( 3, 3)

Elementos da matriz que correspondem ao mesmo par devem ser somados. Para determinar a ordem das somas, que mapear cada par (p, q) a p + nq , onde n é o número de linhas / colunas de M .

-24 -16  -8   0   6  12  18
-16 -16  -8   0   6  12  12
 -8  -8  -8   0   6   6   6
  0   0   0   0   0   0   0
 -6  -6  -6   0   8   8   8
-12 -12  -6   0   8  16  16
-18 -12  -6   0   8  16  24

A ordem das somas corresponde à ordem dos números inteiros e corresponde aos seus summands.

Como funciona

LHŒRṗ2Ç€ḅLĠịFS€  Main link. Argument: M (matrix)

L                Compute n, the length (number of rows) of M.
 H               Halve it.
  ŒR             Symmetric range; map t to [-int(t), ..., 0, int(t)].
    ṗ2           Compute the second Cartesian power, yielding all pairs [i, j]
                 with -t ≤ i, j ≤ t.
      ǀ         Map the helper link over the resulting array of pairs.
         L       Yield n.
        ḅ        Unbase; map each pair [q, p] to (p + nq).
          Ġ      Group the indices of the resulting array of n² integers by their
                 corresponding values, ordering the groups by the values.
            F    Flatten M.
           ị     Index into the serialized matrix.
             S€  Compute the sum of each group.


AṂ×ṠṚ            Helper link. Argument: [i, j] (index pair)

A                Absolute value; yield [|i|, |j|].
 Ṃ               Minimum; yield m := min(|i|, |j|).
   Ṡ             Sign; yield [sign(i), sign(j)].
  ×              Multiply; yield [p, q] := [sign(i)m, sign(j)m].
    Ṛ            Reverse; yield [q, p].
Dennis
fonte
5
isto é brilhante.
Uriel
5

Python, 159 158 bytes

def f(m):l=len(m)-1;r=range(1,l);return m[0][::l]+f([[sum(m[x][1%y*y:(y>l-2)-~y])+m[0][y]*(x<2)+m[l][y]*(x>l-2)for y in r]for x in r])+m[l][::l]if l else m[0]

Experimente online!

KSab
fonte
1
y+1+(y>l-2)pode ser (y>l-2)-~y.
Jonathan Frech
2

APL (Dyalog) , 60 bytes *

Em colaboração com meu colega Marshall .

Prefixo anônimo lambda. Toma matriz como argumento e retorna vetor. Assume ⎕IO ( I ndex O rigin) como zero, o que é padrão em muitos sistemas.

{(,⍉{+/,(s×-×⍺)↓⍵×i∊¨⍨s←⌊⊃r÷2}⌺r⊢⍵)/⍨,(⊢∨⌽)=/¨i←⍳r←⍴⍵}

Experimente online!

{... } lambda anônima; é o argumento correto (como a letra mais à direita do alfabeto grego):

⍴⍵ forma do argumento (lista de dois elementos idênticos)

r← armazenar como r(como em r ho)

 todos os índices de uma matriz desse tamanho, ou seja (0 0), (0 1)

i← armazenar em i(como em i ota)

=/¨ Booleano onde as coordenadas são iguais (ou seja, a diagonal)

() Aplique esta função de prefixo tácito anônimo:

   reverter o argumento

  ⊢∨ OU que, com o argumento não modificado

, passear (endireitar em lista simples)

 Agora temos uma máscara booleana para as diagonais.

()/⍨ Use isso para filtrar o seguinte:

  ⊢⍵ produzir (separar r) o argumento

  {}⌺r Chame o seguinte infixo anônimo lambda em cada elemento, com o r-neighbourhood (preenchido com zeros, conforme necessário) como argumento correto ( ) e uma lista de dois elementos de número preenchido de linhas, colunas (negativo para baixo / direito, zero para nenhum) como argumento à esquerda ( ):

   r÷2 dividir rcom dois

    escolha o primeiro elemento (eles são idênticos)

    andar isso

   s← armazenar como s(para s hape)

   i∊⍨¨ para cada elemento de i, Boolean se sfor um membro dele

   ⍵× multiplicar a vizinhança com isso

   ()↓ Solte o seguinte número de linhas e colunas (negativo para inferior / direita):

    ×⍺ signum do argumento esquerdo (ou seja, a direção dos forros)

    - negar

     multiplicar scom isso

   , ravel (endireite na lista)

   +/ soma (mais redução)

Agora temos uma matriz completa de somas, mas precisamos filtrar todos os valores lidos em colunas.

   transpor

  , passear (endireitar em lista simples)


* Contando como ⎕U233A . Experimente online!

Adão
fonte