计算尾随真相


59

受我亲爱的朋友和同事的启发,并为之缅怀,

丹·巴朗特

Dan Baronet,1956年-2016年。RIP

他为该任务找到了最短的APL解决方案

任务

给定一个布尔列表,计算尾随真值的数量。

案例案例

{}0

{0}0

{1}1

{0, 1, 1, 0, 0}0

{1, 1, 1, 0, 1}1

{1, 1, 0, 1, 1}2

{0, 0, 1, 1, 1}3

{1, 1, 1, 1, 1, 1}6


我们可以将列表作为零和一的字符串吗?例如01100
阿德南

@Adnan仅当这是您的语言表示布尔列表的最正常方式时。
2013年

71
对不起,您的损失。
马丁·恩德

6
@MartinEnder谢谢。未来将很难。Dan教了我为Dyalog工作所需的全部知识。
亚当

5
告别丹。RIP ...
Erik the Outgolfer '16

Answers:


36

Dyalog APL,6个 2字节

⊥⍨

TryAPL上进行测试

这个怎么运作

(uptack,dyadic:decode)执行基本转换。如果左操作数是向量,它将执行混合基数转换,非常适合此任务。

对于基本向量b = b n,⋯,b 0和一个数字向量a = a n,⋯,a 0b⊥aa转换为混合基b,即,计算b 0 ⋯b n-1 a n +⋯+ b 0 b 1 a 2 + b 0 a 1 + a 0

现在,(波浪号降噪,上下班)将操作符修改为左侧,如下所示。在单子上下文中,它使用相等的左右参数调用运算符。

例如,⊥⍨一个被定义为一个⊥一个,它计算一个0 ⋯一个Ñ +⋯+一个0一个120一个10,所有累积的产品从向左右侧的总和。

对于k个尾随的乘积,k个最右边的乘积为1,所有其他乘积为0,因此它们的总和等于k


14
提示:Dan仅用两个字节就做到了。
亚当

3
混合基准转换!那很聪明。
丹尼斯

1
哦。混合基准转换,如何再次发生。
科纳·奥布莱恩

太棒了!实际上,由于Dan,我们特例化了,b⊥b⊥⍨b放弃了无限的提速。
亚当

19

JavaScript(ES6),21个字节

f=l=>l.pop()?f(l)+1:0

测试用例


这是如何运作的?如何f(l)+1返回值> 2
奥利弗

@Oliver这是一个递归过程,评估为l.pop()?(l.pop()?(l.pop()?(...etc...)+1:0)+1:0)+1:0
Arnauld

我懂了。感谢您的解释。
奥利弗

11

果冻,4字节

ŒrṪP

在线尝试!验证所有测试用例。

对于列表为空的情况,有一些奇怪的发现。首先,对空列表进行游程编码会[]返回另一个空列表[]。然后retreiving从使用尾部的最后一个元素返回0,而不是一对[value, count],其是一个游程长度编码的阵列中的常规元件。然后产品在被调用时P返回00这是预期的结果。

说明

ŒrṪP  Main link. Input: list M
Œr    Run-length encode
  Ṫ   Tail, get the last value
   P  Product, multiply the values together

另外ŒgṪS,也可以!
林恩

它为空列表提供了正确的输出作为输入,但是我对解剖感到惊讶。您介意遍历这种特殊情况吗?
彼得·泰勒

@PeterTaylor我也很惊讶它起作用。另外,我只是注意到第一个链接的代码错误。
2016年

Jelly中的@PeterTaylor 实现为:lambda z: iterable(z).pop() if iterable(z) else 0iterable当在列表上调用时,仅返回列表,而空列表当然是虚假的。
FryAmTheEggman '16

10

Brachylog7 6 5字节

@]#=+

在线尝试!

说明

@]        A suffix of the Input...
  #=      ...whose elements are all equal
    +     Sum its elements

由于@] - Suffix从最大的后缀一直到最小的后缀,它将首先找到最长的运行时间。


10

CJam(8字节)

{W%0+0#}

在线测试套件

解剖

{    e# begin a block
  W%  e# reverse the array
  0+  e# append 0 so there's something to find
  0#  e# find index of first 0, which is number of nonzeros before it
}

10

Haskell,26 25字节

a%b|b=1+a|0<3=0
foldl(%)0

用法:

Prelude> foldl(%)0 [True,False,True,True]
2

无点版本(26字节):

length.fst.span id.reverse

使用整数列表而不是布尔列表(21个字节,感谢Christian Sievers):

a%b=b*(a+1)
foldl(%)0

用法:

Prelude> foldl(%)0 [1,0,1,1]
2

无点版本(25字节)

sum.fst.span(==1).reverse

对于整数列表,该foldl想法适用于a%b=b*(a+1)
Christian Sievers,2016年

9

视网膜7 5字节

r`1\G

在线尝试!(第一行启用换行分隔的测试套件。)

定义Retina的输入格式并非一模一样。由于视网膜除字符串外没有任何类型的概念(也没有可用于我们对真假的常规定义的值),因此我通常使用01(或通常是肯定的东西)来表示真假的,因为它们代表零或一些匹配项。

使用单字符表示形式时,我们也不需要列表的分隔符(从某种意义上说,对于只包含字符串的语言,列表分隔符更自然)。Adám确认这是可接受的输入格式。

至于正则表达式本身,它r从右到左\G匹配,并将每个匹配锚定到前一个。因此,这计算了1我们可以从字符串末尾匹配多少个s。


“是的,对于Retina来说,因为它只处理字符串,所以我认为顺序是“ 01”或“ FT”字符串。
Adám16年

9

05AB1E12 10 6 5字节

由于使用了carusocomputing,因此节省了1个字节。

Î0¡¤g

在线尝试!

说明

Î      # push 0 and input
 0¡    # split on 0
   ¤   # take last item in list
    g  # get length

0¡¤g是四个字节。
魔术八达通Ur

@carusocomputing:太好了!当我写这篇文章时,还没有弄清楚字符串输入是否可以,但是我现在知道了:)
Emigna

J0¡¤g还更短;)。
魔术章鱼缸

@carusocomputing:不幸的是,我们需要Î处理空的输入,但是仍然节省了一个字节,谢谢:)
Emigna




7

Mathematica,25个 24字节

Fold[If[#2,#+1,0]&,0,#]&

3
仅记录了Dan出色的混合基础解决方案的端口:FromDigits[b=Boole@#,MixedRadix@b]&(35个字节)。
格雷格·马丁


5

C90(gcc),46个字节

r;main(c,v)int**v;{while(0<--c&*v[c])r++;c=r;}

输入是通过命令行参数(每个参数一个整数),输出是通过退出代码

在线尝试!

这个怎么运作

r是全局变量。它的类型默认为int,并且是全局的,它的值默认为0

函数参数c也默认为int。对于n个布尔数组,它将保存整数n +1main的第一个参数始终是可执行文件的路径。

函数参数v声明为int**。的实际类型vchar**,但由于我们只检查每个参数的最低显著位告诉字符0(代码点48)和1(代码点49)分开,这并不重要的小尾数机器。

while循环递减c并将其与0比较。一旦c达到0,我们就会跳出循环。仅当数组不包含0时才需要。

只要0<--c返回1,我们就使用第c 命令行参数(v[c]),并通过取消引用指针(*)来提取其第一个字符。我们采取的按位与布尔的0<--c和字符(和随后的三项垃圾字节)的代码点,这样的情况会返回0一旦0遇到,打破循环。

在剩余的情况下,在命令行参数是1r++递增- [R1,从而计算后的次数1的。

最后,c=rr的计算值存储在c中。使用默认设置,编译器将优化并删除分配。它实际上会生成movl %eax, -4(%rbp)指令。由于ret返回EAX寄存器的值,因此会生成所需的输出。

请注意,此代码并不能与C99,返回工作0如果年底主要到达。


Isn't argc至少1(与argv[0]包含文件名)?您可以用--c&&代替保存一个字节0<--c&。gcc的退出代码来自argc?整齐。
泰特斯(Titus)

@Titus那行不通。*v[c]10的代码点,所以它是4948,因此始终是真实的。
丹尼斯

使用C89和C90,gcc返回当时RAX中的所有内容。如果到达末尾,C99总是从main 返回0
丹尼斯

4

k,6个字节

+/&\|:

该函数组合转换为sum mins reversein q,这是语言更易读的同级形式,其中mins是滚动最小值。


可以删除吗?
streetster

4

J,9 3个字节

#.~

这是自反的混合碱基转换。因为这与混合基准转换相同。 再次。

测试用例

   v =: #.~
   ]t =: '';0;1;0 1 1 0 0;1 1 1 0 1;1 1 0 1 1;0 0 1 1 1;1 1 1 1 1 1
++-+-+---------+---------+---------+---------+-----------+
||0|1|0 1 1 0 0|1 1 1 0 1|1 1 0 1 1|0 0 1 1 1|1 1 1 1 1 1|
++-+-+---------+---------+---------+---------+-----------+
   v&.> t
+-+-+-+-+-+-+-+-+
|0|0|1|0|1|2|3|6|
+-+-+-+-+-+-+-+-+
   (,. v&.>) t
+-----------+-+
|           |0|
+-----------+-+
|0          |0|
+-----------+-+
|1          |1|
+-----------+-+
|0 1 1 0 0  |0|
+-----------+-+
|1 1 1 0 1  |1|
+-----------+-+
|1 1 0 1 1  |2|
+-----------+-+
|0 0 1 1 1  |3|
+-----------+-+
|1 1 1 1 1 1|6|
+-----------+-+

2
提示:使用Dan解决方案的J转换只能用3个字节完成操作。
2013年

1
@Adám我尝试寻找解决方案。没想到基本转换。他真的很聪明!
科纳·奥布莱恩

1
是。那是丹。:-(
亚当

4

R,40 39 25字节

借助@Dason,完全重新设计了解决方案

sum(cumprod(rev(scan())))

从stdin读取输入,反转向量,如果!=0输出的第一个元素,则输出游程编码(rle)的第一个长度,否则输出0


1
您可以通过将第二行更改为来保存一个字节ifelse(r$v,r$l,0)[1]。(如果是矢量,则取第一个元素。)
rturnbull

1
不需要iflelse-只需将r $ v和r $ l相乘。
戴森

但是sum(cumprod(rev(。)))路由无论如何应该节省很多字节
Dason

3

Haskell,24个字节

foldl(\a b->sum[a+1|b])0

遍历列表,添加一个用于每个元素,复位到0它击中后False

16个字节(使用0/1输入):

foldl((*).(+1))0

如果列表被保证为非空,我们将获得14个字节:

sum.scanr1(*)1

这将从背面计算累积乘积,然后对其求和。累积乘积保持为1,直到命中0,然后变为0。因此,1对应于尾随的1。



3

C#6,103 72字节

using System.Linq;
int a(bool[] l)=>l.Reverse().TakeWhile(x=>x).Count();

使用非通用列表比通用列表快1字节大声笑

-31字节感谢Scott


如果使用ints 数组,则可以int a(int[] l)=>l.Reverse().TakeWhile(i=>i>0).Sum();
Scott

@Scott当然,我在想什么……不过,我还是坚持。问指定布尔列表,它不是C.
链接伍

编译Func<bool[], int>为57个字节的a ,即using System.Linq;l=>l.Reverse().TakeWhile(x=>x).Count();
TheLethalCoder


2

DASH,16字节

@len mstr"1+$"#0

这不是最短的DASH解决方案,但是最短的DASH解决方案却困扰着我。我将这种新颖的方法代替了它。

用法:

(@len mstr"1+$"#0)"100111"

说明

@(                 #. Lambda
  len (            #. Get the length of the array after...
    mstr "1+$" #0  #. ... matching the argument with regex /1+$/
  )                #. * mstr returns an empty array for no matches
)

2

Scala,25个字节

l=>l.reverse:+0 indexOf 0

取消高尔夫:

l=>(l.reverse :+ 0).indexOf(0)

反转列表,追加一个0并找到第一个索引0,即第一个0之前的元素数


2

批次,57个字节

@set n=0
@for %%n in (%*)do @set/an=n*%%n+%%n
@echo %n%

将输入作为命令行参数。通过将累加器乘以当前值然后再将其累加来工作,以便命令行中的任何零都将重置计数。请注意,%%n该变量与n%n%变量不同。



2

Java 7,62字节

int c(boolean[]a){int r=0;for(boolean b:a)r=b?r+1:0;return r;}

取消测试代码:

在这里尝试。

class M{
  static int c(boolean[] a){
    int r = 0;
    for (boolean b : a){
      r = b ? r+1 : 0;
    }
    return r;
  }

  public static void main(String[] a){
    System.out.print(c(new boolean[]{}) + ", ");
    System.out.print(c(new boolean[]{ false }) + ", ");
    System.out.print(c(new boolean[]{ true }) + ", ");
    System.out.print(c(new boolean[]{ false, true, true, false, false }) + ", ");
    System.out.print(c(new boolean[]{ true, true, true, false, true }) + ", ");
    System.out.print(c(new boolean[]{ true, true, false, true, true }) + ", ");
    System.out.print(c(new boolean[]{ false, false, true, true, true }) + ", ");
    System.out.print(c(new boolean[]{ true, true, true, true, true, true }));
  }
}

输出:

0, 0, 1, 0, 1, 2, 3, 6

2

Perl 5.10,22个字节

21个字节+ 1个字节的-a标志。由于基于正则表达式的表达式已完成...:p

数组的输入值必须用空格分隔。

$n++while pop@F;say$n

在线尝试!


1
如果通过命令行接受参数,则稍短一些:perl -E '$_++while pop;say' 0 1 1 0 1 1 1但这不会输出任何信息0(虽然不确定这是否有问题!)
Dom Hastings

2

Perl,22个字节

21个字节的代码+ 1个字节的-p标志。

s/.(?=.*0)//g;$_=y;1;

运行它:

perl -pE 's/.(?=.*0)//g;$_=y;1;' <<< "0 1 1 0 1 1 1"

(实际上,输入的格式并不重要了很多:01101110 1 1 0 1 1 1[0,1,1,0,1,1,1]等一切都能解决)


@Dom Hastings的版本18字节,但需要以0和1的字符串形式提供输入,这是不允许的:

perl -pE '/1*$/;$_=length$&' <<< '0110111'

爱那个;把戏:)如果格式是一个连续的字符串:perl -pE '/1*$/;$_=length$&' <<< '0110111'对于18,不确定是否违反了规则……
Dom Hastings

@DomHastings是的,我也是!(感谢Ton告诉我!)问题的第一和第二条评论都不允许您输入解决方案所需要的输入格式...但是,如果输入的格式更多,我将编辑我的帖子以建议您使用的版本自由。
达达

2

PHP,50个字节

<?=strlen(preg_filter('/.*[^1]/','',join($argv)));

古怪我第一次尝试用正则表达式比我尝试用数组原来短...
使用,如:

php tt.php 1 1 0 1 1

2

Ruby 37 32字节

->n{n.size-1-(n.rindex(!0)||-1)}

创建一个匿名函数,该函数查找错误值的最右边实例,并计算从该值开始的子数组的大小。

它使用!0false,因为Ruby中的true值为0。rindex查找数组中值的最后一个索引。

用法

boolean_list = [true, false, false, true]
->n{n.size-1-(n.rindex(!0)||-1)}[boolean_list]

返回 1


如果允许我将0和1的字符串作为命令行参数传递(这不是ruby表示布尔值列表的方式),我可以将其降低到24:

$*[0]=~/(1*)\z/;p$1.size

这使用正则表达式和打印由正则表达式返回字符串的长度/(1*)\z/,其中,\z是字符串的结尾。$*[0]是传递的第一个参数,是0和1的字符串。

用法:

trailing_truths.rb 011101

返回1。


1
有了最后一个假值的索引后,为什么还要再次从数组中检索元素?
李W

你是对的,我不是。谢谢。关闭5个字节!
IMP1
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.