模块化广播


24

作为2018年5月每月语言活动的一部分,此挑战与MATL语言的某些功能有关


介绍

在MATL中,许多双输入功能与broadcast一起逐个元素地工作。这意味着:

  • 逐元素(或向量化):该函数将具有匹配大小的两个数组作为输入。该功能定义的操作将应用于每对对应的条目。例如,使用后缀表示法:

    [2 4 6] [10 20 30] +
    

    给出输出

    [12 24 36]
    

    这也适用于多维数组。符号[1 2 3; 4 5 6]表示2× 3数组(矩阵)

    1 2 3
    4 5 6
    

    2沿第一个尺寸(垂直)和3沿第二个尺寸(水平)具有尺寸。所以举个例子

    [2 4 6; 3 5 7] [10 20 30; 40 60 80] *
    

    [20 80 180; 120 300 560]
    
  • 广播或(单例扩展):两个输入数组没有匹配的大小,但是在每个不匹配的维度中,其中一个数组具有size 1。该数组沿其他维度隐式复制,以使大小匹配;然后按上述元素操作方式进行操作。例如,考虑两个具有1× 23× 大小的输入数组1

    [10 20] [1; 2; 5] /
    

    多亏了广播,这相当于

    [10 20; 10 20; 10 20] [1 1; 2 2; 5 5] /
    

    所以它

    [10 20; 5 10; 2 4]
    

    同样,使用3× 23× 1(现在广播仅沿第二维起作用),

    [9 8; 7 6; 5 4] [10; 20; 30] +
    

    [19 18; 27 26; 35 34]
    

    尺寸的数量甚至可以不同。例如,大小为3×2和3×1×5的输入是兼容的,并给出3×2×5的结果。实际上,大小3×2与3×2×1相同(存在许多隐式尾随单例尺寸)。

    另一方面,一对2× 23× 1数组会产生错误,因为沿第一维的大小为23:它们不相等,并且都不是1

模块化广播的定义

模块化广播是对广播的概括,即使不匹配的大小都不为,广播也可以工作1。例如,考虑以下2× 23× 1数组作为函数的输入+

[2 4; 6 8] [10; 20; 30] +

规则如下:对于每个维度,将模块化(循环)复制沿该维度较小的数组,以匹配另一个数组的大小。这将使以上内容等同于

[2 4; 6 8; 2 4] [10 10; 20 20; 30 30] +

结果

[12 14; 26 28; 32 34]

再举一个例子

[5 10; 15 20] [0 0 0 0; 1 2 3 4; 0 0 0 0; 5 6 7 8; 0 0 0 0] +

会产生

[5 10 5 10; 16 22 18 24; 5 10 5 10; 20 26 22 28; 5 10 5 10]

通常,大小为a× bc×的输入d给出大小为max(a,b)× 的结果max(c,d)

挑战

实施除了用于二维与阵列模块化广播如上定义。

数组将是矩形的(不参差不齐),将仅包含非负整数,并且至少1在每个维度上均具有大小

附加规则:

测试用例

以下内容;用作行分隔符(如上例所示)。每个测试用例都显示两个输入,然后显示输出。

[2 4; 6 8]
[10; 20; 30]
[12 14; 26 28; 32 34]

[5 10; 15 20]
[0 0 0 0; 1 2 3 4; 0 0 0 0; 5 6 7 8; 0 0 0 0]
[5 10 5 10; 16 22 18 24; 5 10 5 10; 20 26 22 28; 5 10 5 10]

[1]
[2]
[3]

[1; 2]
[10]
[11; 12]

[1 2 3 4 5]
[10 20 30]
[11 22 33 14 25]

[9 12 5; 5 4 2]
[4 2; 7 3; 15 6; 4 0; 3 3]
[13 14 9;12 7 9;24 18 20;9 4 6;12 15 8]

[9 12 5; 5 4 2]
[4 2 6 7; 7 3 7 3; 15 6 0 1; 4 0 1 16; 3 3 3 8]
[13 14 11 16; 12 7 9 8; 24 18 5 10; 9 4 3 21; 12 15 8 17]

[6 7 9]
[4 2 5]
[10 9 14]

“二维数组的实现加法”-存在一维测试用例。
乔纳森·艾伦

我们可以假设我们没有得到参差不齐的数组输入吗?(看起来像)
乔纳森·艾伦

1
@JonathanAllan抱歉,不清楚。是的,您可以假设没有破烂的数组。它们将是矩形阵列。“一维”尺寸应视为尺寸为1× n(例如[1 2 3])或n× 1(例如[1; 2; 3])的二维
Luis Mendo,

您描述的广播似乎比MATLAB或NumPy广播受到更多限制;在您的描述中,输入必须具有相同数量的维,这是MATLAB或NumPy中不存在的限制。这是MATL限制,还是为了挑战的目的而简化(因为挑战仅限于2D输入)?
user2357112支持Monica

@ user2357112是的,这只是描述中的简化。MATL的广播与MATLAB中的广播相同:您可以具有3×2和3×1×5输入,并获得3×2×5的结果。实际上,3×2等效于3×2×1(隐式尾随尺寸)。我认为在Numpy中类似(但具有领先的尺寸)。我已经澄清,在引进
路易斯Mendo

Answers:


4

果冻,10字节

ṁ€ZL$Z€Ɗ⁺S

将一个矩阵对(两个行阵列)作为输入并返回一个矩阵。

在线尝试!

怎么运行的

ṁ€ZL$Z€Ɗ⁺S  Main link. Argument: [M, N] (matrix pair)

  Z $       Zip M with N (i.e., transpose the matrix of arrays [M, N], ...
   L            then take the length (number of rows) of the result.
ṁ€          Mold M and N like the indices, cyclically repeating their rows as many
            times as needed to reach the length to the right.
     Z€     Zip each; transpose both M and N.
       Ɗ⁺   Combine the three links to the left into a chain and duplicate it.
            The first run enlarges the columns, the second run the rows.
         S  Take the sum of the modified matrices.

1
当然...我认为所有这些高尔夫语言在挑战所必需的字节(Jelly,05AB1E,Pyth,APL等)方面都有些兼容,当前大多数答案约为20个字节,Wizard Dennis随之而来一半的答案..;)当模因和真理是相同的时,这很有趣:“ 没人比丹尼斯高得多!
凯文·克鲁伊森

1
@KevinCruijssen APL不是高尔夫语言。
亚当

1
@Adám我知道,我知道。但是它仍然很短(尽管最早是在1960年代开发的)。也许我应该说短语言而不是打高尔夫球的语言。嗯..
Kevin Cruijssen

5

木炭25 23字节

AθIE⌈EθLιE⌈EθL§λ⁰ΣE觧νιλ

在线尝试!链接是详细版本的代码。将输入作为3维数组。说明:

Aθ

输入所有内容。

    θ                   Input
   E                    Map over arrays
      ι                 Current array
     L                  Length
  ⌈                     Maximum
 E                      Map over implicit range
          θ             Input
         E              Map over arrays
             λ          Current array
            § ⁰         First element
           L            Length
        ⌈               Maximum
       E                Map over implicit range
                 θ      Input
                E       Map over arrays
                    ν   Current array
                   § ι  Cyclically index using outer loop index
                  §   λ Cyclically index using inner loop index
               Σ        Sum
I                       Cast to string
                        Implicitly print on separate lines and paragraphs

:P(> _>则更长)
ASCII码,仅ASCII

5

MATL25 24字节

,iZy]vX>XKx,@GK:KP:3$)]+

在线尝试!

最后!本月的语言仅用了一周的时间就回答了本月语言挑战

我的猜测是它的长度不太短,但是我很高兴,因为我的初始版本超过40个字节。编辑:我是对的,路易斯找到了另一个要挤出的字节!

,iZy]	# do twice: read input and find the size of each dimension
vX>	# find the maximum along each dimension
XKx	# save this into clipboard K and delete from stack. Stack is now empty.
,	# do twice:
 @G	# push the input at index i where i=0,1.
	# MATL indexes modularly, so 0 corresponds to the second input
 K:	# push the range 1...K[1]
 KP:	# push the range 1...K[2]
 3$)	# use 3-input ) function, which uses modular indexing
	# to expand the rows and columns to the appropriate broadcasted size
]	# end of loop
+	# sum the now appropriately-sized matrices and implicitly display

等待路易斯·门多(Luis Mendo)再打5个字节;-)
朱塞佩(Giuseppe)

:-D我的测试用例程序有26个字节,做得很好!尼斯使用:与向量输入
路易斯Mendo

4

Python 3中127个 126 125字节

通过更改sum(m)m+n

@Jonathan Frech多了一个字节

lambda y:[[m+n for n,m,j in Z(l)]for*l,i in Z(y)]
from itertools import*
Z=lambda y:zip(*map(cycle,y),range(max(map(len,y))))

将输入作为两个二维数组的列表。

  • 所述Z的λ取两个数组作为输入并返回迭代产生的索引,并且从两个阵列合并值,直到指数达到最大数组的长度。index变量对我没有用,并消耗了我的字节数,但是我不知道该如何使用它...(相关
  • 主lambda只是接受输入数组,然后调用Z外部和内部数组。最里面的值加在一起。

在线尝试!

使用itertools.cycle感觉有点像作弊,但我认为我已经被纯粹的import语句长度所惩罚:)

我敢肯定,这可以golfed多一些,尤其是迭代方法,它的叶子这些无用ij变量。我将不胜感激关于打高尔夫球的任何技巧,我可能会遗漏一些显而易见的东西。


您可以交换您zip的参数,反转其f理解分配,从而删除一个空格(for i,*l-> for*l,i)吗?(125个字节)?
乔纳森·弗雷希

还有一个字节,谢谢!我将更新我的帖子。
etene

3

JavaScript(ES6),131个字节

这不是正确的工作工具,也可能不是正确的方法。哦... \ _(ツ)_ /¯

a=>b=>(g=(a,b,c)=>[...Array((a[b[L='length']]?a:b)[L])].map(c))(a,b,(_,y)=>g(a[0],b[0],(_,x)=>(h=a=>a[y%a[L]][x%a[0][L]])(a)+h(b)))

在线尝试!

怎么样?

辅助函数g()创建一个与最大输入数组(ab)一样大的数组,并在其上调用回调函数c

g = (a, b, c) =>
  [...Array(
    (a[b[L = 'length']] ? a : b)[L]
  )].map(c)

辅助函数h(通过模块化广播读取(x,y)处的2D数组a

h = a => a[y % a[L]][x % a[0][L]]

现在的主要代码为:

a => b =>
  g(a, b, (_, y) =>
    g(a[0], b[0], (_, x) =>
      h(a) + h(b)
    )
  )

递归版本,134字节

a=>b=>(R=[],g=x=>a[y]||b[y]?a[0][x]+1|b[0][x]+1?g(x+1,(R[y]=R[y]||[])[x]=(h=a=>a[y%a.length][x%a[0].length])(a)+h(b)):g(+!++y):R)(y=0)

在线尝试!


3

05AB1E,15个字节

2FεIζg∍ø]øεø¨}O

在线尝试!


旧版本,25字节

é`DŠg∍)Σнg}`DŠнgδ∍€˜)ø€øO

在线尝试!

说明

15乘:

2FεIζg∍ø]øεø¨} O –完整程序。将输入作为来自STDIN的3D [A,B]列表。
2F –申请两次:
  ε–对于[A,B]中的每个:
   Iζ–转置输入(用空格填充空白)。
     g –长度(获取行数)。
      ∍–将当前项目(A或B)扩展到必要的长度。
       ø–移调。
        ] –关闭所有循环。
         ø–再次移调。
          ε–对于^中的每一行(循环结果的列):
           ø–转置色谱柱。
            ¨} –删除最后一个元素并关闭map循环。
              O –总和。

25乘:

éDDg∍)Σнg}DDgŠ∍)ø€øO–完整程序。将输入作为来自STDIN的3D列表。
é–按长度对列表进行排序。
 `D –将内容分别转储到堆栈中,复制ToS。
   Š–执行三次交换。a,b,c-> c,a,b。
    g –获取ToS的长度。
     ∍–相应地扩展较短的列表(在高度上)。
      )Σ} –将整个堆栈包装到一个列表中,并按以下顺序排序:
        нg–第一项的长度。
           `DŠ–与上面相同。
              нg–第一个元素的长度。
                –相应地扩展较短的列表(在宽度上)。 
                    )ø–将堆栈包装成列表并转置(压缩)。
                      €ø-然后压缩每个列表。
                        O –应用矢量求和。

3

R1361041039593字节

在朱塞佩的建议下,高尔夫击倒了33 35个字节。通过使用运算符作为函数名称,使字节数小于100。有关更清晰的代码,请参见历史记录。

function(x,y,d=pmax(dim(x),dim(y)))y/d[2]/d[1]+x/d[2]/d[1]
"/"=function(x,j)apply(x,1,rep,,j)

在线尝试!


真好!我已经将其压缩到104字节,但是使用applyrep.len是我考虑过的,尽管我自己还没有自己编写代码。
朱塞佩

@Giuseppe谢谢!但是104版本没有提供预期的输出。
JayCe '18年

1
gh,我一直误入歧途! 这个应该工作
朱塞佩

1
@Giuseppe喜欢使用dim,更加清洁,并通过递归调用r
JayCe

我一直在尝试使用outer(x,y,"+")包含所有正确总和的明文形式。无法弄清楚如何有效地提取它们。
ngm


2

05AB1E,18个字节

éR`UvXNèy‚é`©g∍®+ˆ

在线尝试!

说明

éR                  # sort by length, descending
  `U                # store the shorter list in X
    v               # for each list y, index N in the longer list
     XNè            # get the nth element of the shorter list
        y‚é         # pair with y and sort by length
           `©g∍     # repeat the shorter list to the same length as the longer
               ®+   # elementwise addition of the lists
                 ˆ  # add to global list
                    # implicitly print global list

2

Pyth,24个字节

KeSmlhdQmm+Fm@@bdkQKeSlM

在这里尝试

说明

KeSmlhdQmm+Fm@@bdkQKeSlM
                    eSlMQ  Get the maximum length of (implicit) input...
KeSmlhdQ           K       ... and the maximum row length.
        mm                 For each 2d index ...
          +Fm@@bdkQ        ... get the sum of the appropriate elements.

2

Java 8,172字节

A->B->{int m=A.length,o=A[0].length,d=B.length,u=B[0].length,l=m>d?m:d,a=o>u?o:u,r[][]=new int[l][a],$;for(;l-->0;)for($=a;$-->0;)r[l][$]=A[l%m][$%o]+B[l%d][$%u];return r;}

在线尝试。

说明:

A->B->{                   // Method with integer-matrix as both parameters and return-type
  int m=A.length,         //  Rows of `A`                        (we got an     M)
      o=A[0].length,      //  Columns of `A`                     (we got an     O)
      d=B.length,         //  Rows of `B`                        (we got a      D)
      u=B[0].length,      //  Columns of `B`                     (we got a      U)
      l=m>d?m:d,          //  Maximum of both rows               (we got an     L)
      a=o>u?o:u,          //  Maximum of both columns            (we got an     A)
      r[][]=new int[l][a],//  Result-matrix of size `l` by `a`   (and we got an R)
      $;                  //  Temp integer                       (which $pells? ;P)
  for(;l-->0;)            //  Loop over the rows
    for($=a;$-->0;)       //   Inner loop over the columns
      r[l][$]=            //    Set the current cell in the result-matrix to:
        A[l%m][$%o]       //     The value at {`l` modulo-`m`, `$` modulo-`o`} in `A`
        +B[l%d][$%u];     //     Plus the value at {`l` modulo-`d`, `$` modulo-`u`} in `B`
  return r;}              //  Return the result matrix


2

Python 2中124个 116字节

l=len
A,B=sorted(input(),key=l)
A*=l(B)
for i in eval(`zip(A,B)`):a,b=sorted(i,key=l);a*=l(b);print map(sum,zip(*i))

在线尝试!

说明:

将两个二维列表作为输入。

l=len
A,B=sorted(input(),key=l)         # Sort inputed lists by length
A*=l(B)                           # Extend shorter list
for i in eval(`zip(A,B)`):        # Zip and remove copied references
  a,b=sorted(i,key=l)             # Sort lists in each pair (keep references)
  a*=l(b)                         # Extend shorter list
  print map(sum,zip(*i))          # Zip and sum

我从我们的两个解决方案中汲取了点创意,最后缩减到105个字节。不过我不得不使用Python 2,并且从您的代码中得到了乘法技巧,因此更新我的答案并不恰当:)
etene

1
@etene您应该发布它,这是一个很好的解决方案!
死负鼠

该死,我这是很愚蠢的错误,再次感谢您!
etene

1
@etene刚注意到,该解决方案存在2个和6个测试用例的问题。需要删除复制的参考文献
Dead Possum,

1
@etene返回到105个字节:C
死负鼠

2

Python 2中101个 97 105字节

编辑:再次感谢Dead Possum节省了4个字节

编辑2:丢失8个字节,一些测试用例没有通过

之间的混合死貂的早期解决方案(感谢他!),和我自己的Python 3溶液

lambda y:[map(sum,P(i))for i in P(y)]
def P(y):y=sorted(y,key=len);y[0]*=len(y[1]);return eval(`zip(*y)`)

在线尝试!

输入与我的Python 3解决方案相同(一对二维列表)。

注释代码:

# Iterate over the nested lists, resized & joined by P(),
# and sum the inner joined items
lambda y:[map(sum,P(i))for i in P(y)]
def P(y):
 y=sorted(y,key=len)  # Sort the two input lists by length
 y[0]*=len(y[1])      # Multiply the smallest one by the biggest one's length
                      # (The smallest list is now the previously largest one)
 return eval(`zip(*y)`)  # Return paired list elements up to the smallest list's length

1

朱0.685 83个字节

M\N=(((r,c),(s,d))=size.((M,N));repmat(M,s,d)+repmat(N,r,c))[1:max(r,s),1:max(c,d)]

在线尝试!

(替换\感谢乔金

通过在水平和垂直方向上重复每个矩阵,使它们都具有相同的大小(行大小的乘积x列大小的乘积),将它们相加并从中提取出正确的区域来工作。(行向量输入或列向量输入需要将reshape调用转换为二维数组,我认为这很好,因为问题指定了“二维数组的实现加法”,而“输入和输出可以由任何合理的手段。其格式照常灵活。”)

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.