Розмальовуйте рядок


39

Дуже багато мов мають вбудовані способи позбутися від дублікатів або "подвоїти" або "уніфікувати" список або рядок. Менш розповсюдженим завданням є "знешкодження" рядка. Тобто для кожного персонажа, який з’являється, зберігаються перші два події.

Ось приклад, де символи, які слід видалити, позначені ^:

aaabcbccdbabdcd
  ^    ^ ^^^ ^^
aabcbcdd

Ваше завдання - реалізувати саме цю операцію.

Правила

Введення - це один, можливо, порожній рядок. Ви можете припустити, що він містить лише малі літери в діапазоні ASCII.

Вихід повинен бути єдиним рядком із усіма видаленими символами, які вже з’являються щонайменше двічі в рядку (таким чином, зберігаються найбільш два лівих випадки).

Замість рядків ви можете працювати зі списками символів (або однорядними рядками), але формат повинен відповідати вводу та виводу.

Ви можете написати програму чи функцію та скористатися будь-яким із наших стандартних методів отримання вводу та надання виводу.

Ви можете використовувати будь-яку мову програмування , але зауважте, що ці лазівки за замовчуванням заборонені.

Це , тому найкоротший вірний відповідь - вимірюється в байтах - виграє.

Випробування

Кожна пара рядків - це один тестовий випадок, введення з подальшим результатом.



xxxxx
xx
abcabc
abcabc
abcdabcaba
abcdabc
abacbadcba
abacbdc
aaabcbccdbabdcd
aabcbcdd

Таблиця лідерів

Фрагмент стека внизу цієї публікації генерує таблицю лідерів з відповідей а) як список найкоротших варіантів для кожної мови та б) як загальну таблицю лідерів.

Щоб переконатися, що ваша відповідь відображається, будь ласка, почніть свою відповідь із заголовка, використовуючи наступний шаблон Markdown:

## Language Name, N bytes

де Nрозмір вашого подання. Якщо ви покращите свій рахунок, ви можете зберегти старі бали у заголовку, прокресливши їх. Наприклад:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Якщо ви хочете включити у свій заголовок декілька чисел (наприклад, тому що ваш результат становить суму двох файлів або ви хочете окремо вказати штрафні санкції для перекладача), переконайтесь, що фактичний результат - це останнє число у заголовку:

## Perl, 43 + 3 (-p flag) = 45 bytes

Ви також можете зробити ім'я мови посиланням, яке з’явиться у фрагменті:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


5
Струни синглів ... стрингтони?
dkudriavtsev

Відповіді:



15

JavaScript (ES6), 42 48

Редагуйте колосальні 6 байт, збережених thx @Neil

s=>s.replace(k=/./g,c=>(k[c]+=c)[11]?'':c)

Пояснення: Я використовую властивості 'a' ... 'z' об'єкта kдля зберігання інформації для кожного символу (об'єкт k - це регулярне вираження в цьому випадку лише для збереження байтів). Ці властивості є спочатку undefined. У javascript додається число до undefineddaje NaN(досить розумне), але додавання рядка 'X' дає "undefinedX"- рядок довжиною 10 (нерозумно). Додавши більше символів, ви отримаєте довші рядки. Якщо отриманий рядок для даного символу довший 11, цей символ не копіюється на вихід.

Тест

F=
s=>s.replace(k=/./g,c=>(k[c]+=c)[11]?'':c)

test=`

xxxxx
xx
abcabc
abcabc
abcdabcaba
abcdabc
abacbadcba
abacbdc
aaabcbccdbabdcd
aabcbcdd`.split`\n`
for(i=0;i<test.length;)
  a=test[i++],b=test[i++],r=F(a),
  console.log(r==b?'OK':'KO',a,'->',r,b)


Суворо кажучи, порожній рядок є одним із тестових випадків.
Ніл

@Neil ok додав тест порожнього рядка
edc65

Якщо ви перейдете на вхід та вихід масиву, ви можете використовувати .filter, щоб зберегти ще 12 символів. v=>v.filter(x=>!(v[x]+=x)[11]). Кудо на "невизначеному" хаку.
Grax32

@Grax ніж, але занадто різний. Слід опублікувати його самостійно
edc65

14

Python 2, 48 байт

lambda s:reduce(lambda r,c:r+c*(r.count(c)<2),s)

c[r.count(c)/2:]є альтернативою такої ж довжини c*(r.count(c)<2).


49 байт:

r=''
for c in input():r+=c*(r.count(c)<2)
print r

12

Сітківка , 17 байт

(.)(?<=\1.*\1.+)

Спробуйте в Інтернеті!

Проста заміна регулярного виразу - відповідність символу, якщо він вже з’явився двічі, та видаліть його.


Я також спробував цикл і повторну групу{2} , обидва з 18 байтами.
Кобі

1
У мене 14 з використанням нещодавно доданої функції. ;)
Мартін Ендер

Я знав, що щось є. Я дивився межі, напевно, не той. Я ще раз перевірю.
Кобі

3
А, я думаю, я знайшов відповідь Мартіна. У мене були проблеми, коли я намагався раніше, я думаю, тому що я не розглядав, як дублікат буде працювати на багаторядковому вході. Спойлер (з 5 байтами додано для включення режиму в рядку): retina.tryitonline.net/…
FryAmTheEggman

@FryAmTheEggman - Добре, я цього не знайшов. Не соромтеся додати відповідь - я думаю, що це занадто відрізняється від моєї відповіді, і мені не було зручно редагувати її :P. Спасибі!
Кобі

6

Брахілог , 25 байт

.v|s.g:.z:1a
:2fl<3
he~t?

Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Пояснення

Це працює, тому що s - Subsetспочатку об'єднається з більшими підмножинами, наприклад, для "aaa"цього спробуй "aa"раніше "a".

  • Основний предикат:

      .v         input = Output = ""
    |          Or
      s.         Output is an ordered subset of the input
      g:.z       Zip each character of the output with the output itself
      :1a        Apply predicate 1 on each element of the zip
    
  • Присудок 1: Перевірте, чи всі символи відображаються максимум двічі. Вхід =[String:Char]

    :2f        Find all valid outputs of predicate 2 (i.e. one output per occurence
                   of the char)
    l<3        There are less than 3 occurences
    
  • Присудок 2: Отримати виникнення символу. Вхід =[String:Char]

    he         Take a character of the string in the input
      ~t?      That character is the char of the input
    

6

> <> , 22 байти

i:0(?;::9g:}2(?o{1+$9p

Спробуйте в Інтернеті! Використовує кодову коду для відстеження підрахунків досі.

i                       Read a char c of input
 :0(?;                  Halt if EOF
      :                 Make a copy - stack has [c c] at the top
       :9g              Get count stored at (c, 9)
          :}            Copy the count and move to bottom of stack
            2(?o        If the count is less than 2, output c
                {1+     Move the count back to the top of the stack and increment
                   $9p  Update cell at (c, 9)
                        [Instruction pointer moves to start as ><> is toroidal]

6

J, 20 15 байт

#~(3>[+/@:={:)\

Це визначає монадічну функцію, яка бере і повертає рядок. Спробуйте тут . Використання:

   f =: #~(3>[+/@:={:)\
   f 'abaacbb'
abacb

Пояснення

Я перейшов на той самий алгоритм, який використовують деякі інші рішення, оскільки він виявився коротшим ...

#~(3>[+/@:={:)\  Input is y.
  (          )\  For each prefix of y:
          =        compute the equality vector
     [     {:      of the prefix and its last element, and
      +/@:         take its sum. Now we have a vector r such that y[i] has its
                   r[i]'th occurrence at position i.
   3>              Mark those coordinates where r[i] < 3.
#~               Remove the non-marked characters from y.

6

Haskell, 40 39 байт

foldl(\s c->s++[c|filter(==c)s<=[c]])""

Приклад використання: foldl(\s c->s++[c|filter(==c)s<=[c]])"" "aaabcbccdbabdcd"-> "aabcbcdd".

Збережіть наступний знак, cякщо рядок усіх cs поки що є лексикографічними меншими або рівними одиночним рядком [c].

Редагувати: @xnor зберег байт, перейшовши зі розуміння списку на filter. Спасибі!


Ваша альтернатива може зробити, filter(==c)s<=[c]щоб зберегти байт.
xnor

5

Perl, 22 байти

21 байт код + 1 для -p.

s/./$&x(2>${$&}++)/ge

Використання

perl -pe 's/./$&x(2>${$&}++)/ge' <<< 'aaabcbccdbabdcd'
aabcbcdd

5

C, 57 байт

Зателефонуйте f()за допомогою рядка, щоб демпліфікувати. Функція змінює свій параметр. Потрібен C99 через forдекларацію -loop.

f(char*p){for(char*s=p,m[256]={0};*s=*p;s+=++m[*p++]<3);}

Ви не можете помістити декларацію sв першу заяву for?
Мартін Ендер

У С99 можна. Я просто цього не зробив, тому що мені подобається зберігати гольфи C89 сумісними.
owacoder

5

JavaScript (ES6), 35 байт

s=>s.filter(c=>(s[c]=(s[c]|0)+1)<3)

Бере масив символів як вхідний і повертає детрильований масив.


Приємно. Ви можете зробити, c=>(s[c]=-~s[c])<3щоб зберегти кілька байт.
ETHproductions

Я пропустив, що ви можете використовувати масиви як вхідні дані і написав функцію, використовуючи map. У гольф це виглядало по суті як ваше. головна відмінність полягала в призначенні, яке, якщо ви переключите його, заощадить кілька байт. Спробуйте s.filter(c=>(s[c]=s[c]+1|0)<3)33 байти. EDIT: Уопс, пропустив коментар над мною, це ще краще :)
січня

4

PowerShell v2 +, 31 байт

$args-replace'(.)(?<=\1.*\1.+)'

Використовується той же регулярний вираз, що і у відповіді Retina Кобі , просто інкапсульований в -replaceоператорі PowerShell . Працює, тому що обидва використовують .NET-ароматичний вираз у фоновому режимі.

Як варіант, без регулярного вираження, 56 байт

$b=,0*200;-join([char[]]$args[0]|%{"$_"*($b[$_]++-lt2)})

Створює довідковий масив, $bпопередньо заповнений 0s. Віддає вхідний рядок $args[0]як- charмасив, передає його через цикл |%{...}. Кожна ітерація виводить поточний символ $_у вигляді рядка, "$_"помноженого на булеву форму, яка є лише $TRUE(неявно приведена 1сюди), якщо відповідна точка в масиві помічників менша 2(тобто ми не бачили цього символу двічі). Отримана колекція рядків інкапсульована в паренах і -joinразом зведена, щоб утворити єдиний вихідний рядок. Це залишилося на конвеєрі, і вихід неявний.


регекс неперевершений. :) Я beleave хеш - таблиця краще тоді масив для варіанту без регулярного виразу: $b=@{};-join($args|% t*y|?{++$b.$_-lt3}).
маззи

1
@mazzy Щодо варіанту без регулярного виразу та вашого коду, йому знадобиться бути більш новою версією, ніж PowerShell 2. В результаті я думаю, що цю відповідь я зберігатиму без змін. Ви можете опублікувати свій код як окрему відповідь!
AdmBorkBork

з'явився хештел у версії 3.0? Добре. Спасибі.
маззи

4

Математика, 39 байт

Fold[If[Count@##<2,Append@##,#]&,{},#]&

Анонімна функція. Візьме список символів як вхідний і поверне детрильований список як вихід. Використовує метод складання списку та відхилення трійкових елементів, це не надто складно.



4

MATL , 8 байт

t&=Rs3<)

Спробуйте в Інтернеті!

Пояснення

t      % Input string implicitly. Push another copy
&=     % Matrix of all pairwise equality comparisons of string elements
R      % Keep only upper triangular part, making the rest of the entries zero
s      % Sum of each column. This gives a vector with number of occurrences
       % of the current character up to the current position
3<     % True for entries that are less than 3
)      % Use as logical index into initial copy of the input. Display implicitly

Приклад

Припускаючи введення 'aaababbc', стек містить наступні після зазначених тверджень:

  • t

    'aaababbc'
    'aaababbc'
    
  • t&=

    'aaababbc'
    [ 1 1 1 0 1 0 0 0;
      1 1 1 0 1 0 0 0;
      1 1 1 0 1 0 0 0;
      0 0 0 1 0 1 1 0;
      1 1 1 0 1 0 0 0;
      0 0 0 1 0 1 1 0;
      0 0 0 1 0 1 1 0;
      0 0 0 0 0 0 0 1 ]
    
  • t&=R

    'aaababbc'
    [ 1 1 1 0 1 0 0 0;
      0 1 1 0 1 0 0 0;
      0 0 1 0 1 0 0 0;
      0 0 0 1 0 1 1 0;
      0 0 0 0 1 0 0 0;
      0 0 0 0 0 1 1 0;
      0 0 0 0 0 0 1 0;
      0 0 0 0 0 0 0 1 ]
    
  • t&=Rs

    'aaababbc'
    [ 1 2 3 1 4 2 3 1 ]
    
  • t&=Rs3<

    'aaababbc'
    [ true true false true false true false true ]
    
  • t&=Rs3<)

    'aabbc'
    

4

Сітківка , 14 байт

D`(.)(?<=\1.*)

Перевірте всі тестові випадки. ( %Увімкнений режим в рядку)

Використовує новий етап "Повторне копіювання", щоб заощадити пару байт за підхід Кобі . Deduplicate збирає список всіх збігів у регулярний вираз і замінює всі, крім перших, порожнім рядком. Режекс відповідає символу, який вже з’являється один раз у рядку, тобто перші два будуть збережені.



3

К, 18 байт

  g:{x{?x@<x}@,/2#'=x}
  g "abc"
"abc"
  g "aaabcbccdbabdcd"
"aabcbcdd"

  /k4 request test vectors from internet
  R:"GET /raw/ftHe0bpE HTTP/1.0\r\nHost: pastebin.com\r\n\r\n"
  t:+0N 2#t@1_&|\(0=#:)'t:1_"\r\n"\:`:http://pastebin.com:80 R 

  /k4 no internet? use a file called "t.txt" in current directory
  t:+0N 2#0:`:t.txt

  /k6?
  t:+0N 2#0:"t.txt"

  /visually inspect test cases
  g't[0]
(();"xx";"abcabc";"abcdabc";"abacbdc";"aabcbcdd")

  /do all tests pass?
  |/ t[1] {$[0=#x;0=#y;x~y]}' g't[0]
1b

K4 доступний для безкоштовного завантаження ; K6 знаходиться в стадії розробки . Якщо ви завантажили KDB, ви можете потрапити в K із зворотною косою рисою .

Це може бути найпростіше бачити цей розбитий, але спочатку якийсь синтаксис: g:xвстановлюється gв x. {x+1}це функція, яка приймає аргумент x . У K перший аргумент функції є x(другий -y а третій z. Четвертий не потребує).

Зараз:

x:"aaabcbccdbabdcd"

=xозначає групу x , яка виробляє:

"abcd"!(0 1 2 10;3 5 9 11;4 6 7 13;8 12 14)

2#'означає два взяті (з) кожен, що виробляє

"abcd"!(0 1;3 5;4 6;8 12)

Як бачите, це компенсації перших двох матчів кожного персонажа. 2 може бути узагальнено.

,/означає приєднатись до кожного і його часто називають різе . Це отримає нам лише значення нашого словника. Таким чином, ,/"abcd"!(0 1;3 5;4 6;8 12)виробляє:

0 1 3 5 4 6 8 12

які нам потрібно сортувати. {x@<x}@- це ідіома K, яку часто бачать програмісти (Q називає це висхідним ), який говорить x при оцінці x . Розбивши його:

  <0 1 3 5 4 6 8 12
0 1 2 4 3 5 6 7

повернув індекси відсортованого масиву, який ми хочемо взяти з вихідного масиву. x@yозначає x at y, тому це індексує масив з індексами роду (якщо це має сенс).

  {x@<x}@0 1 3 5 4 6 8 12
0 1 3 4 5 6 8 12

який ми просто зараз індексуємо у свій початковий масив. Ми можемо сказати x@тут, але K підтримує дійсно потужну концепцію, якою ми можемо скористатися тут: застосування функції - це індексація. Це означає, що a[0]можна шукати нульовий слот aабо це може застосовувати 0функцію, яку називають a. Причина, яка нам потрібна була @раніше, {x@<x}полягає в тому, що x<yозначає xs менше ys : Оператори в K мають діадичну форму (два аргументи) і монадичну форму (один аргумент), що походить від APL. Q не має цієї "амбівалентності".


Ласкаво просимо до PPCG! Чудова перша відповідь. :)
Мартін Ендер

У мене є пара питань. 1. Чи K4 є тією ж мовою, що і та, з якою ви посилаєтесь (Q / kdb +)? 2. Чи можете ви показати, як викликати свою функцію на вході або як слід форматувати елементи в testVectors.txt?
Денніс

@Dennis 1. Так. Натисніть зворотну косу рису, щоб перейти від Q до K. 2. Так само, як вони з’являються у запитанні: pastebin.com/ftHe0bpE Приклад виклику:g"aaabcbccdbabdcd"
геокар

Добре, дякую. Не вдалося працювати з файловою частиною, але g"..."це робить фокус. На жаль, ваш код повертається aabbccдля введення abc.
Денніс

@Dennis Можливо, ти зробив щось не так: {x{?x@<x}@,/2#'=x}"abc"обов'язково повертається "abc". Він повернеться, "aabbcc"якщо ви пропустите ?різницю.
геокар


2

Java 8 лямбда, 90 символів

i->{int[]o=new int[128];String r="";for(char c:i.toCharArray())if(++o[c]<3)r+=c;return r;}

Негольована версія:

public class Q86503 {

    static String detriplicate(String input) {
        int[] occurences = new int[128];
        String result = "";
        for (char c : input.toCharArray()) {
            if (++occurences[c] < 3) {
                result += c;
            }
        }
        return result;
    }
}

Створює масив для всіх символів ascii. Якщо символ трапляється, відповідний лічильник буде збільшений. Якщо вона перевищує 2, символ не буде доданий до рядка результатів. Дуже легко, дуже коротко;)


2

Perl 6, 27 байт

{.comb.grep({++%.{$_} <3})}

Пояснення:

{.comb.grep({++%.{$_} <3})}
{                         } # a function
 .comb                      # get all the characters in the argument
      .grep({           })  # filter
               %.           # an anonymous hash (shared between calls to grep)
             ++  {$_}       # increment the value at the current key (current letter).
                            # if the key doesn't exist, it defaults to 0 (then gets incremented)
                      <3    # return True if it wasn't seen 3 times

(Примітка: Perl 6 не такий «орієнтований на гольф», як його сестра Perl 5 ... Тож так, це місце перед <необхідним. %.{}Анонімний хеш).



2

SmileBASIC, 77 72 69 68 байт

DIM R[#Y]READ S$WHILE""<S$Q=ASC(S$)INC R[Q]?SHIFT(S$)*(R[Q]<3);
WEND

Пояснили:

DIM R[128] 'array to store letter frequencies
READ S$ 'get input string
WHILE""<S$ 'much shorter than LEN(S$)
 Q=ASC(S$) 'get ascii value of first character in S$
 INC R[Q]
 ?SHIFT(S$)*(R[Q]<3); 'remove the first character of S$, and print it if there are less than 3 occurrences.
WEND

Ласкаво просимо в ppcg! Гарний перший пост!
Rɪᴋᴇʀ

1

Загальна Лісп, 127

(lambda(s)(map()(lambda(x)(flet((p(b)(1+(position x s :start b))))(setf s(remove x s :start(p(p 0))))))(remove-duplicates s))s)

Досить друковані

(lambda (s)
  (map nil
       (lambda (x)
         (flet ((p (b)
                  (1+ (position x s :start b))))
           (setf s (remove x s :start (p (p 0))))))
       (remove-duplicates s))
  s)

1

Q , 52 байти

q)f2:{x asc raze{distinct 2#where x}each x~'/:distinct x}
q)f2 each testList
"xx"
"abcabc"
"abcdabc"
"abacbdc"
"aabcbcdd"
q)

1

К , 27 байт

    f:{x{x@<x}@,/{?2#&x}'x~'/:?x}
    testList:("xxxxx";"abcabc";"abcdabcaba";"abacbadcba";"aaabcbccdbabdcd")
    f'testList
("xx";"abcabc";"abcdabc";"abacbdc";"aabcbcdd")

1

Рубі , 79 62 57 байт

Це досить непростим, але я не впевнений, що в даний час я можу гольф набагато краще. Будь-які пропозиції щодо гольфу вітаються. Спробуйте в Інтернеті!

Редагувати: -17 байтів завдяки Value Ink, запропонувавши гольфістору спосіб видалення трійкових символів. -5 байт від видалення .uniqметоду.

->s{s.chars.map{|a|s[s.rindex a]=""while s.count(a)>2};s}

Безголовки:

def g(s)
 s.chars.each do |a|
  while s.count(a) > 2
   i = s.rindex(a)
   s[i] = ""
  end
 end
 return s
end

62 байти:->s{s.chars.uniq.map{|a|s[s.rindex a]=""while s.count(a)>2};s}
Значення чорнила

1

JavaScript, 30 байт

v=>v.filter(x=>!(v[x]+=x)[11])

Використовуючи метод, який @ edc65 придумав для підрахунку, але з фільтром масиву. Перший час з'являється символ, значення об'єкта отримує "невизначене" плюс символ (тобто "undefinedx"). Наступного разу значення об'єкта стає "undefinedxx".

Після цього v [x] [11] повертає істину, і в поєднанні з не оператором, помилкові знакові символи, які вже з’явилися двічі, будуть відфільтровані.


0

Javascript (за допомогою зовнішньої бібліотеки) (80 байт)

Це було добре! Не виграв, але було весело

n=>{a={};return _.From(n).Where(x=>{b=a[x]?a[x]++:a[x]=1;return b<2}).Write("")}

Посилання на lib: https://github.com/mvegh1/Enumerable/

Пояснення коду: Метод приймає рядок, бібліотека аналізує його як масив char, а пункт Where - складний предикат фільтрації, який перевіряє хешмап 'a' на наявність поточного char. Якщо існує, лічильник приросту, інше встановлено на 1. Якщо <2, предикат (та поточний знак) проходить, інакше не виходить

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


Ви можете уникнути з допомогою returnале зробити ваші функції , розділених комами список з виразів в дужках: n=>(a={},_From(n)....). Останній вираз - повернене значення. У вашій Whereфункції, ви можете усунути проміжний bповністю шляхом порівняння з результатом завдання або приросту: x=>(a[x]?a[x]++:a[x]=1)<2.
апспіллери

Нарешті, ви можете не використовувати зовнішню бібліотеку на всіх (і зберегти байти) , використовуючи рядок-спліт крапки і filterз join: [...n].filter(...).join(""). Перемістіть справжню / хибну логіку при зміні Whereна filter.
апспіллери

Ах гарні спостереження! Пізніше ознайомтеся з вашою пропозицією
applejacks01

0

Clojure, 72 байти

#(apply str(reduce(fn[r c](if(<(count(filter #{c}r))2)(conj r c)r))[]%))

Стільки байтів ...


0

Паскаль (FPC) , 103 байти

var a:array['a'..'z']of word;c:char;begin repeat read(c);inc(a[c]);if a[c]<3then write(c)until eof end.

Спробуйте в Інтернеті!

Пояснення:

var a:array['a'..'z']of word; //used for counting occurences of characters in the input
                              //array indices are accessed by chars
    c:char;
begin
  repeat
    read(c);                  //read a character from input
    inc(a[c]);                //increment the count of that character (its number in array)
    if a[c]<3 then write(c)   //if this is character's 1st or 2nd occurence, output it
  until eof                   //go back to reading if input is not read completely
end.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.