字符串中字符的最长运行时间


19

您面临的挑战:编写一个函数,该函数需要一个字符串s,一个字符c,并找出cin中最长运行的长度s。运行的长度为l

规则

  • 如果s长度为0或c为空,l则应为0。
  • 如果cin 中没有实例sl则应为0。
  • 适用标准漏洞标准I / O规则
  • 无论在s s的运行c位置位于何处,l都应相同。
  • s和中可以出现任何可打印的ASCII字符c

测试用例

s,c --> l
"Hello, World!",'l'  -->  2
"Foobar",'o'         -->  2
"abcdef",'e'         -->  1
"three   spaces",' ' -->  3
"xxx xxxx xx",'x'    -->  4
"xxxx xx xxx",'x'    -->  4
"",'a'               -->  0
"anything",''        -->  0

优胜者

,每种语言中最短的答案将获胜。



您能否在测试用例中包括空的sc非空的边缘s情况?
Martin Ender

s/中可以显示什么字符范围c
Martin Ender

6
c可以是空的吗?在许多语言中,字符只是具有特殊语义的整数,您也不能真正拥有一个空整数。
Martin Ender

14
这对我来说真的没有意义。您的测试案例表明我们必须支持它。如果我们不必支持它,那么指定其所需的输出就没有意义了,因为我总是可以说,如果我的解决方案在这种情况下还会执行其他操作,则不支持它。
Martin Ender

Answers:


12

05AB1E,5个字节

码:

SQγOM

使用05AB1E编码。在线尝试!

说明:

SQ      # Check for each character if it is equal to the second input
  γ     # Split the list of zeros and ones into groups
   O    # Sum each array in the arrays
    M   # Get the maximum

2
不错的解决方案!我知道有办法做到这一点,我只是想不到。
莱利

γ¢M表现不像我想的那样,以为是3字节。
Magic Octopus Urn

8

Mathematica,35个字节

Max[Tr/@Split@Boole@Thread[#==#2]]&

将一个字符列表和另一个字符作为输入并返回非负整数的纯函数。在我使用Adnan的观察结果进行的第一次尝试中得到了改进(请投票!),应该在拆分数组之前测试是否等于特殊字符。

Thread[#==#2]检查第一个参数中的每个输入字符是否等于第二个参数中给出的字符。Boole将结果Trues和Falses 转换为1s和0s。Split将列表拆分为连续的元素;Tr/@对每个子列表求和,并Max找到获胜者。(由于Max工作原理,如果第一个参数是空列表,那么此函数将返回-∞。因此,请不要这样做。)

首次提交(51字节)

Max[Split@#/.a:{c_String..}:>Boole[c==#2]Length@a]&

Split@#将输入分成连续的字符,例如{{"t"}, {"h"}, {"r"}, {"e", "e"}, {" ", " ", " "}, {"s"}, {"p"}, {"a"}, {"c"}, {"e"}, {"s"}}第四个测试用例。/.a:{c_String..}:>替换每个子表达式a是一个重复的字符的列表c通过Length@a乘以Boole[c==#2],这是1如果c等于输入字符和0其它。然后Max提取答案。


7

Japt20 18 15字节

fV+Vî+)ª0)n o l

在线尝试!

由于obarakon和ETHproductions节省了5个字节


1
我玩了一段时间自己的解决方案,最后得到了几乎是您的解决方案,但是更短。如果您使用fV+Vî+)...,让您解决其余问题:-)
ETHproductions'Jun

@ETHproductions "If s is of length 0 or c is empty, l should be 0",不过我可能会从字面上理解
汤姆(Tom

哦,我没有意识到只要s不包含的任何实例都会失败c
ETHproductions

7

Python,38个字节

f=lambda s,c:+(c in s)and-~f(s,c+c[0])

在线尝试!

Dennis通过更新c为一串重复的字符而不是递归地更新要乘以的数字来节省3个字节c


1
f=lambda s,c:c in s and-~f(s,c+c[0])保存6个字节(如果不允许False,则为3个字节)。
丹尼斯,


4

Haskell,43个 39字节

f c=maximum.scanl(\n k->sum[n+1|c==k])0

在线尝试!

运行该字符串,并用一个计数器替换当前char,该计数器每当等于时增加c0否则返回。以列表的最大值。

感谢@xnor提供4个字节。


你可以的sum[n+1|c==k]
xnor

@xnor:太好了!我已经试验*fromEnum(c==k)了pointfree和lambda,但总是长2或3个字节。
nimi 2015年

4

C#116115字节

我的第一个代码高尔夫

已进行编辑,因为初始提交是一个摘要,并且缺少正则表达式所需的名称空间

Edit#2完全重写以支持具有特殊正则表达式含义的字符

使用System.Linq; s => c => System.Text.RegularExpressions.Regex.Replace(s,“ [^” + c +“]”,++ c +“”)。Split(c).Max(x => x.Length);

using System.Linq;s=>c=>{var r=(char)(c-1);return string.Join("",s.Select(x=>x==c?c:r)).Split(r).Max(x=>x.Length)};

3
我不知道C#,但看起来您的代码期望变量c并且s要进行预定义。我们称其为“代码段”,这是不允许的。您可能将代码重组为匿名函数,或将这些变量设置为输入。两者都允许。
小麦巫师

那样有用吗?(请参见上面的编辑)
扫帚

1
再次,我不知道C#,但看起来确实如此。您可能想在这里查看我们在C#中打高尔夫球的技巧,以获取有关C#的更多有经验的建议。
小麦巫师

感谢您的链接!我一定会细读C#技巧
Broom

3
在C#中,您仅可以打高尔夫球一些一般性的评论,就可以将函数定义为(s,c)=>。您必须System.Text.RegularExpressions.Regex在函数之前使用 或添加using语句。
LiefdeWen

4

JavaScript(ES6),54 53 51字节

@Neil --2 字节@@ apsillers
-1字节

s=>c=>[...s].map(x=>j=(i=x==c&&i+1)>j?i:j,i=j=0)&&j

以currying语法输入:f("foobar")("o")

测试片段

f=
s=>c=>[...s].map(x=>j=(i=x==c&&i+1)>j?i:j,i=j=0)&&j
String: <input id=I> Letter: <input id=J maxlength=1 size=1> <button onclick='O.innerHTML+=`f("${I.value}")("${J.value}") = ${f(I.value)(J.value)}\n`'>Run</button><pre id="O"></pre>

使用eval和的另一个选项for(54字节)

s=>c=>eval("i=j=0;for(x of s)i=x==c&&i+1,i>j?j=i:0;j")

使用正则表达式的旧答案(85字节)

s=>c=>c?Math.max(...s.match(eval(`/${/\w/.test(c)?c:"\\"+c}*/g`)).map(x=>x.length)):0

1
我认为x==c?i++:i=0可能是i=x==c&&i+1因为比较false结果x==c将被视为0用于数字比较和增量(并且永远不会是返回值,因为任何数字,包括0in j都将始终优先于零falsein i
apsillers

@apsillers谢谢,更新了,但是对于它永远不是返回值,您意味着什么呢?
贾斯汀·马里纳

对困惑感到抱歉; 我只是在解释说,更改永远不会使您的程序返回false(因为挑战总是要求它返回一个数字)
apsillers

1
s=>c=>[...s].map(x=>j=(x!=c?i=0:++i)>j?i:j,i=j=0)&&j似乎节省了几个字节。
尼尔

1
抱歉,我发布了错误的代码,我打算发布f=s=>c=>[...s].map(x=>j=(i=x==c&&i+1)>j?i:j,i=j=0)&&j,该代码短了一个字节。
尼尔

4

JavaScript(Firefox 30-57),75 72字节

(s,c)=>Math.max(0,...(for(s of s.split(/((.)\2*)/))if(s[0]==c)s.length))

与ES6兼容的代码段:

f=
(s,c)=>Math.max(0,...s.split(/((.)\2*)/).filter(s=>s[0]==c).map(s=>s.length))
<div oninput=o.textContent=f(s.value,c.value)><input id=s><input id=c maxlength=1 size=1><pre id=o>0

split 返回一堆空字符串和单个字符以及运行,但这不会影响结果。


3

,112字节

{T l m 1+:Q # T Q T l~:r}:Z{T[0]+}:X
{i s m:n
n p = if(Z,X)
i L=if(,a)}:a
0\\:C:s:i"":p"":n[0]:T
s l:L
a
T l m:\


2

Perl 6的 45个43  42字节

->$_,$c {$c&&$_??.comb(/$c+/)».chars.max!!0}

测试一下

->$_,$c {$c&&$_??.comb(/$c+/).max.chars!!0}

测试一下

->$_,$c {$c&$_??.comb(/$c+/).max.chars!!0}

测试一下

展开:

-> $_, $c {       # pointy block lambda

    $c & $_       # AND junction of $c and $_
                  #   empty $c would run forever
                  #   empty $_ would return 4 ( "-Inf".chars )

  ??              # if True (neither are empty)

    .comb(/$c+/)  # find all the substrings
    .max          # find the max
    .chars        # get the length

  !!              # if False (either is empty)

    0             # return 0
}

2

JavaScript,ES6、52

将字符串输入视为数组的递归解决方案(请注意:初始输入仍然是字符串),并在字符中从左到右使用C

f=([C,...s],c,t=0,T=0)=>C?f(s,c,C==c&&++t,t>T?t:T):T

跟踪的当前运行状况t和全球最佳状态T

说明:

f=            // function is stored in `f` (for recursion)
  ([C,...s],  // turn input string in first-char `C` and the rest in `s`
   c,         // argument `c` to search for
   t=0,T=0)   // current total `t`, best total `T`
     =>
        C?             // if there is still any char left in the string
          f(s,c,       // recursively call `f`
            C==c&&++t, // increment `t` if char is match, or set `t` to `false`
            t>T?t:T)   // set global `T` to max of `t` and `T`
          :T           // when string is depleted, return `T`

将on 设置tfalse不匹配t是可行的,因为无论何时将其递增,false都将被视为0(即false + 1is 1),并且false永远不会比global-max中的任何值进行比较T


1
很好的解决方案,我不熟悉[C,...s]语法。应该可以帮助我slice()减少自己帖子中的字节数。
瑞克·希区柯克

2

果冻,5个字节

=ŒgṀS

这是一个采用字符串和字符的二元链接/函数。请注意,它不能作为完整程序使用,因为命令行参数的输入使用Python语法,并且Python(与Jelly不同)不区分单例字符串和字符。

在线尝试!

怎么运行的

=ŒgṀS  Main link. Left argument: s (string). Right argument: c (character)

=      Compare all characters in s with c, yielding 1 for c and 0 otherwise.
 Œg    Group adjacent, equal Booleans in the resulting array.
   Ṁ   Take the maximum. Note that any array of 1's will be greater than any array
       of 0's, while two arrays of the same Booleans are compared by length.
    S  Take the sum, yielding the length for an array of 1's and 0 otherwise.


2

APL(Dyalog)18 11字节

需要换16.0版本或有⎕ML←3(在许多系统默认值)。

⌈/0,≢¨⊂⍨⎕=⎕

在线尝试!

⎕=⎕ 两个输入之间相等的布尔值

⊂⍨ 自分区(非零元素大于其前任元素的分区开始)

≢¨ 总计

0, 前面加零(对于空输入的情况)

⌈/ 这些最大


旧解决方案

首先提示s,然后提示c

⌈/0,(⎕,¨'+')⎕S 1⊢⎕

在线尝试!

 提示输入

 为了那个原因

(... )⎕S 1PCRE 小号目录操作搜索对出现的长度

'+' 加号(表示一个或多个)

 附加到

 提示输入c

0, 前面加零(对于空输入的情况)

⌈/ 这些最大

如果需要转义,则必须将c作为封闭字符串的1元素向量给出。


2

PHP,70 67字节

三种版本:

while(~$c=$argv[1][$i++])$x=max($x,$n=($c==$argv[2])*++$n);echo+$x;
while(~$c=$argv[1][$i++])$x=max($x,$n=$c==$argv[2]?++$n:0);echo+$x;
for(;++$n&&~$c=$argv[1][$i++];)$x=max($x,$n*=$c==$argv[2]);echo+$x;

从命令行参数获取输入;在线运行-r测试它们


2

PHP,70字节

for(;~$c=$argv[1][$i++];)$r[]=$argv[2]==$c?++$n:$n=0;echo$r?max($r):0;

在线尝试!

PHP,75字节

for(;~$s=substr($argv[1],$i++);)$r[]=strspn($s,$argv[2]);echo max($r?:[0]);

在线尝试!

PHP,83字节

<?=@preg_match_all("<".preg_quote($argv[2])."+>",$argv[1],$t)?strlen(max($t[0])):0;

在线尝试!

+8字节避免 @

<?=($a=$argv[2])&&preg_match_all("<".preg_quote($a)."+>",$argv[1],$t)?strlen(max($t[0])):0;

对于任何正则表达式特殊字符(#当然),67字节版本将失败。
泰特斯(Titus),

...并且~可能失败chr(207)
泰特斯(Titus),

@Titus完成和输入只能是ASCII字符
约克Hülsermann

好眼神++$n!您的意思是可打印的ascii。;)
泰特斯(Titus

1
echo$r?max($r):0;保存一个字节
Titus

2

JavaScript(ES6),47 40 38字节

(由于@Neil而节省了7个字节,而由于@HermanLauenstein而节省了2个字节。)

s=>g=c=>c&&s.includes(c)?1+g(c+c[0]):0

说明:

递归搜索更长的运行时间,直到没有找到为止。

片段:


1
So simple! Brilliant!
apsillers

Can you not do f=(s,c)=>c&&s.includes(c)&&1+f(s,c+c[0])?
Neil

Or better still, curry it to s=>g=c=>c&&s.includes(c)&&1+g(c+c[0]).
Neil

That almost works, but it returns "false" and a null string for the last two cases. That's fixed by appending ||0, which is still shorter than my solution.
Rick Hitchcock

The f= isn't part of the curried version, because only the inner function is recursive.
Neil

2

Jelly, 10 9 bytes

f⁴L
ŒgÇ€Ṁ

Explanation:

f⁴L
f⁴      -Filter by the character argument.
  L     -Return Length of filtered String.

ŒgÇ€»/
Œg      -Group string by runs of characters.
  ǀ    -Run above function on each group.
    Ṁ   -Return the largest in the list.

Try it online!


You can save a couple of bytes with Œgf€L€Ṁ.
Dennis


1

Haskell, 66 bytes

import Data.List
((maximum.(0:).map length).).(.group).filter.elem

Try it online!

A slightly easier to read version - not pointfree:

f c s = maximum (0:(map length (filter (elem c) (group s))))

Groups the string by letter, then filters by those groups that contain the right character, then finds the lengths, appends 0 to the list of lengths in case it doesn't appear, and finally finds the maximum value.


1

Mathematica, 109 bytes

(s=Differences[First/@StringPosition[#,#2]];k=t=0;Table[If[s[[i]]==1,t++;If[k<t,k=t],t=0],{i,Length@s}];k+1)&


input

["xxx xxxx xx","x"]



1

CJam, 20 19 18 16 bytes

0q~e`f{~@=*}$+W=

Try it online!

Explanation

0                 e# Push 0. We'll need it later.
 q~               e# Read and eval input. Pushes c and s to the stack.
   e`             e# Run-length encode s: turns it into an array of [length, char] pairs.
     f{           e# Map over these pairs using c an extra parameter:
       ~          e#  Dump the pair to the stack.
        @=        e#  Bring c to the top, check equality with the char, pushing 0 or 1.
          *       e#  Multiply the length by the result.
           }      e# (end map)
            $     e# Sort the resulting list in ascending order.
             +    e# Prepend the 0 from before, in case it's empty.
              W=  e# Get the last element.

1

Excel, 56 bytes

{=MAX(IFERROR(FIND(REPT(A2,ROW(A:A)),A1)^0*ROW(A:A),0))}

s should be input to A1.
c should be input to A2.
Formula must be an array formula (Ctrl+Shift+Enter) which adds curly brackets { }.

Technically, this can only handle where the longest run is less than 1,048,576 (which is 2^20) because that's how rows the current Excel will let you have in a worksheet. Since it loads the million+ values into memory whenever it recalculates, this is not a fast formula.


1

MATL, 15 bytes

0i0v=dfd1L)0hX>

Try it online!

The basic algorithm is very simple (no use of split!), but I had to throw in 0i0v and 0h to allow for the edge cases. Still, I thought the approach was nice, and perhaps I can still find another technique to handle the edge cases: the algorithm finds the longest run in the middle of a string just fine, but not for single characters or empty strings; I'm still testing if I can 'pad' the variables at better places for better results.

0i0v % Prepends and appends a zero to the (implicit) input.
   = % Element-wise equality with the desired char (implicit input)
   d % Pairwise difference. Results in a 1 at the start of a run, and -1 at the end.
   f % Get indices of 1's and -1's.
   d % Difference to get length of the runs (as well as length of non-runs)
 1L) % Only select runs, throw out non-runs. We now have an array of all run lengths.
  0h % 'Find' (`f`) returns empty if no run is found, so append a zero to the previous array.
  X> % Maximum value.

Does not work on empty c. Then again, I suppose each string contains an infinite run of empty strings between each character :)


1

R, 66 58 bytes

-8 bytes thanks to BLT and MickyT

function(s,c)max((r=rle(el(strsplit(s,''))))$l*(r$v==c),0)

returns an anonymous function. TIO has a 1-byte difference because el doesn't work there for inexplicable reasons.

Try it online!


Save a byte with r=rle(el(strsplit(s,'')))
BLT

1
Ignore my previous comment if you saw it. Got a better one for you function(s,c)max((r=rle(el(strsplit(s,''))))$l*(r$v==c),0)
MickyT

@BLT el doesn't work on TIO (no idea why) and I just copied and pasted it from the working code there so I'll have to remember to put that back in @MickyT very clever! Thanks!
Giuseppe

1

Java 8, 67 65 bytes

s->c->{int t=0,m=0;for(char x:s)m=m>(t=x==c?t+1:0)?m:t;return m;}

-2 bytes thanks to @OlivierGrégoire

Takes input s as a char[], and c as a char

Explanation:

Try it here.

s->c->{          // Method with char[] and char parameters and int return-type
  int t=0,       //  Temp counter-integer
      m=0;       //  Max integer
  for(char a:s)  //  Loop over the characters of the input
    m=m>(
     t=x==c?     //   If the current character equals the input-character:
      t+1        //    Raise `t` by 1
      :          //   Else:
       0)        //    Reset `t` to 0
    ?m:t;        //   If `t` is now larger than `m`, put `t` as new max into `m`
                 //  End of loop (implicit / single-line body)
  return m;      //  Return the resulting max
}                // End of method

1
m=m>(t=x==c?t+1:0)?m:t; is shorter than {t=x==c?t+1:0;m=m>t?m:t;}.
Olivier Grégoire

Even though it's wayyyyyy longer, I like my first thought: s->c->java.util.Arrays.stream(s.split("[^"+c+"]")).mapToInt(z->z.length()).max().orElse(0) ;)
Olivier Grégoire

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.