Trazado matricial generalizado


23

Inspiración.

Dado (por cualquier medio):

  • Una función de recuadro negro de dos argumentos (o argumento simple que consiste en una lista de dos elementos) , (entrada y salida son 1, 2, 3, ...)f: ℤ+ × ℤ+ → ℤ+
  • Una matriz entera estrictamente positiva con al menos dos filas y dos columnas.

devuelve el rastro de la función de la matriz .

¿Qué es un rastro de función ?

Un trazado de matriz normal es la suma de la diagonal principal (superior izquierda a inferior derecha) de una matriz:

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

Pero en lugar de sumar, queremos aplicar a lo flargo de la diagonal:

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

Indique si utiliza de izquierda a derecha o de derecha a izquierda.

La matriz dada y todos los valores intermedios serán enteros estrictamente positivos dentro del dominio de enteros de su idioma. La matriz puede ser no cuadrada.

Ejemplos

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]]5o7

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

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]]2o4

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

Implementación de referencia.


¿Cuál es la diagonal de [[2,2,2],[2,2,3],[2,3,3],[4,4,4]]?
Totalmente humano el

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

1
Maldita sea, leí el título como "trance de matriz generalizada" y me decepcionó mucho cuando se cargó la página
tar

Respuestas:


9

R , 40 30 bytes

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

Pruébalo en línea!

Verificar los casos de prueba.

Atraviesa la diagonal, de izquierda a derecha en este caso. Para operadores aritméticos, puede usar "+"o retroceder alrededor de los operadores ( +,*,-,%/%,^,%%)

Bastante sencillo: Reducees R del equivalente a una fold, y la diagonal de una matriz es aquellos elementos a_ijdonde i==j, es decir, donde el rowy colUMN índices son los mismos. diagtiene el comportamiento apropiado para matrices no cuadradas.


8

Haskell , 39 bytes

¡Gracias @Laikoni por ayudarme a solucionar la solución previamente inválida!

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

Asociados a la izquierda, ¡ pruébelo en línea! (reemplazar foldl1por foldr1derecho-asociativo)


¿qué tal foldl1 f$zipWith(!!)m[0..]?
orgulloso Haskeller

@proudhaskeller: Eso es lo que otros ya intentaron, pero eso falla en matrices no cuadradas ...
ბიმო

5

Mathematica , 16 bytes

-1 byte gracias a Martin Ender.

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

Pruébalo en línea!

Solución alternativa, 17 bytes.

Fold[g]@*Diagonal

Pruébalo en línea!


17 bytes (se pueden suponer funciones de recuadro negro con un nombre)
Sr. Xcoder

Esa @*{}sintaxis no tiene mucho sentido (probablemente quisiste decir@*List ), pero el hecho de que funcione de todos modos es bastante bueno. De hecho, significa que puede reemplazar el {}con 0ay guardar un byte.
Martin Ender

@MartinEnder En realidad sí tuve Listprimero, pero lo intenté {}por el gusto de hacerlo y me sorprendió mucho que funcionó. Tiene sentido, pero ¿cómo 0funciona? o0
totalmente humano

1
@totallyhuman De la misma manera que {}. Actualmente está utilizando {}como una función (o en realidad como una "cabeza" utilizando la terminología de Mathematica). Si utilizó un genérico fallí, obtendría f[1,2,3](si esa es la diagonal). Pero con lo {}que consigues {}[1,2,3]. Esa es una expresión completamente sin sentido, pero las cabezas pueden ser expresiones arbitrarias en sí mismas, y si Mathematica no sabe qué hacer con ellas, simplemente las deja como están. La mayoría de las funciones de manipulación de listas de Mathematica en realidad funcionan con expresiones con una cabeza arbitraria y, en el caso de Fold, la cabeza simplemente se ignora. [por confirmar]
Martin Ender

Entonces puedes usar 0 como cabeza, lo que da lo 0[1,2,3]que todavía no tiene sentido, pero funciona de todos modos.
Martin Ender

4

Octava , 61 57 53 bytes

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

Pruébalo en línea!

Define una función gque toma un controlador de función fy una matriz m. En la primera iteración, m(1)devuelve el elemento de matriz superior izquierdo; después de eso, simplemente regresa m.



@Giuseppe Eso es lo que hice con mi versión inicial de 61 bytes. Por supuesto, debería haber combinado los puntos fuertes de mi versión de 57 y 61 bytes, lo que da una respuesta de 53 bytes. ¡Gracias por hacerme ver eso otra vez!
Sanchises

3

Limpio , 56 bytes

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

Pruébalo en línea!Se pliega de derecha a izquierda.

[t\\[_:t]<-r]es lo mismo que map tl r, pero no necesita import StdEnv.


Evitación muy eleganteStdEnv
Οurous

3

Haskell , 47 45 42 bytes

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

Pruébalo en línea!Define una función (%)que toma una función y una matriz como una lista de listas como entrada.

La función se pliega de derecha a izquierda:

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

Editar: -2 bytes gracias a BMO y -3 bytes gracias a Zgarb !


1
43 bytes usando $y simplificando el condicional con *>.
Zgarb

@Zgarb ¡Buena idea para usar *>!
Laikoni

3

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

⎕/1 1⍉⎕

Pruébalo en línea!

-3 gracias a una sugerencia para convertir esto en un programa completo por Adám .

De derecha a izquierda.


No es necesario usar el SBCS de Adám aquí: puedes usar el Dyalog Classic.
Zacharý,

@ Zacharý La cosa es que estoy respondiendo en Dyalog Unicode, Classic se está quedando obsoleto con el tiempo.
Erik the Outgolfer

No es la página de códigos aunque la página de códigos seguirá viva
Zacharý

@ Zacharý Bueno, seamos más 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])

Pruébalo en línea!

Esto funciona de izquierda a derecha.


@AsoneTuhid puede ser de cualquier manera, consulte los ejemplos (x+y)⁄2yx+2y
Rod

Correcto, lo
leí

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

Se pliega de izquierda a derecha. Editar: se guardaron 2 bytes utilizando el hecho de que la matriz es estrictamente positiva. Solución alternativa, también 56 bytes:

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

No se ve como que necesita el 1/y usted puede ahorrar otros 2 bytes moviendo algunas cosas en torno a: f=>a=>(h=r=>(e=a[++i]&&a[i][i])?h(f(r,e)):r)(a[i=0][0]). TIO
Shaggy

@ Shaggy Oh, es estrictamente positivo, no había visto eso.
Neil

Aparentemente, podemos suponer que las funciones de recuadro negro se asignan a una variable predefinida, por lo que podría ahorrar 2 bytes si desea aprovechar eso.
Shaggy

@ Shaggy ¿De verdad creo que ahorraría 4 bytes (2x f,) de la primera versión?
Neil

Tienes razón; lo siento, olvidé contar f,cuando llamé de gnuevo.
Shaggy

2

JavaScript, 46 bytes

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

Gracias a @Shaggy, use bitwise o guarde un byte. Eso es magia


Esto no parece funcionar si la matriz tiene más filas que columnas.
Shaggy

@Shaggy tan triste, 47 bytes ahora ...
tsh

Sí, eso es lo que tenía originalmente, también. Estaba a punto de editar la solución en mi solución, pero también me superaste :( Creo que puedes recuperar un byte, sin embargo, usando OR bit a bit, sin embargo.
Shaggy

@Shaggy so magic
tsh

Olvidé mencionar: Al parecer, podemos suponer que las funciones de recuadro negro están asignadas a una variable predefinida para que pueda guardar 3 bytes si desea aprovechar eso.
Shaggy

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

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

-7 bytes indirectamente gracias a @KamilDrakari al usar un truco similar al que hizo en su respuesta de C # : en lugar de tener un límite máximo para el bucle basado en las filas / columnas, simplemente intente atrapar el ArrayIndexOutOfBoundsException.
-11 bytes reemplazando catch(Exception e)con finally.

Pruébalo en línea.

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

Pruébalo en línea.

Explicación:

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 de caja negra:

Asume que una función con nombre int f(int x,int y)está presente, lo cual está permitido de acuerdo con esta meta respuesta .

Tengo una clase abstracta que Testcontiene la función predeterminada f(x,y), así como la lambda anterior:

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 los casos de prueba, sobrescribo esta función f. Por ejemplo, el primer caso de prueba se llama así:

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

Adjunto , 14 bytes

Fold#/Diagonal

Pruébalo en línea! Establecer fy llamar como f[function, array].

Explicación

Esta es una bifurcación de dos funciones: Foldy /Diagonal. Esto, para argumentos fy a, es equivalente a:

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

/, cuando se aplica monádicamente a una función, devuelve una función que se aplica a su último argumento. Entonces, esto es equivalente a:

Fold[f, Diagonal[a]]

Esto pliega la función fsobre la diagonal principal de a.


Un idioma casero que es legible‽
Adám

@ Adám; D sí, de hecho!
Conor O'Brien el

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}

Pruébalo en línea!

Tenía curiosidad si AWK podría hacer programación funcional en absoluto. Creo que esto cuenta.

La "matriz" se define como una matriz asociativa estándar, con campos adicionales M[1]=#rowsy M[2]=#columns. El nombre de la función se pasa como una cadena que se evalúa mediante la @F(...)sintaxis. La evaluación se realiza de izquierda a derecha. El rparámetro es un marcador de posición para evitar sobrescribir una rvariable existente y evitar la necesidad de reinicializar cada llamada. Normalmente, se agrega espacio adicional para designar dichos marcadores de posición enAWK , pero este es el código de golf, por lo que cada byte cuenta. :)

El enlace TIO implementa todos los casos de prueba.


2

05AB1E , 15 10 bytes

Se pliega de derecha a izquierda
Guardado 5 bytes usando un nuevo incorporado como lo sugiere Kevin Cruijssen

Å\`[.g#I.V

Explicación

Funciona igual que la versión anterior, excepto que Å\es un nuevo incorporado para empujar la diagonal principal.

Pruébalo en línea! o como un conjunto de pruebas

Versión antigua

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

Pruébalo en línea! o como un conjunto de pruebas

Explicación

¬                 # 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è}[puede ser Å\`[ahora, ahorrando 5 bytes.
Kevin Cruijssen

1

Cáscara , 7 bytes

¡Gracias @Zgarb por arreglar mi presentación!

Ḟ₁§z!Tŀ

Asociados a la izquierda, ¡ Pruébelo en línea! (para una versión asociativa correcta simplemente reemplace porF )

Explicación

Desafortunadamente, no hay una manera fácil de obtener la diagonal de una matriz, por lo que la mayoría de los bytes son para eso:

Ḟ₁§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, incorporado para antiagoniales, pero no para diagonales‽
Adám

2
@ Adám Supongo que es porque puedes calcular antidiagonales de matrices infinitas pero no diagonales.
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)')

Pruébalo en línea!

Define una función T(para TRACE) que toma unARRAY y una cadenaF que es el nombre de una función. Se pliega de izquierda a derecha.

Usar la referencia indirecta ( $) no funciona con funciones. Entonces, usar EVALy pasar una cadena al nombre parece ser la única forma de obtener una función de recuadro negro en SNOBOL.

Además, es bastante doloroso definir matrices; sin embargo, debido a que las referencias de matriz inválidas causan FAILURE, esto funciona para matrices no cuadradas; si Iestá fuera de los límites en cualquier dimensión, F(RETURN)obliga a la función a regresar.

Editar:

Posiblemente, en base a esta meta publicación , puedo suponer que la función de recuadro negro Fse define bajo el nombre F, lo que lo reduciría a 75 bytes (eliminar el uso de EVALy ,Fen la definición de la función). Sin embargo, prefiero esta versión ya que está más cerca de pasar una referencia a una función.



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

La última línea es una función lambda sin nombre que toma una función y una matriz y devuelve la traza de la matriz. La traza es asociativa a la izquierda (es decir f(f(1,5),9)). Pruébalo en línea!

Sin golf

Definimos una función auxiliar para calcular la diagonal; entonces generalized-tracees simplemente un pequeño contenedor alrededor de la función de 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))))

Al calcular la diagonal de forma recursiva, verificamos si (head matrix)es verdad. Si la matriz está fuera de filas, será la lista vacía (nil), y headde nil es nil - falsey. O, si la matriz está fuera de las columnas, su primera fila (encabezado) será la lista vacía (nula) - falsey. De lo contrario, habrá una primera fila no vacía, lo cual es cierto.

Entonces, si la primera fila no existe o está vacía, devolvemos nil. De lo contrario, si hay una primera fila no vacía, tomamos el (head (head matrix))primer elemento de la primera fila y cons(lo anteponemos) al resultado de la llamada recursiva. El argumento para la llamada recursiva es: (map tail (tail matrix))es decir, tomar todas las filas menos la primera, y tomar todas menos el primer elemento de cada fila.



1

C # (compilador de Visual C #) , 72 69 60 bytes

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

Pruébalo en línea!

try/catch permite alcanzar correctamente la diagonal simplemente yendo a lo largo y terminando cuando está fuera de los límites.

3 bytes guardados porque, como lo señaló Kevin Cruijssen, se puede suponer que las funciones de recuadro negro existen bajo un nombre específico .

9 bytes guardados al regresar mediante la modificación de un argumento .

Por lo tanto, la función se llama almacenando la función deseada bajo el nombre f, llamando trace(matrix), y el resultado se almacena en matrix[0][0].

Alternativamente, si realmente te gusta la verbosidad,

C # (compilador de 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{}}

Pruébalo en línea!

32 bytes guardados mediante el uso de una función predefinida, ya que no tomar la función como parámetro permitió eliminar la Systemimportación y el Functipo genérico largo .


Buen truco con el try-catch. He podido jugar golf 7 bytes en mi respuesta Java 8 (aunque tengo que usar en catch(Exception e)lugar de catch. :) EDITAR: Oh, he podido reemplazarlo catch(Exception e)con finallypara guardar más bytes. Gracias de nuevo. +1 de mi parte
Kevin Cruijssen

@KevinCruijssen también puede beneficiarse de mi nueva mejora (aunque no recuerdo con certeza si Java es capaz de modificar argumentos)
Kamil Drakari

Gracias por hacérmelo saber. Aunque es posible en Java, significa que tendré que cambiarlo finallya catch(Exception e), porque finalmente ya no volveré al interior. Entonces m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}(73 bytes) es, lamentablemente, más largo para mí en comparación con mi respuesta actual m->{int r=m[0][0],i=1;try{for(;;)r=f(r,m[i][i++]);}finally{return r;}}(70 bytes) ¡Pero, de hecho, es una buena manera de guardar bytes en su respuesta! :) Lástima que solo pueda hacer +1 en tu respuesta una vez.
Kevin Cruijssen

1

JavaScript, 61 57 56 52 50 44 42 bytes

Reduce de izquierda a derecha. Asume que la función está asignada a la variable f, según esta meta publicación que me llamó la atención el Sr. Xcoder y totalmente humano. No puedo decir que estoy de acuerdo, ya que contradice directamente nuestro consenso existente de que no podemos asumir que la entrada se asigna a una variable predefinida, pero tomaré los pocos bytes que ahorramos por ahora.

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

Casos de prueba

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⍉⍵}

prueba:

  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

Buen trabajo. Si bien creo que llegas a esto por tu cuenta, resulta ser idéntico a la solución original de Erik the Outgolfer .
Adám

0

Jalea , 5 bytes

De izquierda a derecha.

ŒDḢç/

Pruébalo en línea!

Descargo de responsabilidad: no sé si este es un método de entrada aceptable para las funciones de recuadro negro. Esto supone que la función se implementa en el enlace anterior y, por lo tanto, se "nombra" (es decir, se puede llamar con) ç, pero de lo contrario no tengo forma de asignarla ç. Si alguien tiene más experiencia con las funciones de caja negra de Jelly +, agradecería tener pensamientos. Después de pasar un tiempo en el chat, supusimos que el uso çpodría ser válido.


0

Clojure, 30 bytes

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

Reduce "desde la izquierda".


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.