Wiele języków ma wbudowane sposoby na pozbycie się duplikatów, „deduplikowania” lub „unikatowania” listy lub łańcucha. Mniej powszechnym zadaniem jest „detriplikowanie” łańcucha. Oznacza to, że dla każdej pojawiającej się postaci są zachowywane dwa pierwsze wystąpienia.
Oto przykład, w którym znaki, które należy usunąć, są oznaczone ^
:
aaabcbccdbabdcd
^ ^ ^^^ ^^
aabcbcdd
Twoim zadaniem jest wdrożenie dokładnie tej operacji.
Zasady
Dane wejściowe to pojedynczy, być może pusty ciąg. Możesz założyć, że zawiera tylko małe litery w zakresie ASCII.
Wyjście powinno być pojedynczym ciągiem ze wszystkimi usuniętymi znakami, które już pojawiły się co najmniej dwa razy w ciągu (więc zachowane są dwa najbardziej lewe wystąpienia).
Zamiast ciągów możesz pracować z listami znaków (lub ciągami singletonowymi), ale format musi być spójny między wejściem a wyjściem.
Możesz napisać program lub funkcję i użyć dowolnej z naszych standardowych metod otrzymywania danych wejściowych i dostarczania danych wyjściowych.
Możesz używać dowolnego języka programowania , ale pamiętaj, że te luki są domyślnie zabronione.
To jest golf golfowy , więc wygrywa najkrótsza ważna odpowiedź - mierzona w bajtach .
Przypadki testowe
Każda para linii to jeden przypadek testowy, dane wejściowe i dane wyjściowe.
xxxxx
xx
abcabc
abcabc
abcdabcaba
abcdabc
abacbadcba
abacbdc
aaabcbccdbabdcd
aabcbcdd
Tabela liderów
Fragment kodu na dole tego postu generuje tabelę wyników z odpowiedzi a) jako listę najkrótszych rozwiązań dla każdego języka oraz b) jako ogólną tabelę wyników.
Aby upewnić się, że twoja odpowiedź się pojawi, zacznij od nagłówka, korzystając z następującego szablonu Markdown:
## Language Name, N bytes
gdzie N
jest rozmiar twojego zgłoszenia. Jeśli poprawić swój wynik, to może zachować stare porachunki w nagłówku, uderzając je przez. Na przykład:
## Ruby, <s>104</s> <s>101</s> 96 bytes
Jeśli chcesz umieścić w nagłówku wiele liczb (np. Ponieważ twój wynik jest sumą dwóch plików lub chcesz osobno wymienić kary za flagi tłumacza), upewnij się, że rzeczywisty wynik jest ostatnią liczbą w nagłówku:
## Perl, 43 + 3 (-p flag) = 45 bytes
Możesz także ustawić nazwę języka jako link, który pojawi się we fragmencie:
## [><>](http://esolangs.org/wiki/Fish), 121 bytes
<style>body { text-align: left !important} #answer-list { padding: 10px; width: 290px; float: left; } #language-list { padding: 10px; width: 290px; float: left; } table thead { font-weight: bold; } table td { padding: 5px; }</style><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="language-list"> <h2>Shortest Solution by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr> </thead> <tbody id="languages"> </tbody> </table> </div> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr> </thead> <tbody id="answers"> </tbody> </table> </div> <table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table><script>var QUESTION_ID = 86503; var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe"; var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk"; var OVERRIDE_USER = 8478; var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page; function answersUrl(index) { return "https://api.stackexchange.com/2.2/questions/" + QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER; } function commentUrl(index, answers) { return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER; } function getAnswers() { jQuery.ajax({ url: answersUrl(answer_page++), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { answers.push.apply(answers, data.items); answers_hash = []; answer_ids = []; data.items.forEach(function(a) { a.comments = []; var id = +a.share_link.match(/\d+/); answer_ids.push(id); answers_hash[id] = a; }); if (!data.has_more) more_answers = false; comment_page = 1; getComments(); } }); } function getComments() { jQuery.ajax({ url: commentUrl(comment_page++, answer_ids), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { data.items.forEach(function(c) { if (c.owner.user_id === OVERRIDE_USER) answers_hash[c.post_id].comments.push(c); }); if (data.has_more) getComments(); else if (more_answers) getAnswers(); else process(); } }); } getAnswers(); var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/; var OVERRIDE_REG = /^Override\s*header:\s*/i; function getAuthorName(a) { return a.owner.display_name; } function process() { var valid = []; answers.forEach(function(a) { var body = a.body; a.comments.forEach(function(c) { if(OVERRIDE_REG.test(c.body)) body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>'; }); var match = body.match(SCORE_REG); if (match) valid.push({ user: getAuthorName(a), size: +match[2], language: match[1], link: a.share_link, }); else console.log(body); }); valid.sort(function (a, b) { var aB = a.size, bB = b.size; return aB - bB }); var languages = {}; var place = 1; var lastSize = null; var lastPlace = 1; valid.forEach(function (a) { if (a.size != lastSize) lastPlace = place; lastSize = a.size; ++place; var answer = jQuery("#answer-template").html(); answer = answer.replace("{{PLACE}}", lastPlace + ".") .replace("{{NAME}}", a.user) .replace("{{LANGUAGE}}", a.language) .replace("{{SIZE}}", a.size) .replace("{{LINK}}", a.link); answer = jQuery(answer); jQuery("#answers").append(answer); var lang = a.language; lang = jQuery('<a>'+lang+'</a>').text(); languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang.toLowerCase(), user: a.user, size: a.size, link: a.link}; }); var langs = []; for (var lang in languages) if (languages.hasOwnProperty(lang)) langs.push(languages[lang]); langs.sort(function (a, b) { if (a.lang_raw > b.lang_raw) return 1; if (a.lang_raw < b.lang_raw) return -1; return 0; }); for (var i = 0; i < langs.length; ++i) { var language = jQuery("#language-template").html(); var lang = langs[i]; language = language.replace("{{LANGUAGE}}", lang.lang) .replace("{{NAME}}", lang.user) .replace("{{SIZE}}", lang.size) .replace("{{LINK}}", lang.link); language = jQuery(language); jQuery("#languages").append(language); } }</script>
Odpowiedzi:
Galaretka , 6 bajtów
Wypróbuj online! lub zweryfikuj wszystkie przypadki testowe .
Jak to działa
źródło
JavaScript (ES6), 42
48Edytuj Ogromne 6 bajtów zaoszczędzonych dzięki @Neil
Objaśnienie: Używam właściwości „a” ... z z obiektu
k
do przechowywania informacji dla każdego znaku (w tym przypadku obiekt k jest wyrażeniem regularnym tylko w celu zapisania bajtów). Te właściwości są początkowoundefined
. W javascript dodanie liczby doundefined
dajeNaN
(całkiem rozsądne), ale dodanie ciągu „X” daje"undefinedX"
- ciąg długości 10 (głupie). Dodając więcej znaków, otrzymujesz dłuższe ciągi. Jeśli uzyskany ciąg dla danego znaku jest dłuższy niż 11, znak ten nie jest kopiowany do wyniku.Test
źródło
v=>v.filter(x=>!(v[x]+=x)[11])
. Wyrazy uznania za „nieokreślony” hack.Python 2, 48 bajtów
c[r.count(c)/2:]
jest alternatywą dla tej samej długościc*(r.count(c)<2)
.49 bajtów:
źródło
Siatkówka , 17 bajtów
Wypróbuj online!
Prosta zamiana wyrażeń regularnych - dopasuj znak, jeśli pojawił się już dwukrotnie, i usuń go.
źródło
{2}
, obie z 18 bajtami.:P
. Dzięki!Brachylog , 25 bajtów
Wypróbuj online! lub zweryfikuj wszystkie przypadki testowe .
Wyjaśnienie
Działa to, ponieważ
s - Subset
najpierw ujednolici się z większymi podzbiorami, dlatego np"aaa"
. Spróbuje"aa"
wcześniej"a"
.Główny predykat:
Predykat 1: Sprawdź, czy wszystkie postacie pojawiają się maksymalnie dwa razy. Dane wejściowe =
[String:Char]
Predicate 2: Uzyskaj wystąpienie postaci. Dane wejściowe =
[String:Char]
źródło
> <> , 22 bajty
Wypróbuj online! Używa codbox do śledzenia do tej pory liczby.
źródło
J,
2015 bajtówDefiniuje funkcję monadyczną, która przyjmuje i zwraca ciąg znaków. Wypróbuj tutaj . Stosowanie:
Wyjaśnienie
Przełączyłem się na ten sam algorytm, którego używają niektóre inne rozwiązania, ponieważ okazał się on krótszy ...
źródło
Haskell,
4039 bajtówPrzykład użycia:
foldl(\s c->s++[c|filter(==c)s<=[c]])"" "aaabcbccdbabdcd"
->"aabcbcdd"
.Zachowaj następny znak,
c
jeśli ciąg wszystkichc
jak dotąd jest leksykograficzny mniejszy lub równy ciągowi singletonu[c]
.Edycja: @xnor zapisał bajt, przełączając się ze zrozumienia listy na
filter
. Dzięki!źródło
filter(==c)s<=[c]
być uratowanie bajtu.Perl, 22 bajty
Kod 21 bajtów + 1 dla
-p
.Stosowanie
źródło
C, 57 bajtów
Zadzwoń
f()
ze sznurkiem, aby się dowiedzieć. Funkcja modyfikuje swój parametr. Wymaga C99 z powodufor
deklaracji pętli.źródło
s
w pierwszej deklaracjifor
?JavaScript (ES6), 35 bajtów
Pobiera tablicę znaków jako dane wejściowe i zwraca tablicę szczegółową.
źródło
c=>(s[c]=-~s[c])<3
aby zaoszczędzić kilka bajtów.map
. Grał w golfa w zasadzie wyglądał jak twój. główną różnicą było przypisanie, które, jeśli je przełączysz, zaoszczędzi kilka bajtów. Spróbujs.filter(c=>(s[c]=s[c]+1|0)<3)
33 bajtów. EDYCJA: Ups, przegapiłem komentarz nade mną, to jeszcze lepiej :)PowerShell v2 +, 31 bajtów
Używa tego samego wyrażenia regularnego, co w odpowiedzi Retina Kobi , po prostu enkapsulowanej w
-replace
operatorze PowerShell . Działa, ponieważ oba używają w tle wyrażenia regularnego .NET-flavour.Alternatywnie, bez wyrażenia regularnego, 56 bajtów
Tworzy tablicę pomocniczą
$b
wstępnie wypełnioną0
s. Rzuca ciąg wejściowy$args[0]
jakochar
tablicę, przepuszcza go przez pętlę|%{...}
. Każda iteracja generuje bieżący znak$_
jako ciąg"$_"
pomnożony przez wartość logiczną, która jest$TRUE
(domyślnie rzutowana1
tutaj) tylko wtedy, gdy odpowiedni punkt w tablicy pomocniczej jest mniejszy niż2
(tj. Nie widzieliśmy tego znaku dwa razy). Powstały zbiór ciągów jest enkapsulowany w pareny i edytowany-join
razem, tworząc pojedynczy ciąg wyjściowy. Pozostaje to w potoku, a dane wyjściowe są niejawne.źródło
$b=@{};-join($args|% t*y|?{++$b.$_-lt3})
.Mathematica, 39 bajtów
Funkcja anonimowa. Pobiera listę znaków jako dane wejściowe i zwraca listę danych szczegółowych jako dane wyjściowe. Używa metody zwijania listy i odrzucania potrójnych elementów, nie jest to zbyt skomplikowane.
źródło
05AB1E, 12 bajtów
Wyjaśnienie
Wypróbuj online
źródło
MATL , 8 bajtów
Wypróbuj online!
Wyjaśnienie
Przykład
Zakładając dane wejściowe
'aaababbc'
, stos zawiera następujące elementy po wskazanych instrukcjach:t
t&=
t&=R
t&=Rs
t&=Rs3<
t&=Rs3<)
źródło
Siatkówka , 14 bajtów
Sprawdź wszystkie przypadki testowe. (
%
Włącza tryb per-line)Wykorzystuje nowy etap „deduplikacji”, aby zaoszczędzić kilka bajtów w stosunku do podejścia Kobi . Deduplikat gromadzi listę wszystkich dopasowań wyrażenia regularnego i zastępuje wszystkie oprócz pierwszego pustym ciągiem. Wyrażenie regularne dopasowuje znak, który już pojawia się raz w ciągu, co oznacza, że pierwsze dwa zostaną zachowane.
źródło
Pyke, 16 bajtów
Wypróbuj tutaj!
źródło
K, 18 bajtów
K4 jest dostępny do pobrania za darmo ; K6 jest w fazie rozwoju . Jeśli pobrałeś KDB, możesz dostać się do K z ukośnikiem odwrotnym .
Być może najłatwiej jest to rozdzielić, ale najpierw trochę składni:
g:x
ustawiag
nax
.{x+1}
jest funkcją, która przyjmuje argument x . W K pierwszym argumentem funkcji jestx
(drugi jest,y
a trzeci jestz
. Nie potrzebujesz czwartego).Teraz:
=x
oznacza grupę x , która wytwarza:2#'
oznacza dwa pobrane (z) każdego, które produkujeJak widać, są to przesunięcia pierwszych dwóch dopasowań każdej postaci. 2 mogą być uogólnione.
,/
oznacza dołączyć do każdego i jest często nazywany raze . Dostarczy nam tylko wartości naszego słownika. W ten sposób,/"abcd"!(0 1;3 5;4 6;8 12)
produkuje:które musimy posortować.
{x@<x}@
to idiom, który często widzą programiści K (Q nazywa to asc ), co mówi x przy ocenie x . Rozbijając to na części:zwróciło wskaźniki posortowanej tablicy, które chcemy pobrać z oryginalnej tablicy.
x@y
oznacza x at y, więc indeksuje tablicę indeksami tego rodzaju (jeśli ma to jakiś sens).które po prostu indeksujemy teraz do naszej oryginalnej tablicy. My mogliśmy powiedzieć
x@
tutaj, ale K obsługuje naprawdę potężne pojęcie, które możemy wykorzystać tutaj: application funkcja indeksowania. Oznacza to, żea[0]
może szukać zerowej szczelinya
lub może zastosować funkcję0
do wywołanej funkcjia
. Powodem, dla którego potrzebowaliśmy@
poprzednio,{x@<x}
jest to, żex<y
oznacza xs mniej niż ys : Operatory w K mają formę diadadową (dwuparametrową) i formę monadyczną (jednotargową) pochodzącą z APL. Q nie ma tej „ambiwalencji”.źródło
g"aaabcbccdbabdcd"
g"..."
. Niestety Twój kod zwracaaabbcc
dane wejścioweabc
.{x{?x@<x}@,/2#'=x}"abc"
zdecydowanie wraca"abc"
. Wróci,"aabbcc"
jeśli przegapisz?
wyraźne.Python 2, 51 bajtów
Przetestuj na Ideone .
źródło
Java 8 lambda, 90 znaków
Wersja bez golfa:
Tworzy tablicę dla wszystkich znaków ascii. Jeśli pojawi się postać, odpowiedni licznik zostanie zwiększony. Jeśli przekroczy 2, znak nie zostanie dołączony do ciągu wynikowego. Bardzo łatwe, bardzo krótkie;)
źródło
Perl 6, 27 bajtów
Wyjaśnienie:
(Uwaga: Perl 6 nie jest tak „zorientowany na golfa” jak jego siostra Perl 5 ... Więc tak, to miejsce przed
<
koniecznością.%.{}
Jest to anonimowy skrót).źródło
SmileBASIC,
77726968 bajtówWyjaśniono:
źródło
Common Lisp, 127
Całkiem drukowane
źródło
Q , 52 bajtów
źródło
K , 27 bajtów
źródło
Ruby ,
796257 bajtówJest to dość niewygodne, ale nie jestem pewien, czy mogę teraz grać w golfa o wiele lepiej. Wszelkie sugestie dotyczące gry w golfa są mile widziane. Wypróbuj online!
Edycja: -17 bajtów dzięki Value Ink, sugerując bardziej golfowy sposób na usunięcie trzech powtórzeń. -5 bajtów od usunięcia
.uniq
metody.Nie golfowany:
źródło
->s{s.chars.uniq.map{|a|s[s.rindex a]=""while s.count(a)>2};s}
JavaScript, 30 bajtów
Używając metody, którą @ edc65 wymyślił do zliczania, ale z filtrem tablicowym. Gdy pojawia się pierwszy znak, wartość obiektu staje się „niezdefiniowana” plus znak (tzn. „Niezdefiniowany”). Następnym razem, gdy wartość obiektu stanie się „undefinedxx”.
Następnie v [x] [11] zwraca true, a po połączeniu z operatorem not, false, co oznacza, że znaki, które pojawiły się dwukrotnie, zostaną odfiltrowane.
źródło
JavaScript (przy użyciu zewnętrznej biblioteki) (80 bajtów)
To był dobry! Nie wygrał, ale było fajnie
Link do lib: https://github.com/mvegh1/Enumerable/
Objaśnienie kodu: Metoda akceptuje ciąg znaków, biblioteka analizuje go jako tablicę znaków, a klauzula Where jest złożonym predykatem filtrującym, który sprawdza skrót mapy „a” pod kątem obecności bieżącego znaku. Jeśli istnieje, licznik przyrostów, w przeciwnym razie ustawiony na 1. Jeśli <2, predykat (i bieżący znak) przejdzie, w przeciwnym razie nie powiedzie się
źródło
return
ale czyni czynność listę oddzielonych przecinkami ciągu wyrażeń w nawiasach:n=>(a={},_From(n)....)
. Ostatnie wyrażenie jest wartością zwracaną. W swojejWhere
funkcji, można wyeliminować pośrednib
całkowicie porównując przeciwko wyniku cesji lub przyrostu:x=>(a[x]?a[x]++:a[x]=1)<2
.filter
zjoin
:[...n].filter(...).join("")
. Odwróć logikę prawda / fałsz przy zmianieWhere
nafilter
.Clojure, 72 bajty
Tyle bajtów ...
źródło
Pascal (FPC) , 103 bajty
Wypróbuj online!
Wyjaśnienie:
źródło