截断连续字符到n个长度


14

挑战

给定输入字符串和整数n-将连续字符的所有游程截断为最大n个长度。字符可以是任何字符,包括特殊字符。该函数应区分大小写,并且n的范围可以从0到无穷大。

输入/输出示例:

f("aaaaaaabbbccCCCcc", 2) //"aabbccCCcc" 
f("aaabbbc", 1) //"abc"
f("abcdefg", 0) //""
f("aaaaaaabccccccccCCCCCC@", 4) //"aaaabccccCCCC@"

计分

评分基于使用的字节数。从而

function f(s,n){return s.replace(new RegExp("(.)\\1{"+n+",}","g"),function(x){return x.substr(0, n);});}

将是104分。

打高尔夫球快乐!

编辑:删除语言限制,但我还是很想看看javascript答案


1
为什么不允许ES6?
TuxCrafting '16

7
我建议不要使用语言。Javascript是这里最常用的语言之一。对自己所获得的东西进行自我回答可能会吸引人们帮助您打高尔夫球,或者尝试用另一种方法击败您。此外,如果您获得足够的声誉,则可以在考虑特定语言的情况下为问题添加赏金。如果那不适合您,您可以将此问题修改为提示问题,并尝试寻求特定的高尔夫帮助。
FryAmTheEggman '16

取消了语言限制,并因此更改了评分规则。我仍然希望看到javascript条目,但我想我可以使用4-5个字符的高尔夫语言。
TestSubject06 '16

欢迎来到编程难题和代码高尔夫球!默认情况下,代码高尔夫挑战赛以字节为单位对长度进行评分。虽然得分由长度字符是可能的,你一定会得到这样一些答案这一个
丹尼斯

天啊。更改为字节计分。
TestSubject06

Answers:


6

Python 2,52字节

lambda s,n:reduce(lambda r,c:r+c*(r[-n:]!=c*n),s,'')

写成程序(54字节):

s,n=input();r=''
for c in s:r+=c*(r[-n:]!=c*n)
print r

遍历输入字符串s,将每个字符追加到输出字符串,r除非的最后一个n字符r是该字符。

我虽然失败了,n==0因为r[-0:]不是最后0个字符(空字符串),而是整个字符串。但是,它可以工作,因为字符串保持为空,因此它始终与0字符字符串匹配。

lambda由于重复,递归给出了56

f=lambda s,n:s and s[:f(s[1:],n)[:n]!=s[0]*n]+f(s[1:],n)

另一种防止i重复最后一个字符的策略也比直接检查最后一个n字符的时间更长。


6

C,81 78

修改传入的字符串。

c,a;f(p,n)char*p;{char*s=p;for(;*p;s+=c<n)*s=*p++,a^*s?c=0:++c,a=*s;c=a=*s=0;}

测试程序

需要两个参数,第一个是要截断的字符串,第二个是长度限制。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, const char **argv)
{
    char *input=malloc(strlen(argv[1])+1);
    strcpy(input,argv[1]);
    f(input,atoi(argv[2]));
    printf("%s\n",input);
    free(input);
    return 0;
}

说明:

c,a;                 //declare two global integers, initialized to zero.
                     //c is the run length, a is the previous character
f(char*p,int n){...} //define function f to truncate input
char*s=p;            //copy p to s; p is source, s is destination
for(;*p              //while there is a source character
;s+=c<n)             //increment copied pointer if run is under the limit
*s=*p++,             //copy from source to destination, increment source
a^*s?c=0:++c,        //if previous character != current then run=0 else increment run
a=*s;                //previous character = current source character
c=a=*s=0;            //after loop, terminate destination string with NUL and reset c and a.

之所以可行,是因为源指针将始终等于或大于目标指针,因此我们可以在解析字符串时覆盖它。


这太神奇了,您能解释一下吗?
TestSubject06 '16

@ TestSubject06-添加了说明。
owacoder

这是否适用于n = 0的情况?我无法编译此处进行测试。
TestSubject06 '16

是的,它确实。我添加了一个测试程序,以便可以编译。
owacoder

太好了,找不到任何反例。短而有效!
TestSubject06 '16

5

Haskell,36个字节

import Data.List
(.group).(=<<).take

的无点版本\n s -> concatMap (take n) (group s)


4

JavaScript的ES6,60 54 55 43个字节

-12个字节,感谢@ TestSubject06和@Downgoat

(s,n)=>s.replace(/(.)\1*/g,x=>x.slice(0,n))

示例运行:

f("aaaaaaabbbccCCCcc"      , 2) -> "aabbccCCcc" 
f("aaabbbc"                , 1) -> "abc"
f("abcdefg"                , 0) -> ""
f("aaaaaaabccccccccCCCCCC@", 4) -> "aaaabccccCCCC@"
f("a"                      , 1) -> "a"

f(“ a”,1)->“”
TestSubject06 '16

1
因为你的正则表达式不是动态以任何方式控制,你可以节省一些字节用正则表达式(“()\\ 1 *。”,“G”) - > /(.)\1*/g
TestSubject06

1
转换RegExp("(.)\\1*","g")/(.)\1*/g
Downgoat '16

1
除非我们从完全不同的角度来看,否则我认为这在JS中不会越来越小。干得好@石end兰!
TestSubject06 '16

1
通过更改(s,n)为刮一个字节s=>n,使用方式变为f("aaaaaaabbbccCCCcc")(2)
Patrick Roberts

3

MATL,9个字节

Y'i2$X<Y"

在线尝试

说明

        % Implicitly grab input as a string
Y'      % Perform run-length encoding. Pushes the values and the run-lengths to the stack
i       % Explicitly grab the second input
2$X<    % Compute the minimum of the run lengths and the max run-length
Y"      % Perform run-length decoding with these new run lengths
        % Implicitly display the result

“@@@@@ bbbbbcccddeegffsassss” 3返回“@@@ bbbcccddeegffsass”,其缺少最终的'
TestSubject06

@ TestSubject06感谢您指出这一点。
Suever

2

CJam,12个字节

{e`\af.e<e~}

在线尝试!

说明

e`   e# Run-length encode the input. Gives a list of pair [length character].
\a   e# Swap with maximum and wrap in an array.
f.e< e# For each run, clamp the run-length to the given maximum.
e~   e# Run-length decode.


2

Python 2,56个字节

import re
lambda s,n:re.sub(r'(.)(\1{%d})\1*'%n,r'\2',s)

2

gs2,6个字节

CP437中编码:

╠c╨<ΘΣ

这是一个匿名函数(块),期望在堆栈顶部有一个数字,在堆栈下面有一个字符串。

     Σ   Wrap previous five bytes in a block:
╠          Pop number into register A.
 c         Group string.
    Θ      Map previous two bytes over each group:
  ╨<         Take the first A bytes.

在线尝试。(这里的代码是lines, dump, read number, [the answer], run-block。)


1

Perl 6的 38  36个字节

->$_,$n {S:g/(.)$0**{$n..*}/{$0 x$n}/}
->$_,\n{S:g/(.)$0**{n..*}/{$0 x n}/}

说明:

-> $_, \n { # pointy block lambda
  # regex replace ( return without modifying variant )
  # globally
  S:global /
    # a char
    (.)
    # followed by 「n」 or more identical chars
    $0 ** { n .. * }
  /{
    # repeat char 「n」 times
    $0 x n
  }/
}

测试:

#! /usr/bin/env perl6
use v6.c;
use Test;

my &truncate-char-runs-to = ->$_,\n{S:g/(.)$0**{n..*}/{$0 x n}/}

my @tests = (
  ("aaaaaaabbbccCCCcc", 2) => "aabbccCCcc",
  ("aaabbbc", 1) => "abc",
  ("abcdefg", 0) => "",
  ("aaaaaaabccccccccCCCCCC@", 4) => "aaaabccccCCCC@",
);

plan +@tests;

for @tests -> $_ ( :key(@input), :value($expected) ) {
  is truncate-char-runs-to(|@input), $expected, qq'("@input[0]", @input[1]) => "$expected"';
}
1..4
ok 1 - ("aaaaaaabbbccCCCcc", 2) => "aabbccCCcc"
ok 2 - ("aaabbbc", 1) => "abc"
ok 3 - ("abcdefg", 0) => ""
ok 4 - ("aaaaaaabccccccccCCCCCC@", 4) => "aaaabccccCCCC@"

0

Javascript ES5、73

function f(s,n){return s.replace(RegExp("(.)(\\1{"+n+"})\\1*","g"),"$2")}

从她的Python答案中重新使用Lynn的正则表达式。


您的代码无法处理n为零的情况,它只返回整个原始字符串。
TestSubject06 '16

是的,在Firefox中,您可以删除花括号和return语句,尽管(非常)不推荐使用该语法,并且该语法将被删除(实际上不提供几个版本,但没有意识到它们已将其带回)。
Dendrobium

您也可以将new关键字删除-4个字节。
D

@ TestSubject06谢谢,我已经编辑了答案,我相信它现在可以通过测试用例了。
FryAmTheEggman '16

0

Perl 5,50个字节

46个字节的代码+ 3个 -i和1个用于-p

将数字截断为via -i

s!(.)\1+!$&=~s/(.{$^I}).+/$1/r!ge

用法

perl -i4 -pe 's!(.)\1+!$&=~s/(.{$^I}).+/$1/r!ge' <<< 'aaaaaaabccccccccCCCCCC@'
aaaabccccCCCC@

为什么-p只有一个字节?
有人withpc

@someonewithpc可以与-e这些选项组合时仅消耗1个字节。如果必须从文件运行脚本,则该脚本需要花费3的空间,并且会自行标记。我会尝试找到一个元帖子,但我现在正在移动上。
Dom Hastings


0

重击46个字节

read c;sed -r ":l;s/(.)(\1{$c})(.*)/\2\3/;t l"

用法:输入要限制的字符数,按Enter键并输入字符串。Ctrl+ D退出sed(发送EOF)。


0

Java 7中,107个 106字节

String c(String s,int i){String x="";for(int i=-1;++i<j;)x+="$1";return s.replaceAll("(.)\\1{"+i+",}",x);}

字符串连接的先前替代内联for循环(String s="";for(int i=-1;++i<j;)s+="$1";不幸的是,多1个字节):

String c(String s,int i){return s.replaceAll("(.)\\1{"+i+",}",new String(new char[i]).replace("\0","$1")));}

非高尔夫球和测试用例:

在这里尝试。

class Main {
  static String c(String s, int i){
    String x="";
    for(int j = -1; ++j < i;){
      x += "$1";
    }
    return s.replaceAll("(.)\\1{"+i+",}", x);
  }

  public static void main(String[] a){
    System.out.println(c("aaaaaaabbbccCCCcc", 2));
    System.out.println(c("aaabbbc", 1));
    System.out.println(c("abcdefg", 0));
    System.out.println(c("aaaaaaabccccccccCCCCCC@", 4));
    System.out.println(c("@@@@@bbbbbcccddeegffsassss", 5));
  }
}

输出:

aabbccCCcc
abc

aaaabccccCCCC@
@@@@@bbbbbcccddeegffsassss

0

Javascript(使用外部库)(115字节)

(s,r)=>_.From(s).Aggregate((c,n)=>{if(c.a!=n){c.c=1;c.a=n}else{c.c++}if(c.c<=r){c.b+=n}return c},{a:"",b:"",c:0}).b

链接到lib:https : //github.com/mvegh1/Enumerable

代码说明:将字符串加载到库中,该库在内部解析为char数组。在序列上应用累加器,传入自定义对象作为种子值。属性a是当前元素,b是累积的字符串,c是当前元素的顺序计数。累加器检查当前迭代值n是否等于最后一个元素值ca,如果不相等,我们将计数重置为1并设置当前元素。如果当前元素的计数小于或等于所需的长度,则将其累加到返回字符串中。最后,我们返回属性b,即累积的字符串。不是最复杂的代码,但是很高兴我找到了一个可行的解决方案...

在此处输入图片说明


0

J,31 30字节

((<.#@>)#{.@>@])]<;.1~1,2~:/\]

将输入字符串分组为相同字符的游程(子字符串),并采用该游程长度的最小值和为截断字符串而输入的最大长度。然后多次复制每个运行的第一个字符。

用法

   f =: ((<.#@>)#{.@>@])]<;.1~1,2~:/\]
   2 f 'aaaaaaabbbccCCCcc'
aabbccCCcc
   1 f 'aaabbbc'
abc
   0 f 'abcdefg'

   4 f 'aaaaaaabccccccccCCCCCC@'
aaaabccccCCCC@

说明

((<.#@>)#{.@>@])]<;.1~1,2~:/\]  Input: k on LHS, s on RHS
                             ]  Get s
                        2~:/\   Test if each pair of consecutive chars are not equal
                      1,        Prepend a 1
                ]               Get s
                 <;.1~          Chop s where a 1 occurs to get the runs in s
    #@>                         Get the length of each run
  <.                            Take the min of the length and k
         {.@>@]                 Get the head of each run
        #                       Copy the head of each run min(k, len(run)) times
                                Return that string as the result

0

Dyalog APL22 20 字节

(∊⊢↑¨⍨⎕⌊⍴¨)⊢⊂⍨1,2≠/⊢

提示输入n输入并将输入字符串作为参数。

(默认功能...
    弄平
    ⊢↑¨⍨截断为参数(即,每个分区)中的每个元素
    ⎕⌊⍴¨的最小数值输入的和当前的长度
)[隐性功能的结束]施加到
⊢⊂⍨在所述划分的输入ᴛʀᴜᴇ
1, ᴛʀᴜᴇ预置到(所述第一个字符不等于其不存在的前
2≠/⊢一个字符)输入中字符的成对不相等


0

Ruby,32个字节

->s,n{s.gsub(/(.)\1*/){$&[0,n]}}

-1

TCC,7个 5字节

$~(;)

输入是一个字符串和一个数字,以空格分隔。

在线尝试!

       | Printing is implicit
$~     | Limit occurence
  (;   | First part of input
    )  | Second part of input

1
答案的两个修订版均不适用tcc.lua于时间戳为16-07-25 16:57 UTC 的文件,该文件无法一次读取多个输入。如果您的答案需要挑战后使用的语言版本,则必须在标题中将其标记为“ 非竞争 ”。当您这样做时,我将删除我的弃权票。
丹尼斯
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.