Golf Down the PPCG Nombres de usuario

32

Un comentario que hice en el chat y la conversación que siguió me inspiró a hacer este desafío.

¿Soy el único al que se refieren las iniciales por aquí? Estamos a punto de jugar al golf. Podemos tener MB y D-nob y ... O.

Si me conocen como "CH", entonces creo que todos los demás deberían tener un apodo inicial también.

Aquí hay una lista de los 100 mejores usuarios de Puzzles de programación y Code Golf por reputación para jugar:

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

( así es como lo conseguí )

Reto

Escriba un programa o función que tome una lista de cadenas y genere otra lista de cadenas de sus apodos mínimos, únicos y basados ​​en la inicial, dando preferencia a aquellos más cercanos al comienzo de la lista.

Aplique este método a cada cadena S en la lista en el orden dado para crear los apodos:

  1. Divide S en palabras separadas por espacios, eliminando todos los espacios en el proceso.
  2. Enumere los prefijos no vacíos de la cadena de las primeras letras de las palabras en S, de la más corta a la más larga.
    por ejemplo, Just Some NameJ, JS,JSN
  3. Elija el primer elemento de esta lista que no sea idéntico a un apodo ya elegido como el apodo para S. Deténgase si se eligió un apodo, de lo contrario continúe con el paso 4.
    por ejemplo, si Just Some Namefue la primera cadena, Jse garantiza que sea el apodo.
  4. Liste los prefijos nuevamente, pero esta vez incluya la segunda letra de la primera palabra en su lugar natural.
    por ejemplo, Just Some NameJu, JuS,JuSN
  5. Haga lo mismo que en el paso 3 para esta lista, deteniéndose si se encuentra un apodo único.
  6. Repita este proceso con las letras restantes de la primera palabra, eventualmente insertando letras en la segunda palabra, luego en la tercera, y así sucesivamente, hasta encontrar un apodo único.
    por ejemplo, la primera cadena exclusivo que se muestra aquí será el apodo:
    Jus, JusS, JusSN
    Just, JustS, JustSN
    Just, JustSo, JustSoN(nota de que ono se añadió después Just)
    Just, JustSom, JustSomN
    Just, JustSome, JustSomeN
    Just, JustSome, JustSomeNa
    Just, JustSome, JustSomeNam
    Just, JustSome,JustSomeName

Al final, todas las cadenas de entrada deben terminar con un apodo único (potencialmente idéntico a la cadena). Puede suponer que ninguna de las cadenas de entrada se asignará al mismo apodo utilizando este método.

Ejemplo

Actualizado para corregir mi error!

Para la 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

los apodos serían

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

Detalles

  • La entrada puede ser de un archivo (un nombre por línea), o un nombre a la vez a través de stdin / línea de comando, o como un argumento de función de una lista de cadenas, o como una función arg de una sola cadena con nuevas líneas entre los nombres.
  • La salida debe imprimirse en stdout (un apodo por línea) o la función debe devolverla como una lista de cadenas o como una cadena con nuevas líneas entre los apodos.
  • Idealmente, los programas funcionarán para nombres que contengan caracteres, excepto los terminadores de línea . Sin embargo, puede suponer que todos los nombres solo contienen ASCII imprimible . (Los nombres PPCG no lo hacen).
  • Solo el carácter de espacio regular cuenta como un separador de palabras. Los espacios iniciales y finales pueden ser ignorados.

Tanteo

La presentación más corta en bytes gana. Tiebreaker va a la respuesta publicada más temprano.

Pasatiempos de Calvin
fuente
49
Esto explica por qué me desperté en medio de la noche con esta vaga sensación de sentirse violado.
Martin Ender

Respuestas:

8

CJam, 58 53 bytes

Esto se puede jugar mucho golf .. Pero para empezar:

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

Expansión de 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";

Pruébalo en línea aquí

Optimizador
fuente
2
Vea mi comentario a OP: si 'Ju' o 'Jus' son apodos válidos para 'Just Some Name', 'Maertin Butter' debe ser 'Ma', luego 'MaB', 'Mar', 'MarB'.
edc65
Lo que @ edc65 dice es cierto. Lo siento por eso. Te permitiré no cambiar las cosas si quieres; fue mi error.
Hobbies de Calvin
9

JavaScript (ES6) 159

Siguiendo las especificaciones y no el ejemplo.

Genero los apodos candidatos que tienen una palabra media actual (al principio, la primera palabra). Las palabras antes de la corriente se usan 'tal cual'. Las palabras después de la actual contribuyen con no, o solo con el primer carácter. La palabra actual contribuye con 1 carácter más para cada ciclo.

Ejemplo 'Sólo un nombre' => 'Sólo', 'Algunas', 'Nombre'
Cw Just, posición 1, tratar J, JS, JSN
Cw Just, posición 2, tratar Ju, JuS, JuSN
Cw Just, posición 3, tratar Jus, JusS, JusSN
Cw Just, posición 4, tratar Just, JustS, JustSN
ahora Justse ha agotado , se Someconvierte en Cw, la posición se reinicia a 2 (para la posición 1, todo ya se intentó)

Cw Some, posición 2, prueba Just, JustSo, JustSoN
cw Some, posición 3, tratar Just, JustSom, JustSomN
cw Some, posición 4, tratar Just, JustSome, JustSomeN
ahora Someestá agotada, Namese convierte en cw, posición reinicia a 2

Cw Name, posición 2, prueba Just, JustSome, JustSomeNa
cw Name, posición 3, tratar Just, JustSome, JustSomeNam
cw Name, posición 4, tratar Just, JustSome, JustSomeName
Eso es todo amigos!

El código

(q es la posición actual de la palabra, p es la posición 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

Prueba en la consola 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 "]

edc65
fuente
2

PHP, 327 289 275 274 270

Todavía puede haber un pequeño potencial de golf.

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,'
';}
  • El programa funciona en stdin / stdout, funciona en ASCII, tiene errores en UTF
  • uso: php -d error_reporting=0 golfnicks.php < nicknames.txt
  • o cat <<EOF | php -d error_reporting=0 golfnicks.php+ lista de nombres +EOF
  • Para probar como función en el navegador web: busque el desglose, descomente todas las líneas marcadas con // FUNCy comente la marcada con //PROG. Tratarf(array_fill(0,21,'Just Some Name'));

Descompostura

#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
Titus
fuente