您可以将这根弦切成多少块?


45

考虑一条字符串(如“绳子”,而不是“一串字符”),该字符串在实线上来回折叠。我们可以通过(按顺序)通过的点列表来描述字符串的形状。为了简单起见,我们假定所有这些点都是整数。

举个例子[-1, 3, 1, -2, 5, 2, 3, 4](注意,并非每个条目都包含一个折叠):

在此处输入图片说明

沿垂直方向延伸的字符串仅用于可视化目的。想象一下,所有的弦线都扁平化到了实线上。

现在的问题是:一次切割就可以切成最大的弦数(在上图中必须是垂直的)。在这种情况下,答案是6,且在2和之间的任意位置都有一个割线3

在此处输入图片说明

为了避免歧义,切口具有在一个非整数的位置被执行。

挑战

给定一串可折叠的整数位置列表,您将确定一次可在非整数位置进行一次切割即可切割的最大片段数。

您可以编写完整的程序或函数。您可以通过STDIN,命令行参数,提示符或函数参数进行输入。您可以将输出写入STDOUT,在对话框中显示或从函数返回。

您可以假定该列表采用任何方便的列表或字符串格式。

该列表将包含至少2个且不超过100个条目。入口将整数,每个范围-2 31 ≤p <2 31。您可以假定没有两个连续的条目相同。

您的代码必须在合理的台式PC上在不到10秒的时间内处理任何此类输入(包括下面的测试用例)。

测试用例

所有测试用例只需输入,然后输出即可。

[0, 1]
2

[2147483647, -2147483648]
2

[0, 1, -1]
3

[1, 0, -1]
2

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

[-1122432493, -1297520062, 1893305528, 1165360246, -1888929223, 385040723, -80352673, 1372936505, 2115121074, -1856246962, 1501350808, -183583125, 2134014610, 720827868,  -1915801069, -829434432, 444418495, -207928085, -764106377, -180766255, 429579526,  -1887092002, -1139248992, -1967220622, -541417291, -1617463896, 517511661, -1781260846,  -804604982, 834431625, 1800360467, 603678316, 557395424, -763031007, -1336769888,  -1871888929, 1594598244, 1789292665, 962604079, -1185224024, 199953143, -1078097556, 1286821852, -1441858782, -1050367058, 956106641, -1792710927, -417329507, 1298074488,  -2081642949, -1142130252, 2069006433, -889029611, 2083629927, 1621142867, -1340561463,  676558478, 78265900, -1317128172, 1763225513, 1783160195, 483383997, -1548533202,  2122113423, -1197641704, 319428736, -116274800, -888049925, -798148170, 1768740405,  473572890, -1931167061, -298056529, 1602950715, -412370479, -2044658831, -1165885212,  -865307089, -969908936, 203868919, 278855174, -729662598, -1950547957, 679003141,  1423171080, 1870799802, 1978532600, 107162612, -1482878754, -1512232885, 1595639326,  1848766908, -321446009, -1491438272, 1619109855, 351277170, 1034981600, 421097157,  1072577364, -538901064]
53

[-2142140080, -2066313811, -2015945568, -2013211927, -1988504811, -1884073403, -1860777718,  -1852780618, -1829202121, -1754543670, -1589422902, -1557970039, -1507704627, -1410033893,  -1313864752, -1191655050, -1183729403, -1155076106, -1150685547, -1148162179, -1143013543,  -1012615847, -914543424, -898063429, -831941836, -808337369, -807593292, -775755312, -682786953, -679343381, -657346098, -616936747, -545017823, -522339238, -501194053,  -473081322, -376141541, -350526016, -344380659, -341195356, -303406389, -285611307, -282860017, -156809093, -127312384, -24161190, -420036, 50190256, 74000721, 84358785,  102958758, 124538981, 131053395, 280688418, 281444103, 303002802, 309255004, 360083648,  400920491, 429956579, 478710051, 500159683, 518335017, 559645553, 560041153, 638459051,  640161676, 643850364, 671996492, 733068514, 743285502, 1027514169, 1142193844, 1145750868,  1187862077, 1219366484, 1347996225, 1357239296, 1384342636, 1387532909, 1408330157,  1490584236, 1496234950, 1515355210, 1567464831, 1790076258, 1829519996, 1889752281,  1903484827, 1904323014, 1912488777, 1939200260, 2061174784, 2074677533, 2080731335, 2111876929, 2115658011, 2118089950, 2127342676, 2145430585]
2

我们是否可以假设您希望将切块放在保证最大切块数的位置?
DavidC

2
我可能会说,“确定最大数量”而不是“确定多少数量”。
DavidC

1
不是a reasonable desktop PC很am昧吗?
globby 2015年

3
@globby这是当运行时不是获胜标准的一部分(但仅用于确保解决方案不使用蛮力)时使用的一个相当普遍的短语。这主要意味着该限制不是100%严格的。如果您的计算机上花费15秒(并且您没有使用超级计算机),那么周围的某人可能会在10秒内完成台式PC的安装。但是,如果在您的计算机上花费一分钟的可能性很小,那么您就必须考虑采用另一种方法。同样,选择限制以使有效的算法将在10秒之内轻松完成。
马丁·恩德

2
@ZainR 不。
马丁·恩德

Answers:


16

APL,16 14字节

1+⌈/+/2≠/∘.≤⍨⎕

感谢@ngn节省2个字节。

实际上是一个盒子字符,而不是缺字体错误。您可以在tryapl.org上尝试该程序,但是由于那里没有完全支持该程序,因此您必须将其替换为输入值:

    1+⌈/+/2≠/∘.≤⍨ ¯1 3 1 ¯2 5 2 3 4
6

说明

使用示例输入可以最好地解释该程序,该示例输入s = ¯1 3 1 ¯2 5 2 3 4来自STDIN,由。首先,我们计算的-外产品s自身使用∘.≤⍨。这将产生一个布尔矩阵,该布尔矩阵的i第t行表明的哪些元素s小于或等于s[i]

1 1 1 0 1 1 1 1
0 1 0 0 1 0 1 1
0 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1
0 0 0 0 1 0 0 0
0 1 0 0 1 1 1 1
0 1 0 0 1 0 1 1
0 0 0 0 1 0 0 1

行标记处0 11 0上出现的i地方是字符串经过点的地方s[i] + 0.5。我们使用2≠/“减少2个子列表” ,在每一行上进行匹配:

0 0 1 1 0 0 0
1 1 0 1 1 1 0
1 0 1 1 0 0 0
0 0 0 0 0 0 0
0 0 0 1 1 0 0
1 1 0 1 0 0 0
1 1 0 1 1 1 0
0 0 0 1 1 0 1

剩下的就是用 +/

2 5 3 0 2 3 5 3

和一个加上这些的最大值1+⌈/

6

在大多数APL实现中,结果将自动打印到STDOUT。


@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳我的错-预期结果是件数,而不是生产它的位置。
J ...

从技术上讲,这是16个字符,28个字节。Unicode将为您做到这一点= P
KChaloux

1
@KChaloux仅当您以utf8字节计数时才使用,而对于APL则不这样。有一个单字节代码页,其中包含APL使用的整个字符集,因此使用它来进行计数是很公平的。
马丁·恩德

@MartinBüttner一个可靠的源链接会很棒。否则,某人可以制作自己的任意网页,其中只包含用于任何语言的一组字符以减少字节数。
agweber

1
@GuillaumeLethuillier APL实际上非常容易学习,至少可以写这样的简单高尔夫答案。有几十个函数具有易于记忆的名称(例如×乘法)和非常简单的语法规则。谷歌“掌握Dyalog APL”是一个很好的指南。
Zgarb 2015年

16

Python,88 75 73字节

lambda x:max(sum((a+.5-m)*(a+.5-n)<0for m,n in zip(x,x[1:]))for a in x)+1

只是一个简单的lambda


只是为了展示另一种方法:

Pyth,28 27字节

heSmsmq@S+k(d)1dC,QtQm+b.5Q

这个大概相当于

lambda x:max(sum(a+.5==sorted(n+(a+.5,))[1]for n in zip(x,x[1:]))for a in x)+1

从STDIN应用于输入列表。在在线解释器上尝试一下。


您甚至可以将函数存储为相同数量的字符:def f(x):max(sum((a+.5-m)*(a+.5-n)<0for m,n in zip(x,x[1:]))for a in x)+1
Christian Sonne 2015年

4
@ChristianSonne您的函数不返回任何内容。
2015年

射门,你是对的@Jakube
Christian Sonne

我不完全确定这是如何工作的,但我认为您可以删除+.5s以保存一些字符。我意识到他们对我毫无意义。
KSFT 2015年

@KSFT它将字符串分成多个间隔,遍历每个间隔a = point + .5并计算严格包含的间隔数a。没有这种情况,.5您将遇到类似[1, 0, -1]示例的问题。
Sp3000

16

Pyth31 30 29 28 24 23个字符(Python 68个字符)

heSmsm&<hSkdgeSkdC,tQQQ

在这里尝试:Pyth编译器/执行器

它期望一个整数列表作为输入 [-1, 3, 1, -2, 5, 2, 3, 4]

这是我的Python程序的直接翻译:

lambda s:1+max(sum(min(a)<i<=max(a)for a in zip(s,s[1:]))for i in s)

旧解决方案:Pyth 28个字符

仅出于存档原因。

heSmsm<*-dhk-dek0C,tQQm+b.5Q

相应的Python代码为:

f=lambda x:1+max(sum((i-a)*(i-b)<0for a,b in zip(x,x[1:]))for i in [j+.5 for j in x])

非常确定您可以使用它,QtQ代替[QtQ)
FryAmTheEggman 2015年

i不是交线,i - 0.5是。因此1 (实际上1 - 0.5 = 0.5)在内部(-1, 1)min(a)<i<=max(a)等于min(a) < i - 0.5 < max(a),在Pyth中用min(a) < i < max(a)+1(注意hin heSk)求解。
雅库布

我想你就在这里。或至少我找不到这种逻辑失败的任何情况……
Optimizer

您可以使用保存的字符g,也就是>=,如果更换<dheSk使用geSkd
isaacg 2015年

2
谢谢@isaacg。但是,当我对此感到非常满意和自信时,为什么为什么总是来破坏我的解决方案呢?;-)
Jakube 2015年

10

CJam,36 34 33 30字节

q~[__(+]zW<f{f{1$+$#1=}1b}$W=)

我相信,在野外还有更好的算法。尽管如此,这仍在所有测试用例所需的限制下工作(即使在在线编译器上)

输入就像

[-2142140080 -2066313811 -2015945568 -2013211927 -1988504811 -1884073403 -1860777718  -1852780618 -1829202121 -1754543670 -1589422902 -1557970039 -1507704627 -1410033893  -1313864752 -1191655050 -1183729403 -1155076106 -1150685547 -1148162179 -1143013543  -1012615847 -914543424 -898063429 -831941836 -808337369 -807593292 -775755312 -682786953 -679343381 -657346098 -616936747 -545017823 -522339238 -501194053  -473081322 -376141541 -350526016 -344380659 -341195356 -303406389 -285611307 -282860017 -156809093 -127312384 -24161190 -420036 50190256 74000721 84358785  102958758 124538981 131053395 280688418 281444103 303002802 309255004 360083648  400920491 429956579 478710051 500159683 518335017 559645553 560041153 638459051  640161676 643850364 671996492 733068514 743285502 1027514169 1142193844 1145750868  1187862077 1219366484 1347996225 1357239296 1384342636 1387532909 1408330157  1490584236 1496234950 1515355210 1567464831 1790076258 1829519996 1889752281  1903484827 1904323014 1912488777 1939200260 2061174784 2074677533 2080731335 2111876929 2115658011 2118089950 2127342676 2145430585]

输出(上述情况)为

2

这个怎么运作

q~[__(+]zW<f{f{1$+$#1=}1b}$W=)
q~                                "Evaluate input string as array";
  [__                             "Put two copies of it in an array";
     (+]                          "Shift first element of second copy to its end";
        z                         "Zip together the two arrays. This creates";
                                  "pair of adjacent elements of the input.";
         W<                       "Remove the last pair";
           f{            }        "For each element of input array, take the zipped";
                                  "array and run the code block";
             f{       }           "For each element of the zipped array along with";
                                  "the current element from input array, run this block";
               1$+                "Copy the current number and add it to the pair";
                  $#              "Sort the pair and find index of current number";;
                    1=            "check if index == 1 for a < I <= b check";
                       1b         "Get how many pairs have this number inside of them";
                          $W=)    "Get the maximum parts the rope can be cut into";

现在假设输入数组为[-1 3 1 -2 5 2 3 4],压缩步骤如下:

[-1 3 1 -2 5 2 3 4] [[-1 3 1 -2 5 2 3 4] [-1 3 1 -2 5 2 3 4]
[-1 3 1 -2 5 2 3 4] [[-1 3 1 -2 5 2 3 4] [3 1 -2 5 2 3 4 -1]
[-1 3 1 -2 5 2 3 4] [[-1 3] [3 1] [1 -2] [-2 5] [5 2] [2 3] [3 4]]]

最后一行的第二个数组是字符串的折叠。

现在,我们进行迭代[-1 3 1 -2 5 2 3 4]并计算每个集合所在的集合的数量。从该数量中获取最大值,将其增加,我们得到答案。

在这里在线尝试


10

Matlab (123)(97)(85)

是的,最后是XNOR的一种用法=)我确信它可以被更多地使用。

但老实说,我有点为MatLab成为我最了解的语言感到尴尬= /

近似运行时间为O(n^2)

编辑2:

a=input();v=2:nnz(a);disp(max(arrayfun(@(e)sum(~xor(a(v-1)<e,e<a(v))),sort(a)-.5))+1)

编辑:新的高尔夫版本(包括来自@DennisJaheruddin的提示,谢谢!)

a=input();c=sort(a)-.5;n=0;v=2:nnz(c);for e=c;n=[n,sum(~xor(a(v-1)<e,e<a(v)))];end;disp(max(n)+1)

旧版本:

a=input();
c=conv(sort(a),[.5,.5],'valid');' %find all cutting positions by taking the mean of two successive points
k=numel(c);
for e=1:k %iterate over all 'cuts'
    n(e)=sum(~xor(a(1:k)<c(e),c(e)<a(2:k+1)));%find the number of threads the cut cuts
end
disp(max(n)+1) %output the max

@MartinBüttner:我真的很喜欢你在我上床睡觉之前的小挑战!


10
我的妻子受不了XNORing
窃贼

9
@xnor做笔记的时间=)
瑕疵的

我认为您可以节省一些切点,因为折痕始终是整数:c=sort(a)-.5当然,第一个折点不在范围内,但可以肯定地更容易解决。在最坏的情况下,您可以执行此操作c(1)=[];。-您也可以剥去DISP命令,只是计算的东西将其写入标准输出.--最后,在这种情况下,numel可以被替换nnz
丹尼斯Jaheruddin

但是我为自己的conv方法感到骄傲... = D。我总是忘记了nnz,非常感谢!
瑕疵的

我可以找到很多方法来使之更短!我正在使用,disp因为有人曾经批评过您提出的方法,您还会将其他字符(var或的名称ans)写入stdout ...
骗子

9

数学134 133 104

尽管代码很大,但解决起来很有趣。另外高尔夫仍然可以通过替换的想法可以实现IntervalMemberQ[Interval[a,b],n]a<n<b

n_~f~i_:=Count[IntervalMemberQ[#,n]&/@i,1>0];
g@l_:=Max[f[#,Interval/@Partition[l,2,1]]&/@(Union@l+.5)]+1

g[{-1, 3, 1, -2, 5, 2, 3, 4}]

6


说明

list1给定的点列表 list2是一个缩短的列表,该列表删除了没有折合的数字;他们无关紧要。不必这样做,但是它会导致更清晰,更有效的解决方案。

list1 = {-1, 3, 1, -2, 5, 2, 3, 4};
list2 = {-1, 3, 1, -2, 5,2, 3, 4} //. {beg___, a_, b_, c_, end___} /; (a <= b <= c) 
 \[Or] (a >= b >= c) :> {beg, a, c, end}

list1list2中的间隔如下图所示:

NumberLinePlot[Interval /@ Partition[list1, 2, 1]]
NumberLinePlot[intervalsArrangedVertically = Interval /@ Partition[list2, 2, 1]]

间隔


我们只需要在由折叠点确定的每个间隔中测试一条直线。测试线是图中的垂直虚线。

delimitersLeftToRight = Union[list2]
testLines = delimitersLeftToRight + .5
NumberLinePlot[
 intervalsArrangedVertically = Interval /@ Partition[list2, 2, 1], 
 GridLines -> {testLines, {}}, 
 GridLinesStyle -> Directive[Gray, Dashed]]

测试线


f查找每条测试线的切割或交叉数量。x = 2.5处的线进行了5个交叉。剩下5 +1条琴弦。

f[num_, ints_] := Count[IntervalMemberQ[#, num] & /@ ints, True]
f[#, intervalsArrangedVertically] & /@ testLines
Max[%] + 1

{2,3,5,5,3,2,0}
6


8

Pyth,21个字节

heSmsmq1xS+dSkdC,tQQQ

在这里尝试。

输入为Python样式的列表,例如 [-1, 3, 1, -2, 5, 2, 3, 4]

紧密基于@jakube的程序,但具有改进的中央算法。我不对每个数字进行一次>检查,而是对三个数字进行并确保索引为1,这意味着它大于最小值,小于或等于最大值。>=.index()


7

R,86 83

经过努力,然后意识到我基本上想出了与Optimizer和其他我怀疑的解决方案相同的解决方案。

无论如何,这是一个需要向量的函数

f=function(l)max(colSums(mapply(function(n)c(l[-1],NA,l)<=n&c(l,l[-1],NA)>=n,l),T))

好,所以我有偏见,就像R。FWIW您可以通过使用T“ TRUE” 来保存3个字符
Carl Witthoft

@CarlWitthoft谢谢你的提示
MickyT

4

GolfScript(43个字节)

~[.(;]zip);{$}%:x{0=:y;x{{y>}%2,=},,}%$-1=)

在效率方面,假设比较花费O(1)时间,则为O(n ^ 2)。它将输入分成多个线段,并针对每个起点计算与之交叉的半开线段。

在线演示


4

蟒蛇-161

这可能打得更多。咬人帮助了高尔夫很多。

l=input()
d={}
for i in zip(l,l[1:]):d[sum(i)/2.]=0
for i,k in zip(l,l[1:]):
 for j in[m for m in d.keys()if min(i,k)<m<max(i,k)]:d[j]+=1
print max(d.values())+1

1
@MartinBüttner/ Jakube我修复了它。现在,它可以在十秒钟内适用于所有测试用例。
KSFT

为什么对此有两个反对意见?
KSFT 2015年

3

红宝石,63岁

在概念上类似于Python解决方案。

->a{a.map{|x|a.each_cons(2).count{|v|v.min<x&&x<=v.max}}.max+1}

在代码前添加2个字符,例如,f=如果要使用命名函数。THX到MarkReed


裸proc似乎是可以接受的答案,而无需将其分配给变量。保存两个字符。
马克·里德

3

C#,73 65字节

N=>1+N.Max(i=>N.Zip(N.Skip(1),(f,s)=>f<i+.5==i+.5<s).Count(b=>b))

阅读规则,我认为C#lambda应该做得很好。

编辑:刚刚发现Count有有用的重载进行过滤!

您可以通过定义适当的delegate类型进行测试:

delegate int solver(int[] l);

接着

var l = new int[] { -1, 3, 1, -2, 5, 2, 3, 4 };
solver s = N=>1+N.Max(i=>N.Zip(N.Skip(1),(f,s)=>f<i+.5==i+.5<s).Count(b=>b));

Console.WriteLine(s(l));

3

Matlab(63 43)

输入作为传递给函数的行向量给出f。因此,例如f([-1, 3, 1, -2, 5, 2, 3, 4])return 6

f=@(x)max(sum(diff(bsxfun(@le,2*x',x(1:end-1)+x(2:end)))~=0))+1

短版:

f=@(x)max(sum(diff(bsxfun(@lt,x',x))~=0))+1

八度(31)

bsxfun通过自动广播,可以删除八度中的内容:

f=@(x)max(sum(diff(x'<x)~=0))+1

2

JavaScript(ES6)80 82

查看评论-字节数不包括分配给F(仍需要测试)

F=l=>Math.max(...l.map(v=>l.map(t=>(n+=t>u?v<t&v>=u:v>=t&v<u,u=t),n=1,u=l[0])&&n))

在FireFox / FireBug控制台中 测试

;[
 F([0, 1])
,F([2147483647, -2147483648])
,F([0, 1, -1])
,F([1, 0, -1])
,F([-1, 3, 1, -2, 5, 2, 3, 4])  
,F([-1122432493, -1297520062, 1893305528, 1165360246, -1888929223, 385040723, -80352673, 1372936505, 2115121074, -1856246962, 1501350808, -183583125, 2134014610, 720827868, -1915801069, -829434432, 444418495, -207928085, -764106377, -180766255, 429579526, -1887092002, -1139248992, -1967220622, -541417291, -1617463896, 517511661, -1781260846, -804604982, 834431625, 1800360467, 603678316, 557395424, -763031007, -1336769888, -1871888929, 1594598244, 1789292665, 962604079, -1185224024, 199953143, -1078097556, 1286821852, -1441858782, -1050367058, 956106641, -1792710927, -417329507, 1298074488, -2081642949, -1142130252, 2069006433, -889029611, 2083629927, 1621142867, -1340561463, 676558478, 78265900, -1317128172, 1763225513, 1783160195, 483383997, -1548533202, 2122113423, -1197641704, 319428736, -116274800, -888049925, -798148170, 1768740405,  473572890, -1931167061, -298056529, 1602950715, -412370479, -2044658831, -1165885212, -865307089, -969908936, 203868919, 278855174, -729662598, -1950547957, 679003141,  1423171080, 1870799802, 1978532600, 107162612, -1482878754, -1512232885, 1595639326, 1848766908, -321446009, -1491438272, 1619109855, 351277170, 1034981600, 421097157, 1072577364, -538901064])
,F([-2142140080, -2066313811, -2015945568, -2013211927, -1988504811, -1884073403, -1860777718, -1852780618, -1829202121, -1754543670, -1589422902, -1557970039, -1507704627, -1410033893,  -1313864752, -1191655050, -1183729403, -1155076106, -1150685547, -1148162179, -1143013543,  -1012615847, -914543424, -898063429, -831941836, -808337369, -807593292, -775755312, -682786953, -679343381, -657346098, -616936747, -545017823, -522339238, -501194053,  -473081322, -376141541, -350526016, -344380659, -341195356, -303406389, -285611307, -282860017, -156809093, -127312384, -24161190, -420036, 50190256, 74000721, 84358785,  102958758, 124538981, 131053395, 280688418, 281444103, 303002802, 309255004, 360083648,  400920491, 429956579, 478710051, 500159683, 518335017, 559645553, 560041153, 638459051,  640161676, 643850364, 671996492, 733068514, 743285502, 1027514169, 1142193844, 1145750868,  1187862077, 1219366484, 1347996225, 1357239296, 1384342636, 1387532909, 1408330157,  1490584236, 1496234950, 1515355210, 1567464831, 1790076258, 1829519996, 1889752281,  1903484827, 1904323014, 1912488777, 1939200260, 2061174784, 2074677533, 2080731335, 2111876929, 2115658011, 2118089950, 2127342676, 2145430585])
]

输出量

[2、2、3、2、6、53、2]


2
基于Python lambda解决方案,您无需将函数值分配给实际变量,因此可以将两个字符分开。
马克·里德

1
是的 除非在挑战中另有说明,否则未命名的函数是完全可以的。
马丁·恩德

1

果冻,10字节

>þ`^ƝS$€Ṁ‘

在线尝试!

这个怎么运作

>þ`^ƝS$€Ṁ‘ - Main link. 1 argument        e.g.   [1, 0, -1]
>þ`        - Greater than outer product          [[0, 0, 0], [1, 0, 0], [1, 1, 0]]
      $€   - Over each sublist:           e.g.   [1, 1, 0]
    Ɲ      -   Over each overlapping pair e.g.   [1, 0]
   ^       -     Perform XOR                     1
     S     -   Take the sums                     [0, 1, 1]
        Ṁ  - Take the maximum                    1
         ‘ - Increment                           2

1

05AB1E,6个字节

ε@Ôg}à

在线尝试!

说明:

ε   }    # for each element of the input
 @       # is each element >= this one? (returns list of booleans)
  Ô      # connected uniquified
   g     # length
     à   # maximum


0

加++,27字节

D,w,@@,VbUG€<ÑBxs
L~,A€wM1+

在线尝试!

感谢Zgarb的APL解答

挑战的关键部分是实施外部产品命令。不幸的是,Add ++没有内置的功能,它没有任何定义以其他函数作为参数的函数的方法。但是,我们仍然可以使广义外积函数。由于要在另一个功能内访问功能的唯一方法是通过引用用户定义或内置的现有功能,我们必须创建一个引用此类功能的“内置”。

通用的“表”功能如下所示:

D,func,@@,+

D,iter,@@*, VbUG €{func}
D,table,@@, $ bRbU @ €{iter} B]

在线尝试!

func包含我们的操作数的二进位函数在哪里。在w函数开始时,您可以在原始提交中看到此结构的微妙相似之处,但是在这里,我们主要希望是单子外部乘积函数-一个在两侧都采用相同参数的外部乘积函数。

通用函数利用了每个快速方法如何处理二进位函数的优势。如果堆栈看起来像

 [a b c d e]

€{func}遇到时,弹出e,结合,作为左参数的对子,和地图,部分功能上a, b, c, d。但是,快速映射会覆盖整个堆栈,而不是列表。因此,我们需要先展平作为参数传递的数组。

函数的工作总体是这样

D,func,@@,+

D,iter,		; Define our helper function iter
		;   This takes an array as its left argument
		;   And a single integer as its right argument
	@@	; Dyadic arguments - take two arguments and push to the stack
	*,	; After execution, return the entire stack, rather then just the top element
		;
		; Example arguments:	[5 6 7 8] 1
		; 
	VbUG	; Unpack the array;	[5 6 7 8 1]
		;
	€{func}	; Map func over the stack
		; As func is dyadic, this pops the right argument
		;   and binds that to a monadic func
		; This then maps the remaining elements, [5 6 7 8]
		;   over the monadic call of func, yielding [6 7 8 9]
		; Now, as the * flag was defined, we return the entire array
		;   rather than just the last element.
		; We'd achieve the same behaviour by removing the flag and appending B]

D,table,	; Define the main table function
		;   This takes two arrays as arguments
		;   Returns a single 2D array representing their outer product with func
	@@,	; Take the two arrays and push to the stack
		; 
		; Example arguments:	[[1 2 3 4] [5 6 7 8]]
		;
	$	; Swap;		STACK = [[5 6 7 8] [1 2 3 4]]
	bR	; Reverse last;	STACK = [[5 6 7 8] [4 3 2 1]]
	bU	; Unpack;	STACK = [[5 6 7 8] 4 3 2 1]
	@	; Reverse;	STACK = [1 2 3 4 [5 6 7 8]]
		; 
		; This allows us to place the stack so that each element of
		;   the first array is iterated over with the second array
		;
	€{iter}	; Map iter;	STACK = [[6 7 8 9] [7 8 9 10] [8 9 10 11] [9 10 11 12]]
		;
	B]	; Return the whole stack;

$table>?>?
O

但是,由于我们需要外部表为monadic,而只需要将其应用于传递的参数,因此可以将其缩短很多。该A命令将每个参数分别推入堆栈,因此我们无需弄乱任何堆栈操作。简而言之,如果我们的参数是array [a b c d],则需要将堆栈放入

[a b c d [a b c d]]

当然,最高值是参数。您可能已经从一般示例中注意到bUunpack命令,即它将顶部数组喷溅到堆栈中。因此,要进行上述配置,我们可以使用代码

L,bUA

在线尝试!

但是,可以将其缩短一个字节。作为的别名L,bU,我们可以使用~标志来预先将参数扩展到堆栈,从而使我们的配置示例成为

L~,A

在线尝试!

这是程序第二行的开始。现在我们已经实现了Monadic外部乘积,我们只需要实现其余的算法即可。一旦使用(小于)检索的结果<,并计算每行中[0 1]和的数量[1 0]。最后,我们采用这些计数中的最大值,并将其增加。

逐步完成的完整步骤是

D,w,		; Define a function w
		;   This takes an array and an integer as arguments
		;   First, it produces the outer product with less than
		;   Then reduce overlapping pairs by XOR
		;   Finally, sum the rows
	@@,	; Take two arguments
		;
		; Example arguments:		[[0 1 2 3] 0]
		;
	VbUG€<	; Map < over the array;	STACK = [0 1 1 1]
	ÑBx	; Equals [1 0];		STACK = [1 0 0]
	s	; Sum;			STACK = [1]

L		; Define a lambda function
		;   This takes one argument, an array
	~,	;   Splat the array to the stack before doing anything
		;
		; Example argument:		[0 1 2 3]
		;
	A€w	; Map with w;		STACK = [1 1 1 0]
	M	; Maximum;		STACK = [1]
	1+	; Increment;		STACK = [2]
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.