Golfe nos nomes de usuário do PPCG


32

Um comentário que fiz no bate - papo e a conversa que se seguiu me inspiraram a fazer esse desafio.

Eu sou o único referido pelas iniciais por aqui? Temos tudo a ver com o golfe. Podemos ter MB e D-nob e ... O.

Se eu sou conhecido como "CH", acho que todo mundo deveria ter um apelido inicial também.

Aqui está uma lista dos 100 principais usuários de Puzzles de programação e código Golf por reputação para jogar:

Martin Büttner
Doorknob
Peter Taylor
Howard
marinus
Dennis
DigitalTrauma
David Carraher
primo
squeamish ossifrage
Keith Randall
Ilmari Karonen
Quincunx
Optimizer
grc
Calvin's Hobbies
ugoren
Mig
gnibbler
Sp3000
aditsu
histocrat
Ventero
xnor
mniip
Geobits
J B
Joe Z.
Gareth
Jan Dvorak
isaacg
edc65
Victor
steveverrill
feersum
ace
Danko Durbić
xfix
PhiNotPi
user23013
manatwork
es1024
Joey
daniero
boothby
nneonneo
Joey Adams
Timwi
FireFly
dansalmo
grovesNL
breadbox
Timtech
Flonk
algorithmshark
Johannes Kuhn
Yimin Rong
copy
belisarius
professorfish
Ypnypn
trichoplax
Darren Stone
Riot
ProgramFOX
TheDoctor
swish
minitech
Jason C
Tobia
Falko
PleaseStand
VisioN
leftaroundabout
alephalpha
FUZxxl
Peter Olson
Eelvex
marcog
MichaelT
w0lf
Ell
Kyle Kanos
qwr
flawr
James_pic
MtnViewMark
cjfaure
hammar
bitpwner
Heiko Oberdiek
proud haskeller
dan04
plannapus
Mr Lister
randomra
AShelly
ɐɔıʇǝɥʇuʎs
Alexandru
user unknown

( é assim que eu entendi )

Desafio

Escreva um programa ou função que inclua uma lista de cadeias e produza outra lista de cadeias com seus apelidos mínimos, únicos e baseados em iniciais, dando preferência àqueles mais próximos do início da lista.

Aplique este método a cada sequência S na lista na ordem fornecida para criar os apelidos:

  1. Divida S em palavras separadas por espaços, removendo todos os espaços no processo.
  2. Liste os prefixos não vazios da sequência das primeiras letras das palavras em S, do menor para o maior.
    por exemplo Just Some NameJ, JS,JSN
  3. Escolha o primeiro item nesta lista que não é idêntico a um apelido já escolhido como o apelido de S. Pare se um apelido foi escolhido, continue na etapa 4 caso contrário.
    por exemplo, se Just Some Namefoi a primeira string, Jé garantido que seja o apelido.
  4. Liste os prefixos novamente, mas desta vez inclua a segunda letra da primeira palavra em seu local natural.
    por exemplo Just Some NameJu, JuS,JuSN
  5. Faça o mesmo que na etapa 3 desta lista, parando se um apelido exclusivo for encontrado.
  6. Repita esse processo com as letras restantes da primeira palavra, eventualmente inserindo letras na segunda palavra, depois na terceira e assim por diante, até que um apelido exclusivo seja encontrado.
    eg A primeira cadeia exclusiva aqui será o apelido:
    Jus, JusS, JusSN
    Just, JustS, JustSN
    Just, JustSo, JustSoN(note que onão foi adicionado depois Just)
    Just, JustSom, JustSomN
    Just, JustSome, JustSomeN
    Just, JustSome, JustSomeNa
    Just, JustSome, JustSomeNam
    Just, JustSome,JustSomeName

No final, todas as seqüências de entrada devem terminar com um apelido exclusivo (potencialmente idêntico à sequência). Você pode assumir que nenhuma das seqüências de entrada será mapeada para o mesmo apelido usando este método.

Exemplo

Atualizado para corrigir meu erro!

Para a entrada

Martin Buttner
Doorknob
Peter Taylor
Howard
marinus
Dennis
DigitalTrauma
David Carraher
Martin Bitter
Martin Butter
Martin Battle
Martini Beer
Mart Beer
Mars Bar
Mars Barn

os apelidos seriam

M
D
P
H
m
De
Di
DC
MB
Ma
MaB
Mar
MarB
Mars
MarsB

Detalhes

  • A entrada pode ser de um arquivo (um nome por linha), ou um nome por vez, via stdin / linha de comando, ou como argumento de função de uma lista de cadeias, ou como argumento de função de uma única cadeia com novas linhas entre nomes.
  • A saída deve ser impressa em stdout (um apelido por linha) ou retornada pela função como uma lista de cadeias ou como uma cadeia com novas linhas entre os apelidos.
  • O ideal é que os programas funcionem para nomes que contenham caracteres, exceto os terminadores de linha . No entanto, você pode assumir que todos os nomes contêm apenas ASCII imprimível . (Os nomes do PPCG não.)
  • Somente o caractere de espaço regular conta como um separador de palavras. Os espaços iniciais e finais podem ser ignorados.

Pontuação

O menor envio em bytes vence. O desempatador vai para a resposta postada mais cedo.


49
Isso explica por que acordei no meio da noite com essa vaga sensação de me sentir violado.
Martin Ender

Respostas:


8

CJam, 58 53 bytes

Isso pode ser muito praticado. Mas para iniciantes:

LqN/{:Q1<aQ,,:)QS/f{{1$<_,@-z1e>}%W<s}+{a1$&!}=a+}/N*

Expansão do código :

L                         "Put an empty array on stack. This is the final nickname array";
 qN/{  ...   }/           "Read the input and split it on new lines. Run the block for each";
     :Q1<a                "Store each name in Q and get its first char. Wrap it in an array";
          Q,,:)           "Get an array of 1 to length(name) integers";
               QS/        "Split the name on spaces";
f{{           }%   }      "for each of the integer in the array, run the code block";
                          "and then for each of the name part, run the inner code block";
   1$<                    "Copy the integer, take first that many characters from the";
                          "first part of the name";
      _,@-z1e>            "Get the actual length of the part and the number of characters";
                          "to be taken from the next name part, minimum being 1";
                W<        "Get rid of the last integer which equals 1";
                  s       "Concat all name parts in the array";
                    +     "Add the list of nick names as per spec with the first character";
{     }=                  "Get the first nick name that matches the criteria";
 a1$&                     "Wrap the nick name in an array and do set intersection with";
                          "the copy of existing nick names";
     !                    "Choose this nick name if the intersection is empty";
N*                        "After the { ... }/ for loop, the stack contains the final";
                          "nick names array. Print it separated with new lines";

Experimente online aqui


2
Veja meu comentário ao OP: se 'Ju' ou 'Jus' são apelidos válidos para 'Just Some Name', 'Maertin Butter' deve ser 'Ma', depois 'MaB', 'Mar', 'MarB'.
Edc65

O que @ edc65 diz é verdade. Me desculpe por isso. Permitirei que você não mude as coisas, se quiser; foi erro meu.
Hobbies de Calvin

9

JavaScript (ES6) 159

Seguindo as especificações e não o exemplo.

Gero os apelidos candidatos com uma palavra do meio atual (no início, a primeira palavra). As palavras antes da corrente são usadas 'como estão'. As palavras depois da corrente contribuem com nenhum - ou apenas o primeiro - caractere. A palavra atual contribui com mais 1 caractere para cada loop.

Exemplo 'Just Alguns Name' => 'Apenas', 'Some', 'Nome'
Cw Just, posição 1, tente J, JS, JSN
Cw Just, posição 2, tente Ju, JuS, JuSN
Cw Just, posição 3, tente Jus, JusS, JusSN
Cw Just, posição 4, tente Just, JustS, JustSN
agora Justestá esgotado , Sometorna-se Cw, posição reiniciada para 2 (para a posição 1, todas já experimentadas)

Cw Some, posição 2, tentativa Just, JustSo, JustSoN
cw Some, posição 3, tente Just, JustSom, JustSomN
cw Some, posição 4, tente Just, JustSome, JustSomeN
agora Someestá esgotado, Nametorna-se cw, posição reiniciado para 2

Cw Name, posição 2, tentativa Just, JustSome, JustSomeNa
cw Name, posição 3, tente Just, JustSome, JustSomeNam
cw Name, posição 4, tente Just, JustSome, JustSomeName
Isso é tudo pessoal!

O código

(q é a posição atual da palavra, p é a posição de corte)

F=l=>
  l.map(w=>{ 
    for(w=w.match(/[^ ]+/g),q=p=0;
        w.every((w,i)=>~o.indexOf(t+=i<q?w:i>q?w[0]:w.slice(0,p+1)),t='')
        &&(w[q][p++]||(p=1,w[++q]));
       );
    o.push(t)
  },o=[])&&o

Teste no console Firefox / FireBug

F(['Martin Buttner','Doorknob','Peter Taylor','Howard','marinus'
  ,'Dennis','DigitalTrauma','David Carraher'
  ,'Martin Bitter','Martin Butter','Martin Battle','Martini Beer','Mart Beer'])

["M", "D", "P", "H", "m", "De", "Di", "DC", "MB", "Ma", "MaB", "Mar", " MarB "]


2

PHP, 327 289 275 274 270

Ainda pode haver um pequeno potencial de golfe.

while($n=fgets(STDIN)){$c=count($w=preg_split('/\s+/',trim($n)));$p=[];for($k=0;$k<$c;$p[$k]++){for($t='',$j=0;$j<$c;$j++)$t.=substr($w[$j],0,$p[$j]+1);for($j=1;$j<=strlen($t);$j++)if(!in_array($v=substr($t,0,$j),$u))break 2;$k+=$p[$k]==strlen($w[$k]);}echo$u[]=$v,'
';}
  • O programa opera em stdin / stdout, funciona em ASCII, buggy em UTF
  • uso: php -d error_reporting=0 golfnicks.php < nicknames.txt
  • ou cat <<EOF | php -d error_reporting=0 golfnicks.php+ lista de nomes +EOF
  • Para testar como função no navegador da web: busque o detalhamento, remova o comentário de todas as linhas marcadas com // FUNCe comente a linha marcada //PROG. Experimentarf(array_fill(0,21,'Just Some Name'));

demolir

#error_reporting(0);function f($a){echo'<pre>'; // FUNC
#foreach($a as$n) // FUNC
while($n=fgets(STDIN)) // PROG
{
    $c=count($w=preg_split('/\s+/',trim($n)));     // split name to words, count them
    $p=[];                                         // initialize cursors
    for($k=0;$k<$c;$p[$k]++)
    {
        for($t='',$j=0;$j<$c;$j++)$t.=substr($w[$j],0,$p[$j]+1); // concatenate prefixes
        for($j=1;$j<=strlen($t);$j++)              // loop through possible nicks
            if(!in_array($v=substr($t,0,$j),$u))   // unused nick found
                break 2;                           // -> break cursor loop
        $k+=$p[$k]==strlen($w[$k]);                // if Cw exhausted -> next word
        // strlen()-1 would be correct; but this works too)
    }
    echo$u[]=$v,'
';
}
#echo '</pre>';} // FUNC
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.