Beaucoup de langues ont des méthodes intégrées pour se débarrasser des doublons, ou "dédupliquer" ou "déséquilibrer" une liste ou une chaîne. Une tâche moins courante consiste à "détripliquer" une chaîne. C'est-à-dire que pour chaque caractère qui apparaît, les deux premières occurrences sont conservées.
Voici un exemple où les caractères qui devraient être supprimés sont étiquetés avec ^
:
aaabcbccdbabdcd
^ ^ ^^^ ^^
aabcbcdd
Votre tâche consiste à implémenter exactement cette opération.
Règles
L'entrée est une chaîne unique, éventuellement vide. Vous pouvez supposer qu'il ne contient que des lettres minuscules dans la plage ASCII.
La sortie doit être une chaîne unique avec tous les caractères supprimés qui sont déjà apparus au moins deux fois dans la chaîne (les deux occurrences les plus à gauche sont donc conservées).
Au lieu de chaînes, vous pouvez utiliser des listes de caractères (ou des chaînes singleton), mais le format doit être cohérent entre entrée et sortie.
Vous pouvez écrire un programme ou une fonction et utiliser l’une quelconque de nos méthodes standard de réception d’entrée et de sortie.
Vous pouvez utiliser n'importe quel langage de programmation , mais notez que ces failles sont interdites par défaut.
C'est du code-golf , donc la réponse valide la plus courte - mesurée en octets - est gagnante.
Cas de test
Chaque paire de lignes correspond à un cas de test, une entrée suivie par une sortie.
xxxxx
xx
abcabc
abcabc
abcdabcaba
abcdabc
abacbadcba
abacbdc
aaabcbccdbabdcd
aabcbcdd
Classement
L'extrait de pile au bas de cet article génère un classement à partir des réponses a) sous forme de liste des solutions les plus courtes par langue et b) sous forme de classement global.
Pour vous assurer que votre réponse apparaît, commencez votre réponse par un titre, en utilisant le modèle Markdown suivant:
## Language Name, N bytes
où N
est la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores en les effaçant. Par exemple:
## Ruby, <s>104</s> <s>101</s> 96 bytes
Si vous souhaitez inclure plusieurs numéros dans votre en-tête (par exemple, parce que votre score est la somme de deux fichiers ou si vous souhaitez répertorier séparément les pénalités d'indicateur d'interprétation), assurez-vous que le score réel est le dernier numéro de l'en-tête:
## Perl, 43 + 3 (-p flag) = 45 bytes
Vous pouvez également faire du nom de la langue un lien qui apparaîtra ensuite dans l'extrait de code:
## [><>](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>
Réponses:
Gelée , 6 octets
Essayez-le en ligne! ou vérifier tous les cas de test .
Comment ça marche
la source
JavaScript (ES6), 42
48Modifier 6 octets sauvés thx @Neil
Explication: J'utilise les propriétés 'a' ... 'z' d'objet
k
pour stocker les informations relatives à chaque caractère (l'objet k est une expression rationnelle dans le cas présent uniquement pour enregistrer des octets). Ces propriétés sont initialementundefined
. En javascript ajoutant un numéroundefined
donneNaN
(tout à fait raisonnable), mais en ajoutant une chaîne « X » donne"undefinedX"
- une chaîne de longueur 10 (stupide). Ajouter plus de caractères vous obtenez des chaînes plus longues. Si la chaîne obtenue pour un caractère donné est supérieure à 11, ce caractère n'est pas copié dans la sortie.Tester
la source
v=>v.filter(x=>!(v[x]+=x)[11])
. Bravo au hack "indéfini".Python 2, 48 octets
c[r.count(c)/2:]
est une alternative de même longueur àc*(r.count(c)<2)
.49 octets:
la source
Retina , 17 octets
Essayez-le en ligne!
Regex simple replace - faites correspondre un caractère s'il est déjà apparu deux fois et supprimez-le.
la source
{2}
, les deux avec 18 octets.:P
. Merci!Brachylog , 25 octets
Essayez-le en ligne! ou vérifier tous les cas de test .
Explication
Cela fonctionne parce que
s - Subset
l'unifiera d'abord avec les plus gros sous-ensembles, par exemple"aaa"
il essaiera"aa"
avant"a"
.Prédicat principal:
Prédicat 1: Vérifiez que tous les caractères n'apparaissent qu'au plus deux fois. Entrée =
[String:Char]
Prédicat 2: Obtenir l'occurrence d'un personnage. Entrée =
[String:Char]
la source
> <> , 22 octets
Essayez-le en ligne! Utilise la boîte à code pour suivre les comptes jusqu'à présent.
la source
J,
2015 octetsCeci définit une fonction monadique qui prend et retourne une chaîne. Essayez-le ici . Usage:
Explication
Je suis passé au même algorithme que d'autres solutions, puisqu'il s'est avéré plus court ...
la source
Haskell,
40 à39 octetsExemple d'utilisation:
foldl(\s c->s++[c|filter(==c)s<=[c]])"" "aaabcbccdbabdcd"
->"aabcbcdd"
.Conservez le prochain caractère
c
si la chaîne de tous lesc
s jusqu'à présent est lexicographique inférieure ou égale à la chaîne de singleton[c]
.Edit: @xnor a sauvegardé un octet en passant de la compréhension de liste à
filter
. Merci!la source
filter(==c)s<=[c]
pour sauver un octet.Perl, 22 octets
Code 21 octets + 1 pour
-p
.Usage
la source
C, 57 octets
Appelez
f()
avec la chaîne à détruire. La fonction modifie son paramètre. Requiert C99 en raison de lafor
déclaration -loop.la source
s
dans la première déclaration de lafor
?JavaScript (ES6), 35 octets
Prend un tableau de caractères en entrée et retourne le tableau détruit.
la source
c=>(s[c]=-~s[c])<3
pour sauver quelques octets.map
. Golfé, il ressemblait essentiellement au vôtre. la principale différence était l'affectation qui, si vous la permutez, économisera quelques octets. Essayezs.filter(c=>(s[c]=s[c]+1|0)<3)
33 octets. EDIT: Whoops, a raté le commentaire ci - dessus moi, qui est encore mieux :)PowerShell v2 +, 31 octets
Utilise la même expression rationnelle que dans la réponse Retina de Kobi , qui vient d'être encapsulée dans l'
-replace
opérateur PowerShell . Fonctionne parce que les deux utilisent .NET -avor regex en arrière-plan.Sinon, sans regex, 56 octets
Crée un tableau d'assistance
$b
pré-rempli avec0
s. Jette la chaîne d'entrée$args[0]
tant quechar
-array, la dirige au travers d'une boucle|%{...}
. Chaque itération génère le caractère actuel$_
sous forme de chaîne"$_"
multipliée par un booléen qui est uniquement$TRUE
(implicitement converti1
ici) si le point approprié dans le tableau d'assistance est inférieur à2
(nous n'avons pas déjà vu ce caractère deux fois). La collection résultante de chaînes est encapsulée dans des parenthèses et-join
édité ensemble pour ne former qu'une seule chaîne de sortie. Cela reste sur le pipeline et la sortie est implicite.la source
$b=@{};-join($args|% t*y|?{++$b.$_-lt3})
.Mathematica, 39 octets
Fonction anonyme. Prend une liste de caractères en entrée et renvoie la liste détaillée en sortie. Utilise la méthode de replier la liste et de rejeter les éléments en triple, ce n'est pas trop compliqué.
la source
05AB1E, 12 octets
Explication
Essayez-le en ligne
la source
MATL , 8 octets
Essayez-le en ligne!
Explication
Exemple
En supposant une entrée
'aaababbc'
, la pile contient les éléments suivants après les instructions indiquées:t
t&=
t&=R
t&=Rs
t&=Rs3<
t&=Rs3<)
la source
Rétine , 14 octets
Vérifier tous les cas de test. (Le
%
mode par ligne activé)Utilise la nouvelle étape de "déduplication" pour économiser quelques octets sur l'approche de Kobi . Deduplicate rassemble une liste de toutes les correspondances dans la regex et remplace toutes les chaînes sauf la première par la chaîne vide. La regex correspond à un caractère qui apparaît déjà une fois dans la chaîne, ce qui signifie que les deux premiers seront conservés.
la source
Pyke, 16 octets
Essayez-le ici!
la source
K, 18 octets
K4 est disponible en téléchargement gratuit ; K6 est en développement . Si vous avez téléchargé KDB, vous pouvez entrer dans K avec une barre oblique inverse .
Il est peut-être plus facile de voir cela en morceaux, mais d’abord une syntaxe:
g:x
définitg
àx
.{x+1}
est une fonction qui prend un argument x . En K, le premier argument d'une fonction estx
(le second esty
et le troisième estz
. N'a pas besoin d'un quatrième).À présent:
=x
signifie groupe x , qui produit:2#'
signifie deux prises (de) chacune qui produitComme vous pouvez le constater, ce sont les décalages des deux premières correspondances de chaque personnage. le 2 pourrait être généralisé.
,/
signifie se joindre à chacun et est souvent appelé raze . Cela ne nous apportera que les valeurs de notre dictionnaire. Ainsi,,/"abcd"!(0 1;3 5;4 6;8 12)
produit:que nous devons trier.
{x@<x}@
est un idiome que les programmeurs voient souvent (Q l’appelle asc ), qui dit x à la montée de niveau x . Le briser:retourné les index du tableau trié, que nous voulons prendre à partir du tableau original.
x@y
signifie x en y donc ceci indexe le tableau avec les index de la sorte (si cela a un sens).que nous indexons simplement maintenant dans notre tableau d'origine. Nous pourrions dire
x@
ici, mais K soutient un concept très puissant dont nous pouvons tirer avantage ici: l’application de fonction est l’indexation. Cela signifie que celaa[0]
pourrait être la recherche de la fente zéroa
ou appliquer la0
à la fonction appeléea
. La raison pour laquelle nous avions besoin de@
précédemment{x@<x}
est parce que lesx<y
moyennes xs sont inférieures à ys : les opérateurs de K ont une forme dyadique (deux arguments) et une forme monadique (un argument) qui provient de APL. Q n'a pas cette "ambivalence".la source
g"aaabcbccdbabdcd"
g"..."
fait le tour. Malheureusement, votre code retourneaabbcc
pour la saisieabc
.{x{?x@<x}@,/2#'=x}"abc"
un retour définitif"abc"
. Il reviendrait"aabbcc"
si vous avez manqué le?
distinct.Python 2, 51 octets
Testez-le sur Ideone .
la source
Java 8 lambda, 90 caractères
Version non-golfée:
Crée un tableau pour tous les caractères ascii. Si un personnage apparaît, le compteur correspondant sera augmenté. S'il est supérieur à 2, le caractère ne sera pas ajouté à la chaîne de résultat. Très facile, très court;)
la source
Perl 6, 27 octets
Explication:
(Remarque: Perl 6 n'est pas aussi "orienté golf" que sa soeur Perl 5 ... Alors oui, cet espace avant
<
est nécessaire. Il%.{}
s'agit d'un hachage anonyme).la source
SmileBASIC,
77726968 octetsA expliqué:
la source
Common Lisp, 127
Joli imprimé
la source
Q , 52 octets
la source
K , 27 octets
la source
Ruby ,
796257 octetsC'est assez difficile à manier, mais je ne suis pas sûr de pouvoir jouer au golf autant mieux pour le moment. Toutes les suggestions de golf sont les bienvenues. Essayez-le en ligne!
Éditer: -17 octets grâce à Value Ink en suggérant un moyen plus rapide de supprimer les caractères en triple. -5 octets de supprimer la
.uniq
méthode.Ungolfed:
la source
->s{s.chars.uniq.map{|a|s[s.rindex a]=""while s.count(a)>2};s}
JavaScript, 30 octets
En utilisant la méthode que @ edc65 a conçue pour compter mais avec un filtre tableau. Le premier caractère apparaît, la valeur de l'objet devient "indéfini" plus le caractère ("indéfini"). La prochaine fois que la valeur de l'objet devient "undefinedxx".
Après cela, v [x] [11] renvoie true et, une fois combiné avec l'opérateur not, false, ce qui signifie que les caractères déjà apparus deux fois seront filtrés.
la source
Javascript (en utilisant une bibliothèque externe) (80 octets)
C'était un bon! N'a pas gagné mais c'était amusant
Lien vers lib: https://github.com/mvegh1/Enumerable/
Explication de code: La méthode accepte une chaîne, la bibliothèque l'analyse en tant que tableau de caractères et la clause Where est un prédicat de filtrage complexe qui vérifie si la table de hachage 'a' contient le caractère actuel. S'il existe, incrémente le compteur, sinon, mis à 1. Si <2, le prédicat (et le caractère actuel) passe, sinon échouera.
la source
return
mais faire de votre fonction d' une liste séparée par des virgules d'une expressions entre parenthèses:n=>(a={},_From(n)....)
. La dernière expression est la valeur de retour. Dans votreWhere
fonction, vous pouvez éliminer l'intermédiaireb
entièrement en comparant contre le résultat de la cession ou augmentation:x=>(a[x]?a[x]++:a[x]=1)<2
.filter
avecjoin
:[...n].filter(...).join("")
. Retournez la logique vrai / faux lorsque vous passezWhere
àfilter
.Clojure, 72 octets
Tant d'octets ...
la source
Pascal (FPC) , 103 octets
Essayez-le en ligne!
Explication:
la source