Generar atajos de teclado para un menú.

10

Atajos de menú

Tradicionalmente, se puede acceder a los menús de los usuarios mediante métodos abreviados de teclado, como Alt + (a letter)simplemente presionar la letra cuando todos los cuadros de texto están desenfocados ( estilo gmail ).

Tu tarea

Dadas las entradas del menú como entrada, su tarea es otorgar a cada entrada del menú una letra de acceso directo adecuada.

Escriba una función o un programa que acepte un conjunto de palabras: las entradas del menú (como una matriz de cadenas, o su equivalente en el idioma), y devuelve un diccionario o un hashmap, de una sola letra a una entrada del menú.

Puede usar un parámetro y devolver un valor, o usar el STDIN y enviar sus resultados a STDOUT. Usted está no permite asumir una variable global / alcance ya está poblada con la entrada.

Algoritmo para determinar la letra correcta

  • Básicamente es la primera letra disponible de la palabra. Ver supuestos y ejemplos a continuación.
  • En caso de que todas las letras de la entrada no estén disponibles, el acceso directo sí lo estará (a letter) + (a number). La letra que eliges de la entrada es arbitraria. El número debe comenzar desde 0 e incrementarse en 1, de modo que todos los accesos directos sean únicos. Ver tercer ejemplo a continuación.

Supuestos

  • La entrada será un conjunto, es decir, sin repeticiones, cada entrada es única.
  • La longitud de la entrada puede ser cualquier número entero no negativo (hasta MAX_INT de su idioma).
  • Sensibilidad a mayúsculas y minúsculas: la entrada distingue mayúsculas de minúsculas (pero se mantendrá única al ignorar mayúsculas y minúsculas) Los resultados deben contener las entradas originales con su carcasa original. Sin embargo, las letras de acceso directo de salida no distinguen entre mayúsculas y minúsculas.
  • Todas las palabras de entrada no terminarán con números.
  • No se probará ninguna "entrada malvada". La "entrada malvada" es tal que debe incrementar el contador de una letra determinada más de 10 veces.

Ejemplos

Los ejemplos a continuación están en JSON, pero puede usar su equivalente de idioma para una matriz y un Diccionario, o, en caso de que esté usando E / S STD, cualquier formato legible para su entrada y salida (como csv, o incluso espacio- valores separados).

1)

Input:  ['File', 'Edit', 'View', 'Help']
Output: {f:'File', e:'Edit', v:'View', h:'Help'}

2)

Input:  ['Foo', 'Bar', 'FooBar', 'FooBars']
Output: {f:'Foo', b:'Bar', o:'FooBar', a:'FooBars'}

3)

Input:  ['a', 'b', 'aa', 'bb', 'bbq', 'bbb', 'ba']
Output: {a:'a', b:'b', a0:'aa', b0:'bb', q:'bbq', b1:'bbb', b2:'ba'}

Condiciones ganadoras

El código más corto gana. Solo se permite ASCII.

Jacob
fuente
"a" ya está en la primera entrada. Entonces, para "aa" ya que sus dos letras ya están ocupadas, obtiene a0. Lo mismo con b0-b2.
mattacular
¿Qué pasa cuando te quedas sin números?
nderscore
@nderscore ¿Es eso realmente necesario?
seequ
Debe ['ab', 'a']dar {a:'ab', a0:'a'}o {b:'ab', a:'a'}?
Adám
@ Adám ambos son aceptables. Sería más fácil implementar el primero ya que escanea la matriz de entrada de manera ordenada, pero si por alguna razón prefiere el último, hágalo.
Jacob

Respuestas:

4

Javascript ( ES6 ) 106 105 100

Esta función toma la entrada como una matriz y genera un objeto javascript.

f=i=>i.map(a=>{for(b of c=a.toLowerCase(d=0)+d+123456789)d<!o[e=b>=0?c[0]+b:b]&&(o[d=e]=a)},o={})&&o

Resultados:

f(['File', 'Edit', 'View', 'Help']);
// {"f":"File","e":"Edit","v":"View","h":"Help"}

f(['Foo', 'Bar', 'FooBar', 'FooBars']);
// {"f":"Foo","b":"Bar","o":"FooBar","a":"FooBars"}

f(['a', 'b', 'aa', 'bb', 'bbq', 'bbb', 'ba']);
// {"a":"a","b":"b","a0":"aa","b0":"bb","q":"bbq","b1":"bbb","b2":"ba"}

Sin golf / comentado:

f=i=>{
  o={};                                        // initialize an object for output
  i.map(a=>                                    // loop through all values in input
    for(b of c=a.toLowerCase(d=0)+d+123456789) // loop through all characters of the string with 0123456789 appended to the end
                                               // and initialize d as 0 to be used as a flag 
      e=b>=0?c[0]+b:b                          // if b is a number, set e to the first character + the number, otherwise b
      if(d<!o[e])                              // if the flag hasn't been triggered and o doesn't have a property e
        o[d=e]=a                               // then store the value at e and trigger the d flag
  )
  return o                                     // return the output object
}
nderscore
fuente
Esto es hermoso. Puede fallar por la entrada malvada ['a', 'aa', 'aaa', 'aaaa', 'aaaaa', 'aaaaaa', 'aaaaaaa', 'aaaaaaaa', 'aaaaaaaaa', 'aaaaaaaaaa', 'aaaaaaaaaaa', 'aaaaaaaaaaaa'], pero creo que podemos ignorar estos casos extremos, ¿no?
Jacob
@Jacob ¿Y qué pasa cuando golpeamos 11? No puede presionar una tecla dos veces en un método abreviado de teclado: P
nderscore
Tiene un punto allí (aunque podría ser posible, dada una implementación que espera hasta el final de las pulsaciones de teclas (más de 200 ms)). De todos modos, agregaré a las suposiciones que no se probará dicha entrada malvada.
Jacob
2

Python 2.x - 176170157114 bytes

Enfoque muy simple, pero alguien tiene que patear el juego.

r={}
for i in input():a=list(i.upper());r[([c for c in a+[a[0]+`x`for x in range(10)]if c not in r])[0]]=i
print r

Edit 1: Reversed the checking operation and made it set the result only once.
Edit 2: Removed branching.
Edit 3: Removed unnecessary dictionary. (thanks to the added assumption)

Ejemplos:

Input:  ['File', 'Edit', 'View', 'Help']
Output: {'H': 'Help', 'V': 'View', 'E': 'Edit', 'F': 'File'}

Input:  ['Foo', 'Bar', 'FooBar', 'FooBars']
Output: {'A': 'FooBars', 'B': 'Bar', 'O': 'FooBar', 'F': 'Foo'}

Input:  ['a', 'b', 'aa', 'bb', 'bbq', 'bbb', 'ba']
Output: {'A': 'a', 'B': 'b', 'Q': 'bbq', 'A0': 'aa', 'B0': 'bb', 'B1': 'bbb', 'B2': 'ba'}

Creo que la única explicación requerida es el código sin golf. (Esta es realmente la versión original)

items = input() # ['File', 'Edit', 'View', 'Help']
chars = map(chr,range(65,91))
numbers = {}.fromkeys(chars,0)
result = {}
for item in items:
    try:
        key = [c for c in item.upper() if c in chars][0] # causes an exception when no items match
        result[key] = item
        chars.remove(key)
    except:
        key = item[0].upper()
        result[key+`numbers[key]`] = item
        numbers[key] += 1
print result
seequ
fuente
Tengo que decir humilde gracias a @Jacob. El formato de entrada es simplemente genial.
seequ
2

JavaScript (ECMAScript 6) - 107 caracteres

f=a=>(o={},p={},[o[[c for(c of l=w.toLowerCase())if(!o[c])][0]||(k=l[0])+(p[k]=p[k]+1|0)]=w for(w of a)],o)

Explicación:

f=a=>(
  o={},                              // The dictionary to output
  p={},                              // Stores record of numbers appended after duplicate
                                     // menu keys
  [                                  // Use array comprehension for each word w of input a
   (unmatchedCharacters
     =[c                             // Use array comprehension for each character c of
      for(c of l=w.toLowerCase())    //   the lower case of word w but only get
      if(!o[c])                      //   those characters which are not already a key in o.
     ],
    key=unmatchedCharacters[0]       // Take the first of those characters
     ||                              // Or if all characters are already in o
     (k=l[0])                        // Take the first character of the lower-case word
     +(p[k]=p[k]+1|0),               //   concatenated with the increment of the digit stored
                                     //   in p (or zero). 
   o[key]=w)                         // Set o to map from this key to the word
   for(w of a)
  ],
  o)                                 // return o

Pruebas:

f(['File', 'Edit', 'View', 'Help']);
{f: "File", e: "Edit", v: "View", h: "Help"}

f(['Foo', 'Bar', 'FooBar', 'FooBars']);
{f: "Foo", b: "Bar", o: "FooBar", a: "FooBars"}

f(['a', 'b', 'aa', 'bb', 'bbq', 'bbb', 'ba']);
{a: "a", b: "b", a0: "aa", b0: "bb", q: "bbq", b1: "bbb", b2: "ba"}
MT0
fuente
1

PHP> = 5.4 - 149 caracteres

De acuerdo con los estándares de PHP (inserte sniggers aquí) , la entrada no es JSON válida, ya que usa en 'lugar de ", así que he sido un poco descarado y estoy usando la entrada como una declaración de variable real:

<?
$i = ['a', 'b', 'aa', 'bb', 'bbq', 'bbb', 'ba'];
$c=[];foreach($i as$w){foreach(str_split($w) as$j)if(!$c[$j]){$x=$j;goto f;}$n=0;do{$x=$w[0].$n++;}while($c[$x]);f:$c[$x]=$w;}echo json_encode($c);

Usando los ejemplos:

Input:  ['File', 'Edit', 'View', 'Help']
Output: {"F":"File","E":"Edit","V":"View","H":"Help"}

Input:  ['Foo', 'Bar', 'FooBar', 'FooBars']
Output: {"F":"Foo","B":"Bar","o":"FooBar","a":"FooBars"}

Input:  ['a', 'b', 'aa', 'bb', 'bbq', 'bbb', 'ba']
Output: {"a":"a","b":"b","a0":"aa","b0":"bb","q":"bbq","b1":"bbb","b2":"ba"}

Sin golfificar es bastante básico:

<?
$i = ['a', 'b', 'aa', 'bb', 'bbq', 'bbb', 'ba'];
$c = [];
foreach($i as $w)
{
    foreach(str_split($w) as $j)
        if(!$c[$j])
        {
            $x = $j;
            goto f;
        }
    $n = 0;
    do
    {
        $x = $w[0] . $n++;
    }
    while($c[$x]);
    f: $c[$x] = $w;
}
echo json_encode($c);
MrLore
fuente
PHP tiene declaraciones de salto? Eso es tan ... de los 90.
seequ
2
No tiene que apegarse a JSON, solo proporcioné los ejemplos en JSON, pero, como se indica en la pregunta, puede elegir cualquier formato legible para la salida o usar su idioma equivalente para un Diccionario. (Puede guardar 13 caracteres eliminando la json_encodeinvocación).
Jacob
echono funciona con matrices; pero print_r($c);lo haría, ahorrando 9 bytes.
Tito
Pero esto no es insensible a mayúsculas y minúsculas. str_split(strtoupper($w))y ucfirst($w[0])puede resolver eso (+21); o $s=strtoupper($w);(+18)
Tito el
1

PowerShell , 91 83 bytes

$r=@{}
$args|%{$r[($_|% *wer|% t*y|%{$c=$_;,''+0..9|%{$c+$_}|?{!$r.$_}})[0]]=$_}
$r

Pruébalo en línea!

Lanza una excepción si no se encuentra un acceso directo adecuado.

Desenrollado:

$result=@{}
$args|%{
    $shortcuts = $_|% toLower|% toCharArray|%{
        $c=$_
        ,''+0..9|%{$c+$_}|?{!$result.$_}    # output shortcuts are not exist in the result
    }
    $properShortcut = $shortcuts[0]         # throws an exception if a proper shortcut not found
    $result[$properShortcut]=$_
}
$result
mazzy
fuente
0

PHP, 153 bytes

for($c=[];$w=trim(fgets(STDIN));$c[reset(array_diff(str_split($s),array_keys($c)))?:$y]=$w){$s=strtoupper($w);for($n=0;$c[$y=$s[0].$n++];);}print_r($c);

ejecutar con php-r '<code>' <<EOF+ Enter + <word1>+ Enter + <word2>+ Enter + ... + EOF+ Enter

trabajando en argv para 155 bytes :

$c=[];foreach($argv as$i=>$w)if($i){$s=strtoupper($w);for($n=0;$c[$y=$s[0].$n++];);$c[reset(array_diff(str_split($s),array_keys($c)))?:$y]=$w;}print_r($c);

corre con php -r '<code>' <word1> <word2> ...

(-13 bytes con un global definido: en foreach($i as$w)lugar de foreach($argv as$i=>$w)if($i))

Tito
fuente