Identifique todas as (anti) diagonais com valores duplicados

17

Desafio:

Dada uma entrada de matriz, determine a quantidade de diagonais e antiagonais com números duplicados.
Portanto, se tivermos uma matriz como esta:

[[aa,ab,ac,ad,ae,af],
 [ba,bb,bc,bd,be,bf],
 [ca,cb,cc,cd,ce,cf],
 [da,db,dc,dd,de,df]]

Todas as diagonais e antiagonais seriam:

[[aa],[ab,ba],[ac,bb,ca],[ad,bc,cb,da],[ae,bd,cc,db],[af,be,cd,dc],[bf,ce,dd],[cf,de],[df],
 [af],[ae,bf],[ad,be,cf],[ac,bd,ce,df],[ab,bc,cd,de],[aa,bb,cc,dd],[ba,cb,dc],[ca,db],[da]]

Exemplo:

[[1,2,1,2,1,2],
 [1,2,3,4,5,6],
 [6,5,4,3,2,1],
 [2,1,2,1,2,1]]

Todas as diagonais e antiagonais seriam:

[[1],[2,1],[1,2,6],[2,3,5,2],[1,4,4,1],[2,5,3,2],[6,2,1],[1,2],[1],
 [2],[1,6],[2,5,1],[1,4,2,1],[2,3,3,2],[1,2,4,1],[1,5,2],[6,1],[2]]

Removendo todas as diagonais e antiagonais que contêm apenas números exclusivos:

[[2,3,5,2],[1,4,4,1],[2,5,3,2],[1,4,2,1],[2,3,3,2],[1,2,4,1]]

Portanto, a saída é a quantidade de diagonais e antiagonais que contêm números duplicados:

6

Regras do desafio:

  • Se a matriz de entrada estiver vazia, contiver apenas 1 número ou apenas números únicos em toda a matriz, a saída será sempre 0.
  • A entrada é garantida para conter apenas dígitos positivos [1,9](a menos que esteja completamente vazia).
  • A matriz sempre será retangular (ou seja, todas as linhas têm o mesmo comprimento).
  • A E / S é flexível. A entrada pode ser tomada como uma lista de listas de números inteiros, ou uma matriz 2D de números inteiros, ou um objeto Matrix, como uma string, etc. etc. Você também pode usar uma ou ambas as dimensões da matriz como entrada adicional se ele salvasse bytes no idioma de sua escolha.

Regras gerais:

  • Isso é , então a resposta mais curta em bytes vence.
    Não permita que idiomas com código de golfe o desencorajem a postar respostas com idiomas que não sejam codegolf. Tente encontrar uma resposta o mais curta possível para 'qualquer' linguagem de programação.
  • As regras padrão se aplicam à sua resposta com as regras de E / S padrão , para que você possa usar STDIN / STDOUT, funções / método com os parâmetros adequados e programas completos do tipo retorno. Sua chamada.
  • As brechas padrão são proibidas.
  • Se possível, adicione um link com um teste para o seu código (ou seja, TIO ).
  • Além disso, é altamente recomendável adicionar uma explicação para sua resposta.

Casos de teste:

Input:                     Output:

[[1,2,1,2,1,2],            6
 [1,2,3,4,5,6],
 [6,5,4,3,2,1],
 [2,1,2,1,2,1]]

[[]]                       0

[[1,2],                    0
 [3,4]]

[[1,1],                    2
 [1,1]]

[[9,9,9],                  6
 [9,9,9],
 [9,9,9]]

[[7,7,7,7],                8
 [7,7,7,7],
 [7,7,7,7]]

[[1,1,1],                  1
 [2,3,4],
 [2,5,1]]

[[1,8,4,2,9,4,4,4],        12
 [5,1,2,7,7,4,2,3],
 [1,4,5,2,4,2,3,8],
 [8,5,4,2,3,4,1,5]]

[[1,2,3,4],                4
 [5,6,6,7],
 [8,6,6,9],
 [8,7,6,5]]
Kevin Cruijssen
fonte

Respostas:

4

Gelatina , 10 bytes

ŒD;ŒdQƑÐḟL

Experimente online! ou Confira a suíte de testes!

Alternativas:

ŒD;ŒdQƑ€¬S
ŒD;ŒdQƑ€ċ0

Como funciona?

ŒD;ŒdQƑÐḟL – Monadic link / Full program.
  ;        – Join:
ŒD           – The diagonals
             with
   Œd        – The anti-diagonals.
       Ðḟ  – Discard the lists that are not:
     QƑ      – Invariant under deduplication.
         L – Length (count them).
Mr. Xcoder
fonte
10

R , 92 86 82 78 bytes

function(m,x=row(m),y=col(m),`|`=split,`^`=Map)sum(max^table^c(m|x-y,m|x+y)>1)

Experimente online!

Explicação

xy

x-y

0 -1 -2 -3 1 0 -1 -2 2 1 0 -1 3 2 1 0

x+y

2 3 4 5 3 4 5 6 4 5 6 7 5 6 7 8

Agora, split(m, x-y)e split(m, x+y)produza as listas reais de diagonais e anti-diagonais, nas quais nos juntamos.

Finalmente, contamos as entradas da lista resultante em que duplicatas estão presentes.

Obrigado pelos bytes salvos:

-4 por CriminallyVulgar
-4 por digEmAll

Kirill L.
fonte
1
Acho que posso adicionar rowe colà minha lista de 'funções extremamente situacionais'. Solução realmente inteligente.
CriminallyVulgar
1
Eu acho que você pode mover a c(m|x-y,m|x+y)linha reta para a chamada sapply, remover a l=peça. Não vejo nenhum teste com falha. Experimente online!
CriminallyVulgar
Sim, isso mesmo, perdi que, depois do meu primeiro golfe, lrestava apenas uma instância.
Kirill L.
1
Eles devem ter adicionado as funções rowe columnao R esta manhã, porque nunca ouvi falar deles.
ngm 25/01
5

J , 21 20 bytes

-1 byte graças a Jonah!

1#.|.,&((~:&#~.)/.)]

Experimente online!

Explicação:

1#.                   find the sum of the  
     ,                concatenation of
       (          )   the result of the verb in the parentheses applied to
                   ]  the input
      &               and
   |.                 the reversed input
        (      )/.    for each diagonal
         ~:&#~.       check if all elements are unique and negate the result 
Galen Ivanov
fonte
1
é meio louco que você não possa fazer melhor do que (-.@-:~.)"os itens exclusivos não combinam" em J, mas eu já encontrei isso muitas vezes também e acho que você não pode ... nós temos =e ~:, por um lado mão e -:e <this is missing>.
Jonah
Na verdade, conseguiu raspar mais 1 byte off: 1#.|.,&((~:&#~.)/.)]. Experimente online!
Jonah
@ Jonah: uso legal de &, obrigado!
Galen Ivanov
5

Japonês , 31 bytes

ËcUî
ËéEÃÕc¡XéYnÃÕ mf fÊk_eZâÃl

Experimente todos os casos de teste

Explicação:

Ëc                            #Pad each row...
  Uî                          #With a number of 0s equal to the number of rows

ËéEÃÕ                         #Get the anti-diagonals:
ËéEÃ                          # Rotate each row right a number of times equal to the row's index
    Õ                         # Get the resulting columns
     c                        #Add to that...
      ¡XéYnÃÕ                 #The diagonals:
      ¡XéYnà                  # Rotate each row left a number of times equal to the row's index
            Õ                 # Get the resulting columns
              mf              #Remove the 0s from each diagonal
                 fÊ           #Remove the all-0 diagonals
                   k_   Ã     #Remove the ones where:
                     eZâ      # The list contains no duplicates
                         l    #Return the number of remaining diagonals

Também tentei uma versão baseada na resposta de Kirill L. Haskell, mas não consegui encontrar uma boa maneira de "agrupar por uma função dos índices X e Y" e a alternativa que encontrei não era boa o suficiente.

Kamil Drakari
fonte
31 bytes
Shaggy
4

JavaScript (ES6),  107 105 101  98 bytes

f=(m,d=s=1)=>(m+0)[s-=~d/2]?m.some(o=(r,y)=>!r.every((v,x)=>x+d*y+m.length-s?1:o[v]^=1))+f(m,-d):0

Experimente online!

Nota

Da maneira como esse código é jogado, a anti-diagonal que consiste na única célula inferior esquerda nunca é testada. Tudo bem porque não pode conter valores duplicados.

Comentado

f = (                    // f = recursive function taking:
  m,                     //   m[] = input matrix
  d =                    //   d   = direction (1 for anti-diagonal or -1 for diagonal)
  s = 1                  //   s   = expected diagonal ID, which is defined as either the sum
) =>                     //         or the difference of x and y + the length of a row
  (m + 0)[               //
    s -= ~d / 2          // increment s if d = -1 or leave it unchanged otherwise
  ] ?                    // if s is less than twice the total number of cells:
    m.some(o =           //   o = object used to store encountered values in this diagonal
    (r, y) =>            //   for each row r[] at position y in m[]:
      !r.every((v, x) => //     for each cell of value v at position x in r[]:
        x + d * y +      //       x + d * y + m.length is the ID of the diagonal
        m.length - s ?   //       if it's not equal to the one we're looking for:
          1              //         yield 1
        :                //       else:
          o[v] ^= 1      //         toggle o[v]; if it's equal to 0, v is a duplicate and
                         //         every() fails which -- in turn -- makes some() succeed
      )                  //     end of every()
    )                    //   end of some()
    + f(m, -d)           //   add the result of a recursive call in the opposite direction
  :                      // else:
    0                    //   stop recursion
Arnauld
fonte
4

05AB1E , 25 bytes

í‚εεygÅ0«NFÁ]€ø`«ʒ0KDÙÊ}g

Experimente online! ou como um conjunto de testes

Explicação

í                          # reverse each row in input
 ‚                         # and pair with the input
  ε                        # for each matrix
   ε                       # for each row in the matrix
    ygÅ0«                  # append len(row) zeroes
         NFÁ               # and rotate it index(row) elements to the right
            ]              # end loops
             €ø            # transpose each matrix
               `«          # append them together
                 ʒ     }   # filter, keep only rows that
                  0K       # when zeroes are removed
                    DÙÊ    # are not equal to themselves without duplicate values                           
                        g  # push length of the result

Sinto como se tivesse perdido algo aqui.
Precisa tentar jogar isso mais tarde.

Emigna
fonte
1
Não ajuda em nada, mas rotate N leftseria N._agora. Então í‚εεygÅ0«N._]também funciona. Também é possível remover o achatamento com essa nova alteração ... embora ainda não haja economia de bytes:í‚vyεygÅ0«N._}ø}«ʒ0KDÙÊ}g
Magic Octopus Urn
1
@MagicOctopusUrn: Interessante. Eu tinha perdido esse comando. Apenas uma esquerda embora. Isso é estranho.
Emigna 29/01
1
@ Emigna Você pode dar certo, N(._eu acho, mas o seu NFÁ}é o mesmo comprimento e, nesse caso, ainda mais curto, devido ao ]fechamento do loop e dos mapas simultaneamente. No geral, o uso de ._só é útil quando você sai para salvar 1 byte, em comparação com NFÀ}.
Kevin Cruijssen 31/01
@KevinCruijssen: Ah, legal. Embora, como você diz, não seja muito útil.
Emigna 31/01
3

Python 2 , 144 136 bytes

lambda m:sum(l(set(d))<l(d)for d in[[r[i*x+o]for i,r in enumerate(m)if-1<i*x+o<l(r)]for o in range(-l(`m`),l(`m`))for x in[-1,1]])
l=len

Experimente online!

TFeld
fonte
3

Oitava , 98 bytes

@(A)nnz([(q=@(Q)arrayfun(@(n)nnz(z=diag(Q,n))-nnz(unique(z)),-([m,n]=size(Q)):n))(A),q(rot90(A))])

Experimente online!

Sanchises
fonte
1
As matrizes são realmente divertidas? ; p
Kevin Cruijssen 25/01
E obrigado por preparar os casos de teste no formato Octave!
Luis Mendo
2
@KevinCruijssen Não apenas arrays! Você também pode ter cellfun, e para os masoquistas structfun. No Octave, é um loop for ou having fun!
Sanchises
E não se esqueça de b-sx-fun!
Luis Mendo
3

Haskell, 118 112 bytes

import Data.List
r#(a:b)=sum[1|(/=)=<<nub$[h|h:_<-a:r]]+[t|_:t<-a:r]#b
[]#_=0
a#_=a#[[]]
h x=[]#x+[]#(reverse x)

Experimente online!

r#(a:b)                      -- function '#' calculates the ant-diagonals of a matrix
                             -- where 'a' is the first row and 'b' all the others
                             -- as we recursively walk down the rows of the matrix,
                             -- 'r' holds the rows from before with the respective
                             -- head dropped
                             --
          [h|h:_<-a:r]       -- if the heads of the the current row and the rows
                             -- before
       (/=)=<<nub$           -- contain duplicates
    [1|                ]     -- make a singleton list [1] (else the empty list)
 sum                         -- and take the sum thereof
      +                      -- and add
             #               -- a recursive call with
 [t|_:t<-a:r]                -- the tails of the current row and the rows before
              b              -- and the rows below
                             --
[]#_=0                       -- base case if there aren't any tails anymore, return 0
a#_=a#[[]]                   -- if there are tails, but no further rows below,
                             -- continue with tails

h x=[]#x+[]#(reverse x)      -- main function, call '#' with input matrix 'x'
                             -- and the reverse of it to get the number of diagonals
                             -- and anti-diagonals. Recursion starts with no
                             -- rows before the 1st row.

-- example trace of function '#'
-- input matrix:
--   [[1,2,3,4],
--    [5,6,7,8],
--    [9,9,9,9]]
--
--  | r         a          b              a:r          heads   tails (r of next call)
-- -+----------------------------------------------------------------------------------
-- 1| []        [1,2,3,4]  [[5,6,7,8],    [[1,2,3,4]]  [1]     [[2,3,4]]
--  |                       [9,9,9,9]]
--  | 
-- 2| [[2,3,4]]  [5,6,7,8]  [[9,9,9,9]]   [[5,6,7,8],  [5,2]   [[6,7,8],
--  |                                      [2,3,4  ]]           [3,4  ]]
--  |
-- 3| [[6,7,8],  [9,9,9,9]  []            [[9,9,9,9],  [9,6,3] [[9,9,9],
--  |  [3,4  ]]                            [6,7,8  ],           [7,8  ]
--  |                                      [3,4    ],           [4    ]
--  |
--  | ....
nimi
fonte
2

Carvão , 61 56 53 bytes

F²FLθFL§θ⁰F⟦⁻κ×⊖⊗ιλ⟧⊞υ⊞O⎇∧λ﹪⁺μιLθ⊟υ⟦⟧§§θμλILΦυ⊙ι‹⌕ιλμ

Experimente online! Link é a versão detalhada do código. Explicação:

F²

Loop sobre diagonais para frente e para trás; i=0representa diagonais avançadas enquanto i=1representa diagonais reversas.

FLθ

Loop sobre cada índice de linha. Isso representa o índice do início da diagonal.

FL§θ⁰«

Faça um loop sobre o índice de cada coluna.

F⟦⁻κ×⊖⊗ιλ⟧

Calcule o índice de linha da diagonal neste índice de coluna. Eu uso um forloop sobre uma matriz de elemento único em vez de uma atribuição, pois isso evita a quebra da atribuição em um bloco com a seguinte instrução, economizando assim um byte.

⎇∧λ﹪⁺μιLθ

Verifique se esta é a primeira coluna ou se a diagonal está prestes a envolver entre a parte inferior e a superior.

⊟υ

Caso contrário, apareça a última lista da lista de listas.

⟦⟧

se for, inicie uma nova lista vazia.

⊞O...§§θμλ

Adicione a entrada diagonal atual a essa lista.

⊞υ

E empurre essa lista (de volta) para a lista de listas.

ILΦυ⊙ι‹⌕ιλμ

Conte o número de listas que contêm duplicatas.

Vamos dar um exemplo quando i=0e k=1. Isso significa que já coletamos duas diagonais [[1,1,5,2],[9,4,3,5]]. Aqui está a nossa entrada:

 1 8 4 2 9 4 4 4
[5]1 2 7 7 4 2 3
 1 4 5 2 4 2 3 8
 8 5 4 2 3 4 1 5

Em seguida, passamos lde 0para 7. Isso avança a linha e a coluna em 1 a cada vez:

 1 8 4 2 9 4 4 4
[5]1 2 7 7 4 2 3
 1[4]5 2 4 2 3 8
 8 5[4]2 3 4 1 5

A lista é agora [[1,1,5,2],[9,4,3,5],[5,4,4]]. No entanto, quando lé 3que temos k+l=4um múltiplo da altura da matriz. Isto significa que precisamos começar uma nova lista: [[1,1,5,2],[9,4,3,5],[5,4,4],[]]. Em seguida, continuamos a coletar elementos diagonais:

 1 8 4[2]9 4 4 4
[5]1 2 7[7]4 2 3
 1[4]5 2 4[2]3 8
 8 5[4]2 3 4[1]5

A lista é agora [[1,1,5,2],[9,4,3,5],[5,4,4],[2,7,2,1]]. Agora, quando lé 7que temos k+l=8outro múltiplo da altura da matriz. Isto significa que precisamos começar uma nova lista, o que acaba com o último elemento dessa diagonal: [[1,1,5,2],[9,4,3,5],[5,4,4],[2,7,2,1],[4]].

 1 8 4[2]9 4 4[4]
[5]1 2 7[7]4 2 3
 1[4]5 2 4[2]3 8
 8 5[4]2 3 4[1]5

Ao coletar diagonais de quebra automática começando no primeiro elemento de cada linha, eventualmente acumulamos todas as diagonais da matriz.

Neil
fonte
2

Wolfram Language (Mathematica) , 99 98 96 94 83 bytes

Count[DuplicateFreeQ@Diagonal[#,i]~Table~{i,-t,t=#~Total~2}&/@{#,Reverse@#},1<0,2]&

Experimente online!

  • Function[a,a~Diagonal~#&/@Range[t=-#~Total~2,-t]]obtém todas as diagonais de a- o que funciona porque #~Total~2é maior que qualquer dimensão de a.
lirtosiast
fonte
1

APL + WIN, 69 bytes

Solicita uma matriz 2d do formulário 4 6⍴1 2 1 2 1 2 1 2 3 4 5 6 6 5 4 3 2 1 2 1 2 1 2 1

Isso produz:

1 2 1 2 1 2
1 2 3 4 5 6
6 5 4 3 2 1
2 1 2 1 2 1

+/~(v⍳¨v)≡¨⍳¨⍴¨v←(v←⊂[1](⌽0,⍳1↓n)⌽(n⍴0),m,((n←0 ¯1+↑⍴m)⍴0),⌽m←⎕)~¨0

Experimente online! Cortesia de Dyalog Classic

Explicação:

(⌽0,⍳1↓n)⌽(n⍴0),m pad m with zeros to isolate diagonals

((n←0 ¯1+↑⍴m)⍴0),⌽m pad rotated m with zeros to isolate anti-diagonals

Rendimentos:

1 2 1 2 1 2 0 0 0 2 1 2 1 2 1 0 0 0
0 1 2 3 4 5 6 0 0 0 6 5 4 3 2 1 0 0
0 0 6 5 4 3 2 1 0 0 0 1 2 3 4 5 6 0
0 0 0 2 1 2 1 2 1 0 0 0 1 2 1 2 1 2

v←(v←⊂[1](.....)~¨0 enclose the diagonals as a nested vector with padded zeros removed

+/~(v⍳¨v)≡¨⍳¨⍴¨v identify diagnols with duplicate entries and sum
Graham
fonte
1

Perl 5, 89 82 bytes

map{$i=0;map{$a[$x+$i].=$_;$b[@F-$x+$i++].=$_}/\d/g;$x++}@F;$_=grep/(.).*\1/,@a,@b

TIO

Nahuel Fouilleul
fonte
1

TSQL, 140 128 bytes

Encontrou uma maneira de jogar 12 caracteres no golfe. Essa não é mais a solução mais longa.

Golfe:

SELECT sum(iif(y+x=j+i,1,0)+iif(y-x=j-i,1,0))FROM
@,(SELECT x i,y j,max(y)over()m,v w
FROM @)d WHERE(x*y=0or m=y)and v=w and x<i

Ungolfed:

DECLARE @ table(v int,x int,y int)
-- v = value
-- x = row 
-- y = column
INSERT @ values
(1,0,0),(2,0,1),(1,0,2),(2,0,3),(1,0,4),(2,0,5),
(1,1,0),(2,1,1),(3,1,2),(4,1,3),(5,1,4),(6,1,5),
(6,2,0),(5,2,1),(4,2,2),(3,2,3),(2,2,4),(1,2,5),
(2,3,0),(1,3,1),(2,3,2),(1,3,3),(2,3,4),(1,3,5)


SELECT sum(iif(y+x=j+i,1,0)+iif(y-x=j-i,1,0))
FROM @,(SELECT x i,y j,max(y)over()m,v w FROM @)d
WHERE
  (x*y=0or m=y)
  and v=w
  and x<i

Experimente

t-clausen.dk
fonte