Classificar uma sequência de opções

8

fundo

Em C, há uma função de argumentos de linha de comando ajuda de análise: getopt.

Getopt pega o argumento count ( argc), a lista de argumentos ( argv) e uma string que representa as opções que o programa deve usar ( optstring).

A opção string ( optstring) é uma série de caracteres de opção, cada um seguido por dois pontos (para uma opção que exige um argumento), dois pontos (para uma opção com argumento opcional) ou zero dois pontos (para uma opção sem argumento).

Por exemplo: pode-se usar a seguinte opção para o novo widget da empresa.

"v::x:hy:S:G::dns:f::"

Mas isso parece horrível! As opções são todas misturadas! Essa sequência de opções ficaria muito melhor se fosse classificada:

"f::G::v::S:s:x:y:dhn"

Especificações

  • A entrada será uma string que corresponde à expressão regular ([A-Za-z]:{0,2})+

  • Você deve receber a entrada como uma sequência ou lista de caracteres.

  • Você deve gerar a sequência classificada pelo método detalhado abaixo.

  • Você não precisa manipular entrada vazia.

  • Você não precisa manipular entrada com opções repetidas do mesmo tipo ( "aa"não é válido, mas "aa:a::"é válido).

Método de classificação

Na sequência de opções classificada:

  • Os caracteres seguidos por dois pontos-vírgulas são os primeiros, classificados em ordem alfabética, com letras maiúsculas antes de suas respectivas letras minúsculas (ou seja, "aBb", não "Bab").

  • Em seguida, são os caracteres com um dois pontos, classificados em ordem alfabética, com letras maiúsculas antes de suas respectivas letras minúsculas.

  • Por último, os caracteres sem dois pontos, classificados em ordem alfabética, com letras maiúsculas antes de suas respectivas letras minúsculas.

Regras

Pontuação

Isso é , então a resposta mais curta em bytes em cada idioma vence.

Exemplos

# "input" => "output"
"v::x:hy:S:G::dns:f::" => "f::G::v::S:s:x:y:dhn"
"aa:a::" => "a::a:a"
"B:" => "B:"
"Confusio:n::" => "n::o:Cfinosu"
"Confusio:n:" => "n:o:Cfinosu"
"m:qW:X:xc:vViI" => "c:m:W:X:IiqVvx"
"V:omo:V" => "o:V:moV"
"agg:ra:va::ting::" => "a::g::a:g:aginrtv"
"input" => "inptu"

Caso de teste longo (312 caracteres)

Entradas do Invaid (você não precisa lidar com):

"gg" (duplicated option)
"" (empty string)
":w:" (first colon isn't after a character)
"x:y:0:fhn" ('0' is not alphabetic)
"A:::" (3 colons is invalid)
pizzapants184
fonte
agg:ra:va::ting::quebrou o meu heh ... Irônico.
Magic Octopus Urn

Respostas:

9

Casca , 11 bytes

ΣÖom_↔Oġλ¬√

Experimente online!

Explicação

ΣÖom_↔Oġλ¬√  Implicit input, say "kH::r:R:Hk:"
       ġ     Split between characters for which this gives a falsy result:
        λ      Take two arguments, ignore the first.
          √    Is the second argument a letter?
         ¬     Negate.
             Now we have the options: ["k","H::","r:","R:","H","k:"]
      O      Sort: ["H","H::","R:","k","k:","r:"]
 Ö           Sort by
     ↔       reversing and
  om_        converting everything to lowercase: ["H::","k:","R:","r:","H","k"]
Σ            Concatenate: H::k:R:r:Hk
Zgarb
fonte
Há algumas idéias realmente inteligentes aqui, você deve adicionar uma explicação para que as pessoas possam apreciá-las: D
Leo
1
@Leo Adicionado um detalhamento do código.
Zgarb
3

Retina , 47 bytes

.
$&$&
T01`L`l`..
O^`\w.:*
.(.)
$1
O$^`\w:*
$.&

Experimente online!

A parte mais complicada foi classificar as letras, porque o recurso "classificar por" de Retina não possui uma classificação que não diferencia maiúsculas de minúsculas (por padrão, ele classifica as letras maiúsculas na frente de todas as letras minúsculas). Para contornar isso, tive que inserir uma cópia em minúscula de cada caractere para fazer a classificação e depois me livrar dela novamente.

Martin Ender
fonte
Uma classificação que não diferencia maiúsculas de minúsculas foi adicionada em algum lugar no ano passado? E, se não, existe uma maneira de classificar sem distinção entre maiúsculas e minúsculas, mas manter a ordem original? Ou seja, tEsTiNgcom o seu método de classificação acima, os pares de letras são classificados em eEggiinNsstTtt → EgiNsTtvez de eEggiinNsstttT → EgiNstT (as letras maiúsculas são sempre colocadas antes das letras minúsculas).
Kevin Cruijssen 18/01/19
1
@KevinCruijssen Você pode fazer isso com ordenar agora, porque é possível transformar facilmente o caractere em minúscula na sequência de substituição. tio.run/##K0otycxLNPyvquGe8N9fJUGPSyVHRe3//xLX4pBMv3QA
Martin Ender
Ah legal. Eu nunca teria pensado nisso. Muito obrigado. Consegui corrigir minha resposta agora. :)
Kevin Cruijssen 18/01/19
2

Gelatina , 14 bytes

n”:œṗ⁸ṢŒuÞṚLÞṚ

Experimente online!

Programa completo.

Erik, o Outgolfer
fonte
2

Japonês , 17 16 bytes

f".:*" ñ_iZw vÃq

Teste online!

Como funciona

Digamos que a sequência de entrada seja v:vg::G:G::o:. A primeira parte do código, f".:*"localiza todas as correspondências do regex /.:*/g, que corresponde a um caractere seguido por qualquer número de dois pontos. Isso divide a entrada em[v:, v, g::, G:, G::, o:].

O ñmétodo em uma matriz classifica cada matriz como se determinadas alterações fossem aplicadas, sem realmente aplicá-las (como sorted(array, key=<whatever>)no Python). Então, precisamos classificar:

  • dois pontos antes de tudo;
  • dois pontos depois de dois pontos, mas antes de dois pontos;
  • letras em sua ordem alfabética; e finalmente
  • letras maiúsculas antes de minúsculas.

Z{ZiZéJ v} é a maneira mais curta que eu poderia encontrar para fazer isso:

  Zw     Reverse Z.
     v   Convert to lowercase.
Zi       Insert this at the beginning of Z.

Isso é mais fácil de entender com alguns exemplos:

         v:   v  g::    G:   G::    o:
  Zw     :v   v  ::g    :G   ::G    :o
     v   :v   v  ::g    :g   ::g    :o
Zi       :vv: vv ::gg:: :gG: ::gG:: :oo:

Os valores originais são então classificados lexicograficamente por essas chaves. O resultado é que ::gG::é ordenado para a frente, ::gg::e assim por diante, fornecendo-nos o [G::, g::, G:, o:, v:, v]que é então unido qe produzido.

ETHproductions
fonte
1

JavaScript (ES6), 93 bytes

f=
s=>s.match(/\w:*/g).sort((a,b)=>b.length-a.length||parseInt(a,36)-parseInt(b,36)||a>b).join``
<input oninput=o.textContent=this.value&&f(this.value)><pre id=o>

Neil
fonte
1

Perl 5 , 69 + 1 ( -n) = 70 bytes

say sort{$b=~y///c<=>length$a||($"=lc$a)cmp lc$b||1-2*($"ne$a)}/.:*/g

Experimente online!

Xcali
fonte
Cada capital vem antes de sua letra minúscula. Por exemplo 'AaBb'. Eu acho que mudar =~/A-Z/para ==/A-Z/deve resolver o problema.
pizzapants184
1

Haskell , 124 bytes

import Data.List
import Data.Char
s(c:x)|(l,r)<-span(==':')x=(-length l,toLower c,c:l):s r;s _=[]
t(_,_,x)=x
f=(t=<<).sort.s

Experimente online!

user28667
fonte
1

Bash, 232 213 bytes

s(){ s=${1#?} c=${1%$s} o=${s%%[^:]*} s=${s#$o} o=$c$o;};
p()(s $1;l= g= p=$o d=$c;[[ $o ]]&&(while s $s;[[ $o ]];do
(((x=${#o}-${#p},y=36#$d-36#$c,x?x:y?y:62#$c-62#$d)>0))&&g+=$o||l+=$o;done;echo `p $g`$p`p $l`))

experimente online

Nahuel Fouilleul
fonte
1

C # (.NET Core) , 152 bytes

s=>{var o="";for(var d=":::";d!="";){d=d.Substring(1);for(var c='@';c!=90;o+=s.IndexOf(c+d)>=0?c+d:"",s=s.Replace(c+d,""),c^=' ')if(c<97)c++;}return o;}

Experimente online!

Ungolfed:

s => { 
    var o = ""; 
    for (var d = ":::"; d != "";) { 
        d = d.Substring(1); 
        for (
            var c = '@'; 
            c != 90; 
            o += s.IndexOf(c + d) >= 0 ? c + d : "", s = s.Replace(c + d, ""), c ^= ' '
        ) if (c < 97) c++; 
    } 
    return o; 
}

A idéia básica é iterar todas as 156 opções possíveis e verificar sua existência. Se encontrado, anexe à saída e remova-o da entrada.

recursivo
fonte