Укорочення послідовного символу працює до 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

7
Я рекомендую втратити вимоги до мови. Javascript - одна з найпоширеніших мов тут. Самостійно відповідаючи на те, що у вас є, напевно, запросите людей допомогти вам у гольф, або спробуйте перемогти вас іншим підходом. Крім того, якщо ви отримаєте достатню репутацію, ви можете додати щедро запитання до конкретної мови. Якщо це не добре відповідає вам, ви можете змінити це питання на питання щодо порад і спробувати попросити конкретну допомогу з гольфу.
FryAmTheEggman

Видалено обмеження мови та в результаті змінили правила балів. Я все ще хотів би бачити записи JavaScript, але, мабуть, я можу жити на якихось 4-5 мовах гольфу.
TestSubject06

Ласкаво просимо до головоломки програмування та коду для гольфу! Проблеми з кодом для гольфу за замовчуванням оцінюються за довжиною в байтах . Хоча підрахунок за довжиною символів можливий, ви зобов'язані отримати відповіді на кшталт цієї .
Денніс

О, Боже. Змінено на байт балів.
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символів безпосередньо.


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

@ 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"

f ("a", 1) -> ""
TestSubject06

1
Оскільки ваш RegExp ні в якому разі не динамічно керується, ви можете зберегти деякі байти за допомогою RegExp ("(.) \\ 1 *", "g") -> /(.)\1*/g
TestSubject06

1
Перетворити RegExp("(.)\\1*","g")на/(.)\1*/g
Пуховик

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

'@@@@ bbbbbcccddeegffsassss' 3 повернувся '@@@ bbbcccddeegffsass', у якому відсутній фінал '
TestSubject06

@ TestSubject06 Дякую, що вказали на це.
Suever




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 .


Ваш код не обробляє випадок, коли 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лише один байт?
whowithpc

@someonewithpc, коли його можна комбінувати з -eцими параметрами, споживає лише 1 байт. Якщо сценарій потрібно запустити з файлу, він коштує 3 місця, і він позначить сам прапор. Існує мета-повідомлення, яку я спробую знайти, але зараз я на мобільному телефоні.
Дом Гастінгс


0

Bash 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);}

Попередня альтернативна вбудована цикл для об'єднання рядків (що на 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")));}

Невикористані та тестові справи:

Спробуйте тут.

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/Eumerable

Пояснення коду: Завантажте рядок у бібліотеку, яка внутрішньо аналізує масив char. Застосуйте акумулятор до послідовності, передаючи в користувальницький об'єкт як значення насіння. Властивість a - поточний елемент, b - накопичена рядок, а c - послідовний відлік поточного елемента. Акумулятор перевіряє, чи поточне значення ітерації, n, дорівнює останньому значенню елемента, ca Якщо ні, ми скидаємо кількість до 1 і встановлюємо поточний елемент. Якщо кількість поточного елемента менша або дорівнює потрібній довжині, ми накопичуємо його до зворотного рядка. Нарешті, повертаємо властивість b, накопичену рядок. Не найголовніший код, але щасливий, що я отримав рішення, яке працює ...

enter image description here


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

Діалог APL , 22 20 байт

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

Запрошує n та приймає рядок введення як аргумент.

(мовчазна функція ...
    вирівняйте
    ⊢↑¨⍨кожен елемент аргументу (тобто кожен розділ), урізаний до
    ⎕⌊⍴¨мінімуму числового вводу, а поточна довжина
)[кінець негласної функції], застосована до
⊢⊂⍨входу, розділеного на of s
1, pe, попередньо до ( Перший символ не дорівнює його неіснуючому попереднику)
2≠/⊢пара нерівних символів вхідних даних



-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, який не мав можливості читати відразу декілька входів. Якщо у вашій відповіді потрібна версія мови, яка подає виклик, ви повинні позначити її як не конкуруючу у заголовку. Я зніму свій потік, коли ви це зробите.
Денніс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.