Rastreio de matriz generalizada


23

Inspiração.

Dado (por qualquer meio):

  • Um dois-argumento (ou argumento único constituído por uma lista de dois elementos) função caixa preta , (entrada e saída são 1, 2, 3, ...)f: ℤ+ × ℤ+ → ℤ+
  • Uma matriz inteira estritamente positiva com pelo menos duas linhas e duas colunas

retornar o rastreio de função da matriz .

O que é um rastreamento de função ?

Um rastreio de matriz normal é a soma da diagonal principal (canto superior esquerdo para canto inferior direito) de uma matriz:

[[1,2,3],[4,5,6],[7,8,9]][1,5,9]1+5+915

Mas, em vez de somar, queremos aplicar fao longo da diagonal:

[[1,2,3],[4,5,6],[7,8,9]][1,5,9]f(f(1,5),9)ouf(1,f(5,9))

Indique se você usa da esquerda para a direita ou da direita para a esquerda.

A matriz fornecida e todos os valores intermediários serão números inteiros estritamente positivos no domínio inteiro do seu idioma. A matriz pode ser não quadrada.

Exemplos

f(x,y) = xy, [[1,2,3],[4,5,6],[7,8,9]]1×5×945

f(x,y) = xy, [[1,2,3],[4,5,6],[7,8,9]]→ →1591

f(x,y) = x-y, [[4,5,6],[1,2,3]]4-22

f(x,y) = (x+y)⁄2, [[2,3,4],[5,6,7],[8,9,10]]5ou7

f(x,y) = x+2y, [[1,2,3],[4,5,6],[7,8,9]]47ou29

f(x,y) = max(x,y), [[1,2,3],[4,5,6],[7,8,9]]max(1,5,9)9

f(x,y) = 2x, [[1,2,3],[4,5,6],[7,8,9]]2ou4

f(x,y) = lcm(x,y), [[2,2,2],[2,2,3],[2,3,3],[4,4,4]]lcm(2,2,3)6

Implementação de referência.


Qual é a diagonal de [[2,2,2],[2,2,3],[2,3,3],[4,4,4]]?
totallyhuman

3
@totallyhuman:[2,2,3]
Emigna

1
Droga, eu li o título como "transe da Matriz Generalizada" e fiquei muito decepcionado quando a página foi carregada
tar

Respostas:


9

R , 40 30 bytes

function(m,F)Reduce(F,diag(m))

Experimente online!

Verifique os casos de teste.

Percorre a diagonal, portanto, da esquerda para a direita. Para operadores aritméticos, você pode usar "+"ou dar backticks aos operadores ( +,*,-,%/%,^,%%)

Bem direto: ReduceR é equivalente a a fold, e a diagonal de uma matriz são aqueles elementos a_ijonde i==j, ie, onde os índices rowe column são os mesmos. diagtem o comportamento apropriado para matrizes não quadradas.


8

Haskell , 39 bytes

Obrigado @Laikoni por me ajudar a corrigir a solução anteriormente inválida!

f!m=foldl1 f[h|h:_<-zipWith drop[0..]m]

Associados à esquerda, experimente online! (substitua foldl1por foldr1por associativo à direita)


que tal foldl1 f$zipWith(!!)m[0..]?
#

@proudhaskeller: Isso é o que outros já tentaram, mas que falha em matrizes não-quadrados ..
ბიმო

5

Mathematica , 16 bytes

-1 byte graças a Martin Ender.

#~Tr~Fold[g]@*0&

Experimente online!

Solução alternativa, 17 bytes

Fold[g]@*Diagonal

Experimente online!


17 bytes (funções de caixa preta pode ser assumido sob um dado nome)
Sr. Xcoder

Essa @*{}sintaxe não faz muito sentido (você provavelmente quis dizer @*List), mas o fato de funcionar de qualquer maneira é bem legal. De fato, isso significa que você pode substituir o {}por a 0e salvar um byte.
Martin Ender

@MartinEnder Na verdade, eu tive Listprimeiro, mas tentei {}apenas por isso e fiquei extremamente surpreso que funcionou. Faz sentido, mas como 0funciona? o0
totallyhuman

1
@totallyhuman Da mesma maneira que {}. Você está usando atualmente {}como uma função (ou na verdade como uma "cabeça" usando a terminologia do Mathematica). Se você usasse um genérico flá, obteria f[1,2,3](se essa for a diagonal). Mas com {}você {}[1,2,3]. Essa é uma expressão completamente sem sentido, mas as cabeças podem ser expressões arbitrárias e, se o Mathematica não sabe o que fazer com elas, apenas as deixa como estão. A maioria das funções de manipulação de lista do Mathematica realmente funciona com expressões com uma cabeça arbitrária e, no caso de Fold, a cabeça é apenas ignorada. [a confirmar]
Martin Ender

Então você pode usar 0como cabeça, o que dá o 0[1,2,3]que ainda não tem sentido, mas funciona da mesma forma.
Martin Ender

4

Oitava , 61 57 53 bytes

function m=g(f,m)for i=diag(m)'(2:end)m=f(m(1),i);end

Experimente online!

Define uma função gque recebe um identificador de função fe matriz m. Na primeira iteração, m(1)retorna o elemento da matriz superior esquerdo; depois disso, apenas retorna m.



@ Giuseppe Foi o que fiz na minha versão inicial de 61 bytes. Obviamente, eu deveria ter combinado os pontos fortes da minha versão de 57 e 61 bytes, que indeeds fornece uma resposta de 53 bytes. Obrigado por me fazer olhar para isso de novo!
Sanchises

3

Limpo , 56 bytes

t[[h:_]]f=h
t[[h]:_]f=h
t[[h:_]:r]f=f h(t[t\\[_:t]<-r]f)

Experimente online! Dobras da direita para a esquerda.

[t\\[_:t]<-r]é o mesmo que map tl r, mas não precisa import StdEnv.


Evitar muito elegante deStdEnv
Οurous

3

Haskell , 47 45 42 bytes

f%((h:t):r)|[]<-t*>r=h|x<-tail<$>r=f h$f%x

Experimente online! Define uma função (%)que assume uma função e uma matriz como uma lista de listas como entrada.

A função é dobras da direita para a esquerda:

f % [[1,2,3], -> f 1 ( f % [[5,6],   -> f 1 ( f 5 ( f % [[9]] ) ) -> f 1 ( f 5 ( f 9 ) ) )
     [4,5,6],               [8,9]] )
     [7,8,9]]

f % ((h:t):r)              -- (h:t) is the first row and r the remaining rows
 | [] <- t *> r = h         -- a shorter way of checking wether t==[] or r==[]
 | x<-tail<$>r = f h $ f%x -- apply f to h and the result of recursively calling (%) on
                           -- the remaining matrix with the first column removed

Edit: -2 bytes graças ao BMO e -3 bytes graças ao Zgarb !


1
43 bytes usando $e simplificando o condicional com *>.
Zgarb

@ Zgarb Boa idéia para usar *>!
Laikoni

3

APL (Dyalog Unicode) , 7 bytes ( SBCS de Adám )

⎕/1 1⍉⎕

Experimente online!

-3 graças a uma sugestão de converter isso em um programa completo da Adám .

Direita para esquerda.


Não é necessário usar o SBCS de Adám aqui: você pode apenas usar o Dyalog Classic.
Zacharý

@ Zacharý O problema é que eu estou respondendo no Dyalog Unicode, o Classic está ficando obsoleto ao longo do tempo.
Erik the Outgolfer

Não a página de códigos thoughm a página de códigos vai viver
Zachary

@ Zacharý Bem, vamos preferir ser consistentes. : P
Erik the Outgolfer



2

Python 2 , 61 bytes

lambda f,m:reduce(f,[l[i]for i,l in enumerate(m)if len(l)>i])

Experimente online!

Isso funciona da esquerda para a direita.


@AsoneTuhid pode ser de qualquer maneira, verifique os exemplos (x+y)⁄2ex+2y
Rod Rod

Certo, eu interpretei mal, desculpe
Asone Tuhid

2

JavaScript (ES6), 58 56 bytes

g=(f,a,r=a[i=0][0],e=a[++i]&&a[i][i])=>e?g(f,a,f(r,e)):r

Dobras da esquerda para a direita. Editar: salvou 2 bytes usando o fato de que a matriz é estritamente positiva. Solução alternativa, também 56 bytes:

(f,a,g=r=>(e=a[++i]&&a[i][i])?g(f(r,e)):r)=>g(a[i=0][0])

Ele não se parece com você precisa do 1/e você pode economizar mais 2 bytes movendo algumas coisas em torno de: f=>a=>(h=r=>(e=a[++i]&&a[i][i])?h(f(r,e)):r)(a[i=0][0]). TIO
Shaggy

@ Shaggy Oh, é estritamente positivo, eu não tinha visto isso.
Neil

Aparentemente, podemos assumir que as funções da caixa preta são atribuídas a uma variável predefinida, para que você possa salvar 2 bytes se quiser tirar vantagem disso.
Salsicha

@ Shaggy Na verdade, acho que economizaria 4 bytes (2x f,) da primeira versão?
Neil

Você está certo; desculpe, esqueci de contar f,quando ligar gnovamente.
Salsicha

2

JavaScript, 46 bytes

f=>a=>a.reduce((p,l,i)=>l[i]?f(p[0]|p,l[i]):p)

Graças a @Shaggy, use bit a bit ou salve um byte. Isso é mágico.


Isso não parece funcionar se a matriz tiver mais linhas do que colunas.
Salsicha

@Shaggy so sad, 47 bytes now ...
tsh

Sim, é o que eu tinha originalmente também. Estava prestes a editar a correção na minha solução, mas você também me derrotou :( Porém, acho que você pode obter um byte de volta, usando OR bit a bit.
Shaggy

@Shaggy so magic
tsh

Esqueci de mencionar: aparentemente, podemos assumir que as funções da caixa preta estão atribuídas a uma variável predefinida, para que você possa salvar 3 bytes se quiser tirar vantagem disso.
Salsicha

2

Java 8, 88 81 70 bytes

m->{int r=m[0][0],i=1;try{for(;;)r=f(r,m[i][i++]);}finally{return r;}}

Dobras [[1,2,3],[4,5,6],[7,8,9]]para f(f(1,5),9).

-7 bytes indiretamente, graças a @KamilDrakari , usando um truque semelhante ao usado em sua resposta C # : em vez de ter um limite máximo para o loop com base nas linhas / colunas, simplesmente tente pegar o ArrayIndexOutOfBoundsException.
-11 bytes substituindo catch(Exception e)por finally.

Experimente online.

Resposta antiga de 88 bytes:

m->{int r=m[0][0],i=1;for(;i<Math.min(m.length,m[0].length);)r=f(r,m[i][i++]);return r;}

Experimente online.

Explicação:

m->{                   // Method with integer-matrix parameter and integer return-type
  int r=m[0][0],       //  Start the result at the integer of position 0,0 (0-indexed)
      i=1;             //  Start the index at 1 (0-indexed)
  try{for(;;)          //  Loop indefinitely
    r=f(r,m[i][i++]);} //   Call f with the result + next diagonal cell as arguments
                       //   (and increase `i` by 1 with `i++` afterwards)
  finally{             //  If an ArrayIndexOutOfBoundsException occurred we're done,
   return r;}}         //   in which case we return the result-integer

Formato de entrada da caixa preta:

Supõe que uma função nomeada int f(int x,int y)esteja presente, o que é permitido de acordo com esta meta resposta .

Eu tenho uma classe abstrata Testcontendo a função padrão f(x,y), bem como a lambda acima:

abstract class Test{
  int f(int x,int y){
    return x+y;
  }

  public java.util.function.Function<int[][],Integer>c=
    m->{int r=m[0][0],i=1;for(;i<Math.min(m.length,m[0].length);)r=f(r,m[i][i++]);return r;}
  ;
}

Para os casos de teste, substituo essa função f. Por exemplo, o primeiro caso de teste é chamado assim:

System.out.println(new Test(){
  @Override
  int f(int x,int y){
    return x*y;
  }
}.c.apply(new int[][]{
  new int[]{1,2,3},
  new int[]{4,5,6},
  new int[]{7,8,9}
}));

2

Anexo , 14 bytes

Fold#/Diagonal

Experimente online! Defina como fe chame como f[function, array].

Explicação

Este é um garfo de duas funções: Folde /Diagonal. Isso, para argumentos fe a, é equivalente a:

Fold[f, (/Diagonal)[f, a]]

/, quando aplicado monadicamente a uma função, retorna uma função aplicada ao seu último argumento. Portanto, isso é equivalente a:

Fold[f, Diagonal[a]]

Isso dobra a função fsobre a diagonal principal de a.


Uma linguagem fabricada em casa que é
legível‽

@ Adám; D sim mesmo!
Conor O'Brien

2

AWK , 77 bytes

func z(F,M,r){for(e=1;e<M[1]&&e<M[2];)r=@F(r==""?M[1,1]:r,M[++e,e])
return r}

Experimente online!

Fiquei curioso para saber se AWKpoderia fazer programação funcional. Eu acho que isso conta.

A "Matriz" é definida como uma matriz associativa padrão, com campos extras M[1]=#rowse M[2]=#columns. O nome da função é passado como uma sequência que é avaliada através da @F(...)sintaxe. A avaliação é realizada da esquerda para a direita. O rparâmetro é um espaço reservado para evitar a substituição de uma rvariável existente e para evitar a necessidade de reinicializar para cada chamada. Geralmente, é adicionado espaço extra para designar esses espaços reservados AWK, mas esse é um código de golfe, portanto, cada byte conta. :)

O link TIO implementa todos os casos de teste.


2

05AB1E , 15 10 bytes

Dobras da direita para a esquerda
Salva 5 bytes usando um novo built-in, como sugerido por Kevin Cruijssen

Å\`[.g#I.V

Explicação

Funciona da mesma forma que a versão antiga, exceto que Å\é um novo built-in para empurrar a diagonal principal.

Experimente online! ou como um conjunto de testes

Versão antiga

¬g£vyNè}[.g#I.V

Experimente online! ou como um conjunto de testes

Explicação

¬                 # get the head of the input (first row)
 g                # get its length (number of columns)
  £               # take that many rows from input
   v              # for each row_index, row (N,y) do:
    y             # push the row
     Nè           # get the nth element of the row
       }          # end loop
        [.g#      # loop until one value remain on the stack
            I.V   # run the input function

1
¬g£vyNè}[pode ser Å\`[agora, economizando 5 bytes.
Kevin Cruijssen 18/02

1

Casca , 7 bytes

Obrigado @Zgarb por corrigir meu envio!

Ḟ₁§z!Tŀ

Associados à esquerda, Experimente online! (para uma versão associativa correta, basta substituir por F)

Explicação

Infelizmente, não há uma maneira fácil de obter a diagonal de uma matriz; portanto, a maioria dos bytes é para isso:

Ḟ₁§z!Tŀ  -- function ₁ is the function and matrix A implicit, example: 
  §      -- fork A
     T   -- | transpose A: [[1,4,7],[2,5,8],[3,6,9]]
      ŀ  -- | enumerate A: [1,2,3]
   z!    -- and zipWith index: [1,5,9]
Ḟ₁       -- right fold function

Huh, built-in para os anti-diagonais, mas não para diagonals‽
Adám

2
@ Adám Presumo que é porque você pode calcular antidiagonais de matrizes infinitas, mas não diagonais.
Martin Ender

1

SNOBOL4 (CSNOBOL4) , 86 bytes

T	I =1
	T =M<1,1>
I	I =I + 1
	T =EVAL(F '(T,M<I,I>)')	:S(I)F(RETURN)
	DEFINE('T(M,F)')

Experimente online!

Define uma função T(para TRACE) que recebe uma ARRAYe uma sequência Fque é o nome de uma função. Dobras da esquerda para a direita.

Usar referência indireta ( $) não funciona com funções. Portanto, usar EVALe passar uma string para o nome parece ser a única maneira de obter uma função de caixa preta no SNOBOL.

Além disso, é bastante doloroso definir matrizes; no entanto, como as referências de matriz inválidas causam FAILURE, isso funciona para matrizes não quadradas - se Iestiver fora dos limites em qualquer dimensão, isso F(RETURN)força a função a retornar.

Editar:

Possivelmente, com base neste meta post , posso assumir que a função de caixa preta Festá definida sob o nome F, o que diminuiria para 75 bytes (remova o uso de EVALe ,Fna definição de função). No entanto, prefiro esta versão, pois está mais próxima de passar uma referência a uma função.



1

tinylisp , 79 bytes

(load library
(d D(q((M)(i(h M)(c(h(h M))(D(map t(t M))))(
(q((F M)(foldl F(D M

A última linha é uma função lambda sem nome que pega uma função e uma matriz e retorna o rastreamento da matriz. O traço é associativo à esquerda (ie f(f(1,5),9)). Experimente online!

Ungolfed

Definimos uma função auxiliar para calcular a diagonal; então generalized-traceé apenas um pequeno invólucro em torno da função da biblioteca foldl.

(load library)

(def diagonal
 (lambda (matrix)
  (if (head matrix)
   (cons
    (head (head matrix))
    (diagonal (map tail (tail matrix))))
   nil)))

(def generalized-trace
 (lambda (func matrix)
  (foldl func (diagonal matrix))))

Ao calcular a diagonal recursivamente, verificamos se (head matrix)é verdade. Se a matriz estiver fora de linhas, será a lista vazia (nil) e headnil é nil - falsey. Ou, se a matriz estiver sem colunas, sua primeira linha (cabeçalho) será a lista vazia (zero) - falsey. Caso contrário, haverá uma primeira linha não vazia, que é verdadeira.

Portanto, se a primeira linha não existir ou estiver vazia, retornaremos nulo. Caso contrário, se houver uma primeira linha não vazia, pegamos (head (head matrix))- o primeiro elemento da primeira linha - e conso adicionamos ao resultado da chamada recursiva. O argumento para a chamada recursiva é (map tail (tail matrix))- ou seja, pega todas as linhas, exceto a primeira, e pega todos, exceto o primeiro elemento de cada linha.



1

C # (Compilador Visual C #) , 72 69 60 bytes

m=>{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch{}}

Experimente online!

try/catch permite que a diagonal seja alcançada corretamente, basta avançar e terminar quando estiver fora dos limites.

3 bytes salvos porque, como apontado por Kevin Cruijssen, pode-se supor que as funções de caixa preta existam sob um nome específico .

9 bytes salvos retornando através da modificação de um argumento .

Assim, a função é chamada armazenando a função desejada sob o nome f, chamando trace(matrix), e o resultado é armazenado em matrix[0][0].

Como alternativa, se você realmente gosta de verbosidade,

C # (Compilador Visual C #) , 97 + 13 = 110 78 69 bytes

(int[][]m)=>{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch{}}

Experimente online!

32 bytes salvos usando uma função predefinida, porque não tomar a função como parâmetro permitiu remover a Systemimportação e o Functipo genérico longo .


Bom truque com o try-catch. Consegui obter 7 bytes de golfe na minha resposta do Java 8 (mesmo que eu tenha que usar em catch(Exception e)vez de catch. :) EDIT: Ah, consegui substituir o catch(Exception e)por finallypara economizar mais bytes. Obrigado novamente. +1 de mim.
Kevin Cruijssen

@KevinCruijssen você também pode ser capaz de beneficiar de minha mais nova melhoria (embora eu não me lembro ao certo se o Java é passível de modificar os argumentos)
Kamil Drakari

Obrigado por me avisar. Embora seja possível em Java, isso significa que terei que mudar finallypara catch(Exception e), porque não vou mais voltar para dentro do finalmente. Então m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}(73 bytes) é, infelizmente, mais para mim em comparação com a minha resposta atual m->{int r=m[0][0],i=1;try{for(;;)r=f(r,m[i][i++]);}finally{return r;}}(70 bytes) Mas na verdade, uma boa maneira de economizar bytes na sua resposta! :) Pena que só posso marcar sua resposta com +1 uma vez.
Kevin Cruijssen

1

JavaScript, 61 57 56 52 50 44 42 bytes

Reduz da esquerda para a direita. Assume que a função está atribuída à variável f, conforme esta meta post que me foi trazida à atenção pelo Sr. Xcoder e totalmente humano. Não posso dizer que concordo com ele, pois contradiz diretamente o nosso consenso existente de que não podemos assumir que a entrada seja atribuída a uma variável predefinida, mas utilizarei os poucos bytes salvos por enquanto.

a=>a.map((y,z)=>x=(n=y[z])?z?f(x,n):n:x)|x

Casos de teste

g=
a=>a.map((y,z)=>x=(n=y[z])?z?f(x,n):n:x)|x
o.innerHTML=[[`f(x,y) = xy`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x*y,45],[`f(x,y) = x<sup>y</sup>`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x**y,1],[`f(x,y) = x-y`,[[4,5,6],[1,2,3]],(x,y)=>x-y,2],[`f(x,y) = <sup>(x+y)</sup>⁄<sub>2</sub>`,[[2,3,4],[5,6,7],[8,9,10]],(x,y)=>(x+y)/2,7],[`f(x,y) = x+2y`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x+2*y,29],[`f(x,y) = max(x,y)`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>Math.max(x,y),9],[`f(x,y) = 2x`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>2*x,4],[`f(x,y) = lcm(x,y)`,[[2,2,2],[2,2,3],[2,3,3],[4,4,4]],(x,y)=>-~[...Array(x*y).keys()].find(z=>!(++z%x|z%y)),6]].map(([a,b,c,d],e)=>`Test #${++e}:  ${a}\nMatrix:   ${JSON.stringify(b)}\nFunction: ${f=c}\nResult:   ${g(b)}\nExpected: ${d}`).join`\n\n`
<pre id=o></pre>


1

NARS APL, 20 bytes, 10 caracteres

{⍺⍺/1 1⍉⍵}

teste:

  f←{⍺⍺/1 1⍉⍵}
  ⎕←q←3 3⍴⍳10    
1 2 3
4 5 6
7 8 9
  ×f q
45
  *f q
1
  {⍺+2×⍵}f q
47
  ⌈f q
9
  {2×⍺+0×⍵}f q
2
  -f ⊃(4 5 6)(1 2 3)
2
  {(⍺+⍵)÷2}f ⊃(2 3 4)(5 6 7)(8 9 10)
5
  ∧f ⊃(2 2 2)(2 2 3)(2 3 3)(4 4 4)
6

Bom trabalho. Embora eu ache que você chega por conta própria, isso é idêntico à solução original de Erik the Outgolfer .
Adám 31/01

0

Geléia , 5 bytes

Esquerda para a direita.

ŒDḢç/

Experimente online!

Isenção de responsabilidade: não sei se esse é um método de entrada aceitável para funções de caixa preta. Isso pressupõe que a função é implementada no link acima e, portanto, é "nomeada" (ou seja, é possível chamar) ç, mas, caso contrário, não tenho como atribuí-la ç. Se alguém tiver mais experiência com as funções da caixa preta do Jelly +, agradeceria a opinião. Depois de passar algum tempo no bate-papo, descobrimos que o uso çpoderia ser realmente válido.


0

Clojure, 30 bytes

#(reduce %2(map nth %(range)))

Reduz "da esquerda".


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.