Muitos idiomas têm maneiras integradas de se livrar de duplicatas ou "desduplicar" ou "unificar" uma lista ou string. Uma tarefa menos comum é "descriptografar" uma string. Ou seja, para cada personagem que aparece, os dois primeiros ocorrências são mantidas.
Aqui está um exemplo em que os caracteres que devem ser excluídos são rotulados com ^
:
aaabcbccdbabdcd
^ ^ ^^^ ^^
aabcbcdd
Sua tarefa é implementar exatamente esta operação.
Regras
A entrada é uma única sequência, possivelmente vazia. Você pode assumir que ele contém apenas letras minúsculas no intervalo ASCII.
A saída deve ser uma única sequência com todos os caracteres removidos que já apareceram pelo menos duas vezes na sequência (para que as duas ocorrências mais à esquerda sejam mantidas).
Em vez de strings, você pode trabalhar com listas de caracteres (ou strings singleton), mas o formato deve ser consistente entre entrada e saída.
Você pode escrever um programa ou uma função e usar qualquer um dos nossos métodos padrão de recebimento de entrada e saída.
Você pode usar qualquer linguagem de programação , mas observe que essas brechas são proibidas por padrão.
Isso é código-golfe , então a resposta mais curta e válida - medida em bytes - vence.
Casos de teste
Cada par de linhas é um caso de teste, entrada seguida por saída.
xxxxx
xx
abcabc
abcabc
abcdabcaba
abcdabc
abacbadcba
abacbdc
aaabcbccdbabdcd
aabcbcdd
Entre os melhores
O snippet de pilha na parte inferior desta postagem gera um cabeçalho das respostas a) como uma lista da solução mais curta por idioma eb) como um cabeçalho geral.
Para garantir que sua resposta seja exibida, inicie-a com um título, usando o seguinte modelo de remarcação:
## Language Name, N bytes
onde N
está o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:
## Ruby, <s>104</s> <s>101</s> 96 bytes
Se você quiser incluir vários números em seu cabeçalho (por exemplo, porque sua pontuação é a soma de dois arquivos ou deseja listar as penalidades de sinalizador de intérprete separadamente), verifique se a pontuação real é o último número no cabeçalho:
## Perl, 43 + 3 (-p flag) = 45 bytes
Você também pode transformar o nome do idioma em um link que será exibido no snippet:
## [><>](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>
Respostas:
Gelatina , 6 bytes
Experimente online! ou verifique todos os casos de teste .
Como funciona
fonte
JavaScript (ES6), 42
48Editar Um enorme 6 bytes salvos thx @Neil
Explicação: Uso as propriedades 'a' ... 'z' do objeto
k
para armazenar informações para cada caractere (o objeto k é uma expressão regular, neste caso, apenas para salvar bytes). Essas propriedades são inicialmenteundefined
. No javascript, adicionar um número aundefined
dáNaN
(bastante sensato), mas adicionar uma string 'X' dá"undefinedX"
- uma string de comprimento 10 (bobo). Adicionando mais caracteres, você obtém seqüências mais longas. Se a sequência obtida para um determinado caractere for maior que 11, esse caractere não será copiado para a saída.Teste
fonte
v=>v.filter(x=>!(v[x]+=x)[11])
. Parabéns pelo hack "indefinido".Python 2, 48 bytes
c[r.count(c)/2:]
é uma alternativa do mesmo comprimento parac*(r.count(c)<2)
.49 bytes:
fonte
Retina , 17 bytes
Experimente online!
Substituição simples de regex - combine um caractere se ele já apareceu duas vezes e remova-o.
fonte
{2}
, ambos com 18 bytes.:P
. Obrigado!Braquilog , 25 bytes
Experimente online! ou verifique todos os casos de teste .
Explicação
Isso funciona porque
s - Subset
será unificado primeiro com subconjuntos maiores, por exemplo, porque"aaa"
ele tentará"aa"
antes"a"
.Predicado principal:
Predicado 1: verifique se todos os caracteres aparecem apenas no máximo duas vezes. Input =
[String:Char]
Predicado 2: Consiga a ocorrência de um personagem. Input =
[String:Char]
fonte
> <> , 22 bytes
Experimente online! Usa o codebox para acompanhar as contagens até o momento.
fonte
J,
2015 bytesIsso define uma função monádica que pega e retorna uma string. Experimente aqui . Uso:
Explicação
Eu mudei para o mesmo algoritmo usado por algumas outras soluções, pois acabou sendo mais curto ...
fonte
Haskell,
4039 bytesExemplo de uso:
foldl(\s c->s++[c|filter(==c)s<=[c]])"" "aaabcbccdbabdcd"
->"aabcbcdd"
.Mantenha o próximo caractere
c
se a sequência de todos osc
s até agora for lexicográfica menor ou igual à sequência singleton[c]
.Edit: @xnor salvou um byte alternando da compreensão da lista para
filter
. Obrigado!fonte
filter(==c)s<=[c]
para salvar um byte.Perl, 22 bytes
Código de 21 bytes + 1 para
-p
.Uso
fonte
C, 57 bytes
Ligue
f()
com a cadeia para detriplicar. A função modifica seu parâmetro. Requer C99 devido àfor
declaração -loop.fonte
s
na primeira declaração dofor
?JavaScript (ES6), 35 bytes
Pega uma matriz de caracteres como entrada e retorna a matriz com descrições duplicadas.
fonte
c=>(s[c]=-~s[c])<3
para salvar alguns bytes.map
. Golfe, parecia essencialmente com o seu. a principal diferença era a atribuição, que, se você alternar, economizará alguns bytes. Tentes.filter(c=>(s[c]=s[c]+1|0)<3)
por 33 bytes. EDIT: Opa, perdeu o comentário acima de mim, que é ainda melhor :)PowerShell v2 +, 31 bytes
Usa o mesmo regex que na resposta Retina de Kobi , encapsulado no
-replace
operador PowerShell . Funciona porque ambos estão usando regex com sabor .NET em segundo plano.Como alternativa, sem regex, 56 bytes
Cria uma matriz auxiliar
$b
previamente preenchida com0
s. Lança a sequência de entrada$args[0]
como umachar
matriz, passa por um loop|%{...}
. Cada iteração gera o caractere atual$_
como uma sequência"$_"
multiplicada por um booleano que é apenas$TRUE
(convertido implicitamente para1
aqui) se o ponto apropriado na matriz auxiliar for menor que2
(ou seja, já não vimos esse caracter duas vezes). A coleção resultante de seqüências de caracteres é encapsulada em parênteses e-join
editada em conjunto para formar uma única sequência de saída. Isso é deixado no pipeline e a produção está implícita.fonte
$b=@{};-join($args|% t*y|?{++$b.$_-lt3})
.Mathematica, 39 bytes
Função anônima. Pega uma lista de caracteres como entrada e retorna a lista descriptografada como saída. Usa o método de dobrar a lista e rejeitar elementos em triplicado, não é muito complicado.
fonte
05AB1E, 12 bytes
Explicação
Experimente online
fonte
MATL , 8 bytes
Experimente online!
Explicação
Exemplo
Supondo entrada
'aaababbc'
, a pilha contém o seguinte após as instruções indicadas:t
t&=
t&=R
t&=Rs
t&=Rs3<
t&=Rs3<)
fonte
Retina , 14 bytes
Verifique todos os casos de teste. (
%
Ativa o modo por linha)Usa o novo estágio "Deduplicate" para salvar alguns bytes sobre a abordagem de Kobi . A eliminação de duplicatas reúne uma lista de todas as correspondências no regex e substitui todas, exceto a primeira, pela sequência vazia. A regex corresponde a um caractere que já aparece uma vez na cadeia, o que significa que os dois primeiros serão mantidos.
fonte
Pyke, 16 bytes
Experimente aqui!
fonte
K, 18 bytes
O K4 está disponível para download gratuito ; K6 está em desenvolvimento . Se você baixou o KDB, pode entrar no K com barra invertida .
Pode ser mais fácil ver isso desmembrado, mas primeiro alguma sintaxe:
g:x
defineg
comox
.{x+1}
é uma função que recebe um argumento x . Em K, o primeiro argumento para uma função éx
(o segundo éy
e o terceiro éz
. Não precisa de um quarto).Agora:
=x
significa grupo x , que produz:2#'
significa dois retirados (de) cada um que produzComo você pode ver, esses são os desvios das duas primeiras partidas de cada personagem. Os 2 podem ser generalizados.
,/
significa juntar-se a cada um e é chamado de raze . Isso nos dará apenas os valores do nosso dicionário. Assim,,/"abcd"!(0 1;3 5;4 6;8 12)
produz:que precisamos classificar.
{x@<x}@
é um idioma que os programadores costumam ver (Q chama de asc ), que diz x na classificação x . Desmembrando:retornou os índices da matriz classificada, que queremos obter da matriz original.
x@y
significa x em y, portanto, indexa a matriz com os índices da classificação (se isso faz algum sentido).que simplesmente indexamos agora em nossa matriz original. Nós poderia dizer
x@
aqui, mas K suporta um conceito muito poderoso que pode tirar vantagem de aqui: aplicação de função é a indexação. Isso significa quea[0]
pode estar procurando o slot zerotha
ou pode estar aplicando o0
à função chamadaa
. A razão pela qual precisávamos@
anteriormente{x@<x}
é porquex<y
significa xs menor que ys : os operadores em K têm uma forma diádica (dois argumentos) e uma forma monádica (um argumento) que vem da APL. Q não tem essa "ambivalência".fonte
g"aaabcbccdbabdcd"
g"..."
faz o truque. Infelizmente, seu código retornaaabbcc
para entradaabc
.{x{?x@<x}@,/2#'=x}"abc"
definitivamente retorna"abc"
. Voltaria"aabbcc"
se você perdesse o?
distinto.Python 2, 51 bytes
Teste em Ideone .
fonte
Java 8 lambda, 90 caracteres
Versão não destruída:
Cria uma matriz para todos os caracteres ascii. Se um caractere ocorrer, o contador correspondente será aumentado. Se for maior que 2, o caractere não será anexado à sequência de resultados. Muito fácil, muito curto;)
fonte
Perl 6, 27 bytes
Explicação:
(Nota: o Perl 6 não é tão "orientado para o golfe" quanto sua irmã Perl 5 ... Então sim, esse espaço antes do
<
necessário é necessário. O%.{}
hash é anônimo).fonte
SmileBASIC,
77726968 bytesExplicado:
fonte
Lisp comum, 127
Pretty-impresso
fonte
Q , 52 bytes
fonte
K , 27 bytes
fonte
Ruby ,
796257 bytesIsso é bastante pesado, mas não tenho certeza se posso jogar muito melhor no momento. Todas as sugestões de golfe são bem-vindas. Experimente online!
Edit: -17 bytes graças ao Value Ink, sugerindo uma maneira mais eficiente de remover caracteres em triplicado. -5 bytes da remoção do
.uniq
método.Ungolfed:
fonte
->s{s.chars.uniq.map{|a|s[s.rindex a]=""while s.count(a)>2};s}
JavaScript, 30 bytes
Usando o método que o @ edc65 surgiu para contar, mas com um filtro de matriz. Quando o caractere aparece pela primeira vez, o valor do objeto fica "indefinido" mais o caractere (ou seja, "indefinidox"). A próxima vez que o valor do objeto se tornar "undefinedxx".
Depois disso, v [x] [11] retorna true e quando combinado com o operador not, false, significando caracteres que já apareceram duas vezes serão filtrados.
fonte
Javascript (usando biblioteca externa) (80 bytes)
Essa foi boa! Não ganhou, mas foi divertido
Link para lib: https://github.com/mvegh1/Enumerable/
Explicação do código: O método aceita uma string, a biblioteca a analisa como uma matriz de caracteres e a cláusula Where é um predicado de filtragem complexo que verifica o hashmap 'a' quanto à presença do caractere atual. Se existir, incremente o contador; caso contrário, defina como 1. Se <2, o predicado (e o caractere atual) for aprovado, o restante falhará.
fonte
return
, mas fazer a sua função de uma lista separada por vírgulas de um expressões entre parênteses:n=>(a={},_From(n)....)
. A última expressão é o valor de retorno. Em suaWhere
função, você pode eliminar o intermediáriob
inteiramente comparando contra o resultado da cessão ou incremento:x=>(a[x]?a[x]++:a[x]=1)<2
.filter
comjoin
:[...n].filter(...).join("")
. Inverta a lógica verdadeira / falsa ao mudarWhere
parafilter
.Clojure, 72 bytes
Tantos bytes ...
fonte
Pascal (FPC) , 103 bytes
Experimente online!
Explicação:
fonte