Усечение последовательных символов выполняется до длины 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

TestSubject06
источник
1
Почему не разрешить ES6?
TuxCrafting
7
Я бы рекомендовал потерять языковые требования. Javascript - один из самых распространенных языков здесь. Самостоятельно отвечая тем, что вы получили, вероятно, пригласите людей помочь вам в гольф или попытаться обыграть вас другим подходом. Кроме того, если вы наберете достаточно репутации, вы можете добавить награду к вопросу с определенным языком. Если вам это не подходит, вы можете изменить этот вопрос на вопрос с подсказками и попытаться обратиться за конкретной помощью в игре в гольф.
FryAmTheEggman
Убраны языковые ограничения и в результате изменены правила подсчета очков. Я все еще хотел бы видеть записи javascript, но я думаю, что могу жить с некоторыми языками гольфа из 4-5 символов.
TestSubject06
Добро пожаловать в Программирование Пазлов и Code Golf! Задачи Code Golf по умолчанию оцениваются по длине в байтах . Хотя возможна оценка по длине в символах , вы обязательно получите несколько ответов, подобных этому .
Деннис
О Боже. Изменено подсчет байтов.
TestSubject06

Ответы:

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символов напрямую.

XNOR
источник
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.

Это работает, потому что указатель источника всегда будет равен или больше, чем указатель назначения, поэтому мы можем записывать поверх строки при ее разборе.

owacoder
источник
Это удивительно, вы можете это объяснить?
TestSubject06
@ TestSubject06 - Добавлено объяснение.
owacoder
Это работает в случае n = 0? Я не могу заставить его скомпилировать, чтобы проверить здесь.
TestSubject06
Да. Я добавил тестовую программу, чтобы вы могли скомпилировать.
owacoder
Круто, не смог найти контрпримеров. Короче и все работает!
TestSubject06
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"
Dendrobium
источник
f ("a", 1) -> ""
TestSubject06
1
Поскольку ваш RegExp никак не контролируется динамически, вы можете сохранить некоторые байты с помощью RegExp ("(.) \\ 1 *", "g") -> /(.)\1*/g
TestSubject06
1
Конвертировать RegExp("(.)\\1*","g")в/(.)\1*/g
Downgoat
1
Я не вижу, как это уменьшается в JS, если мы не подойдем к этому с совершенно другой точки зрения. Хорошая работа @Dendrobium!
TestSubject06
1
Побрей один байт, изменив (s,n)на s=>n, и использование становитсяf("aaaaaaabbbccCCCcc")(2)
Патрик Робертс
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
Suever
источник
'@@@@@ bbbbbcccddeegffsassss' 3 возвращено '@@@ bbbcccddeegffsass', в котором отсутствуют финальные
буквы
@ TestSubject06 Спасибо за указание на это.
Сувер
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@"
Брэд Гилберт b2gills
источник
0

Javascript ES5, 73

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

Повторно использует регулярное выражение Линн из своего ответа на Python .

FryAmTheEggman
источник
Ваш код не обрабатывает случай, когда n равно нулю, он просто возвращает всю исходную строку.
TestSubject06
Да, в Firefox вы можете удалить фигурные скобки и оператор return , хотя этот синтаксис (к сожалению) устарел и будет удален (фактически он отсутствовал несколько версий назад, не понимая, что они вернули его обратно).
Дендробиум
Вы также можете удалить newключевое слово для -4 байта.
Дендробиум
@ TestSubject06 Спасибо, я отредактировал свой ответ и считаю, что теперь он проходит тестовые случаи.
FryAmTheEggman
0

Perl 5, 50 байт

Код 46 байтов + 3 для -iи 1 для-p

Принимает номер для усечения до -i.

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

использование

perl -i4 -pe 's!(.)\1+!$&=~s/(.{$^I}).+/$1/r!ge' <<< 'aaaaaaabccccccccCCCCCC@'
aaaabccccCCCC@
Дом Гастингс
источник
Почему -pтолько один байт?
Someonewithpc
@someonewithpc, когда он может быть объединен с -eэтими параметрами, потребляет только 1 байт. Если скрипт должен быть запущен из файла, он стоит 3 за место, и он сам помечает. Я постараюсь найти мета-пост, но сейчас я на мобильном.
Дом Гастингс
@someonewithpc meta.codegolf.stackexchange.com/questions/273/…
Дом Гастингс
0

Баш 46 байтов

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

Использование: Введите количество символов для ограничения, нажмите клавишу ввода и введите строку. Ctrl+ Dвыйти sed(отправить EOF).

someonewithpc
источник
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 для конкатенации строк (что на 1 байт больше, чем, String s="";for(int i=-1;++i<j;)s+="$1";к сожалению):

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

Ungolfed и тестовые случаи:

Попробуй это здесь.

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

Объяснение кода: загрузить строку в библиотеку, которая внутренне анализируется как массив символов. Примените аккумулятор к последовательности, передавая пользовательский объект в качестве начального значения. Свойство a является текущим элементом, b является накопленной строкой, а c является последовательным счетчиком текущего элемента. Аккумулятор проверяет, равно ли текущее значение итерации, n, значению последнего элемента, ca. Если нет, мы сбрасываем счетчик до 1 и устанавливаем текущий элемент. Если счетчик текущего элемента меньше или равен требуемой длине, мы накапливаем его в возвращаемой строке. Наконец, мы возвращаем свойство b, накопленную строку. Не самый удачный код, но я счастлив, что получил решение, которое работает ...

введите описание изображения здесь

applejacks01
источник
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

Дьялог АПЛ , 22 20 байт

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

Запрашивает п и принимает входную строку в качестве аргумента.

(молчаливая функция ...
    сплющить
    ⊢↑¨⍨каждый элемент аргумента (т.е. каждого раздел) усекается до
    ⎕⌊⍴¨минимума числового ввода и текущей длиной
)[конец подразумеваемой функции] применяется к
⊢⊂⍨входу секционированного на ᴛʀᴜᴇ х
1, ᴛʀᴜᴇ предваряется ( первый символ не равен его не существующему предшественнику)
2≠/⊢попарно не равны символы на входе

Адам
источник
0

Рубин, 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
brianush1
источник
1
Ни одна из версий вашего ответа не работала с tcc.luaфайлом с отметкой времени 16-07-25 16:57 UTC, который не имел возможности считывать несколько входов одновременно. Если для вашего ответа требуется версия языка, на котором задан вопрос, вы должны пометить его как неконкурентный в заголовке. Я уберу свое понижение, когда ты это сделаешь.
Деннис