广义矩阵迹


23

灵感。

给出(通过任何方式):

  • 两个参数(或包含两个元素的列表的单个参数)黑盒函数,(输入和输出为1、2、3,…)f: ℤ+ × ℤ+ → ℤ+
  • 具有至少两行两列的严格正整数矩阵

返回矩阵的函数trace

什么是功能跟踪

法线矩阵轨迹是矩阵的主要对角线(左上至右下)的总和:

[[1,2,3],[4,5,6],[7,8,9]]→交通[1,5,9]→交通1+5+9→交通15

但是我们不求总和,而是f沿对角线应用:

[[1,2,3],[4,5,6],[7,8,9]]→交通[1,5,9]→交通f(f(1,5),9)f(1,f(5,9))

请说明您使用的是从左到右还是从右到左。

给定的矩阵和所有中间值将严格为您语言的整数域内的正整数。矩阵可以是非正方形的。

例子

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

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-2→交通2

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

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

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

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

参考实施。


对角线是[[2,2,2],[2,2,3],[2,3,3],[4,4,4]]多少?
–totalhuman

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

1
该死,我把标题读为“ Generalized Matrix trance”,页面加载时感到非常失望
tar

Answers:


9

R40 30字节

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

在线尝试!

验证测试用例。

沿对角线向下移动,因此在这种情况下从左到右。对于算术运算符,您可以"+"在运算符(+,*,-,%/%,^,%%)周围使用或反引号

相当简单:Reduce为R的相当于一个fold,和一个矩阵的对角是那些元素a_ij,其中i==j,即,其中rowcolUMN指数是相同的。 diag对非平方矩阵具有适当的行为。


8

Haskell,39个字节

感谢@Laikoni帮助我修复了以前无效的解决方案!

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

左侧的助理,可以在线尝试!foldl1foldr1右关联替换为)


怎么样foldl1 f$zipWith(!!)m[0..]
自豪的haskeller

@proudhaskeller:那是其他人已经尝试过的方法,但是在非平方矩阵上失败了
。–

5

Mathematica,16个字节

-1字节感谢Martin Ender。

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

在线尝试!

替代解决方案,17个字节

Fold[g]@*Diagonal

在线尝试!


17个字节(可以使用给定名称假定黑盒功能)
Xcoder先生,18年

@*{}语法没有多大意义(您可能会说@*List),但是无论如何它都是有效的。实际上,这意味着您可以用替换{}a 0并保存一个字节。
马丁·恩德

@MartinEnder实际上我确实是List第一个,但是我{}只是尝试了一下,对此功能感到非常惊讶。有道理,但如何0运作?o0
完全人类的

1
@totallyhuman与相同{}。您当前正在{}用作函数(或实际上使用Mathematica术语作为“头”)。如果在f那里使用泛型,就可以得到f[1,2,3](如果那是对角线)。但是随着{}你得到{}[1,2,3]。那是一个完全没有意义的表达式,但是head本身可以是任意表达式,而且如果Mathematica不知道如何处理它们,它将直接保留它们。实际上,大多数Mathematica的列表操作函数都可以使用带有任意头的表达式,在情况下Fold,头被忽略。[tbc]
马丁·恩德

因此,您可以改用0head作为头,它0[1,2,3]仍然没有意义,但工作原理相同。
Martin Ender

4

八度61 57 53字节

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

在线尝试!

定义一个g带有函数句柄f和矩阵的函数m。在第一次迭代中,m(1)返回左上角的矩阵元素;之后,它仅返回m



@Giuseppe这就是我最初使用61字节版本的操作。当然,我应该结合使用57字节和61字节版本的优点,确实给出了53字节的答案。感谢您让我再看一次!
Sanchises

3

清洁,56字节

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

在线尝试!从右到左折叠。

[t\\[_:t]<-r]与相同map tl r,但不需要import StdEnv


非常优雅地回避StdEnv
世纪

3

Haskell47 45 42字节

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

在线尝试!定义一个功能(%),将一个函数和一个矩阵作为一个列表列表作为输入。

该函数从右到左折叠:

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

编辑:-2个字节归功于BMO,-3个字节归功于Zgarb


1
通过使用$和简化条件字节数43个字节*>
Zgarb

@Zgarb好主意*>
Laikoni '18

3

APL(Dyalog Unicode),7个字节(Adám的SBCS

⎕/1 1⍉⎕

在线尝试!

-3感谢Adám将其转换为完整程序的建议

右到左。


无需在此处使用Adám的SBCS:您可以仅使用Dyalog Classic。
扎卡里

@Zacharý问题是我用Dyalog Unicode进行应答,Classic随着时间的推移而被弃用。
暴民埃里克(Erik the Outgolfer)'18年

不是代码页thoughm的代码页将生活在
扎卡里

@Zacharý好吧,让我们保持一致。:P
暴民埃里克



2

Python 2,61个字节

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

在线尝试!

这从左到右起作用。


@AsoneTuhid可以采用任何方法,请查看(x+y)⁄2x+2y示例
Rod

是的,我读错了,很抱歉
Asone Tuhid

2

JavaScript(ES6),58 56字节

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

从左到右折叠。编辑:通过使用数组严格为正的事实节省了2个字节。备用解决方案,也为56个字节:

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

它看起来好像不需要1/,您可以通过移动一些内容来节省另外2个字节:f=>a=>(h=r=>(e=a[++i]&&a[i][i])?h(f(r,e)):r)(a[i=0][0])TIO
Shaggy

@Shaggy哦,严格来说是肯定的,我还没有看到。
尼尔

显然,我们可以假定黑盒函数已分配给预定义的变量,因此如果您想利用它,可以节省2个字节。
粗野的

@Shaggy实际上我认为它将f,比第一个版本节省4个字节(2x )?
尼尔

你是对的; 抱歉,忘记再拨f,电话g时的费用。
粗野的

2

JavaScript,46个字节

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

感谢@Shaggy,按位使用或保存一个字节。太神奇了。


如果矩阵的行数多于列数,这似乎不起作用。
毛茸茸的

@Shaggy好难过,现在有47个字节...
tsh

是的,那也是我最初的想法。打算将修复程序编辑到我的解决方案中,但是您也打败了我:(我认为您可以通过使用按位OR来恢复一个字节
。– Shaggy

@Shaggy so magic
tsh

忘了提及:显然,我们可以假定黑盒函数已分配给预定义的变量,因此如果您想利用它,可以节省3个字节。
粗野的

2

Java 8,88 81 70字节

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

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

通过@KamilDrakari间接地感谢-7个字节,方法是使用与他在C#答案中所做的类似的技巧:而不是根据行/ 列为循环设置最大边界,只需尝试捕获ArrayIndexOutOfBoundsException
-11个字节替换catch(Exception e)finally

在线尝试。

旧的88个字节的答案:

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

在线尝试。

说明:

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

黑匣子输入格式:

假设存在一个命名函数int f(int x,int y)根据此元答案可以使用

我有一个Test包含默认函数f(x,y)以及上面的lambda 的抽象类:

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

对于测试用例,我将覆盖此函数f。例如,第一个测试用例的调用方式如下:

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

附件,14字节

Fold#/Diagonal

在线尝试!设置为f并调用为f[function, array]

说明

这是两个功能的分叉:Fold/Diagonal。对于参数fa,这等效于:

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

/,一元化地应用于函数时,将返回应用于其最后一个参数的函数。因此,这等效于:

Fold[f, Diagonal[a]]

这会将函数折叠到f的主对角线上a


可以自

@Adám; D确实是的!
科纳·奥布莱恩

2

AWK,77字节

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}

在线尝试!

我很好奇 AWK可以进行函数式编程。我认为这很重要。

“矩阵”定义为标准关联数组,带有额外字段M[1]=#rowsM[2]=#columns。函数名称以字符串形式传递,该字符串通过@F(...)语法进行评估。评估从左到右执行。该r参数是一个占位符,以防止覆盖现有r变量并避免需要为每个调用重新初始化。通常,会在中添加额外的空间来指定此类占位符AWK,但这是代码高尔夫,因此每个字节都很重要。:)

TIO链接实现了所有测试用例。


2

05AB1E15 10字节

从右到左的折叠
按照Kevin Cruijssen的建议,使用新的内置方法节省了5个字节

Å\`[.g#I.V

说明

与旧版本相同,除了 Å\是用于推动主对角线的新内置工具。

在线尝试! 或作为测试套件

旧版

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

在线尝试! 或作为测试套件

说明

¬                 # 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è}[Å\`[现在可以保存5个字节。
凯文·克鲁伊森

1

外壳,7个字节

感谢@Zgarb修正了我的提交!

Ḟ₁§z!Tŀ

左侧的助理,在线尝试!(对于右关联版本,只需替换F

说明

不幸的是,没有简单的方法来获取矩阵的对角线,因此大多数字节用于此:

Ḟ₁§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

呵呵,内置用于对角线,但不用于对角线

2
@Adám我认为那是因为您可以计算无限矩阵的对角线,但不能计算对角线。
马丁·恩德

1

SNOBOL4(CSNOBOL4),86字节

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)')

在线尝试!

定义一个函数T(用于TRACEARRAY和字符串F作为函数名称的。从左到右折叠。

使用间接引用($)不适用于函数。所以用EVAL字符串并将其传递给名称似乎是在SNOBOL中获得黑盒功能的唯一方法。

另外,定义数组是很痛苦的。但是,由于无效的数组引用cause FAILURE,这适用于非正方形数组-如果I任一维度的边界都超出范围, F(RETURN)强制该函数返回。

编辑:

可能基于此meta post,我可能假设黑盒函数F是在name下定义的F,该函数会将其降至75个字节(在函数定义中删除EVAL,F)。但是,我更喜欢这个版本,因为它更接近传递对函数的引用。



1

tinylisp,79字节

(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

最后一行是一个未命名的lambda函数,该函数采用一个函数和一个矩阵并返回矩阵轨迹。迹线是左关联的(即f(f(1,5),9))。在线尝试!

不打高尔夫球

我们定义了一个辅助函数来计算对角线。然后generalized-trace只是库函数的一个小包装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))))

在递归计算对角线时,我们检查是否(head matrix)为真。如果矩阵不在行中,它将为空列表(nil),而headnil为nil--falsey。或者,如果矩阵不在列中,则其第一行(头)将为空列表(nil)-假。否则,将有一个非空的第一行,这是事实。

因此,如果第一行不存在或为空,则返回nil。否则,如果存在非空的第一行,(head (head matrix))则将第一行的第一个元素作为参数cons(并将其添加)到递归调用的结果中。递归调用的参数是(map tail (tail matrix))-即,采用除第一行以外的所有行,并采用除每一行的第一行以外的所有元素。



1

C#(Visual C#编译器)72 69 60字节

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

在线尝试!

try/catch 只需沿着对角线并在越界时终止即可正确地到达对角线。

节省了3个字节,因为正如凯文·克鲁伊森(Kevin Cruijssen)所指出的,可以假定黑盒函数以特定名称存在

通过修改参数返回可节省9个字节。

因此,通过将所需的函数存储在名称下并f调用来调用该函数trace(matrix),并将结果存储在中matrix[0][0]

另外,如果您真的很喜欢冗长,

C#(Visual C#编译器)97 + 13 = 110 78 69字节

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

在线尝试!

32 bytes saved by using a predefined function, because not taking the function as a parameter allowed removing the System import and the long Func generic type.


Nice trick with the try-catch. I've been able to golf 7 bytes on my Java 8 answer (even though I have to use catch(Exception e) instead of catch. :) EDIT: Oh, been able to replace the catch(Exception e) with finally to save more bytes. Thanks again. +1 from me.
Kevin Cruijssen

@KevinCruijssen you may also be able to benefit from my newest improvement (though I don't remember for sure whether Java is amenable to modifying arguments)
Kamil Drakari

Thanks for letting me know. Although it is possible in Java, it means I'll have to change the finally into catch(Exception e), because I'm not returning inside the finally anymore. So m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}} (73 bytes) is unfortunately longer for me in comparison to my current answer m->{int r=m[0][0],i=1;try{for(;;)r=f(r,m[i][i++]);}finally{return r;}} (70 bytes) But indeed a nice way to save bytes in your answer! :) Too bad I can only +1 your answer once.
Kevin Cruijssen

1

JavaScript, 61 57 56 52 50 44 42 bytes

Reduces left to right. Assumes the function is assigned to variable f, as per this meta post brought to my attention by Mr. Xcoder & totallyhuman. Can't say as I agree with it as it directly contradicts our existing consensus that we may not assume input is assigned to a pre-defined variable, but I'll take the few bytes saving for now.

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

Test Cases

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

APL NARS, 20 bytes, 10 chars

{⍺⍺/1 1⍉⍵}

test:

  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

Good job. While I think you arrive to this on you own, it happens to be identical to Erik the Outgolfer's original solution.
Adám

0

Jelly, 5 bytes

Left-to-right.

ŒDḢç/

Try it online!

Disclaimer: I do not know if this an acceptable input method for black-box functions. This assumes that the function is implemented in the link above, and is thus "named" (that is, it's callable with) ç, but otherwise I have no way to assign it to ç. If anyone has more experience with Jelly + black box functions, I would appreciate thoughts. After spending some time in chat, we figured that using ç might indeed be valid.


0

Clojure, 30 bytes

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

Reduces "from the left".


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.