Genera scorciatoie da tastiera per un menu


10

Scorciatoie del menu

Tradizionalmente, i menu utente sono accessibili tramite scorciatoie da tastiera, come Alt + (a letter), o anche semplicemente colpire la lettera quando tutte le caselle di testo sono sfocate ( stile gmail ).

Il tuo compito

Considerate le voci di menu come input, il tuo compito è quello di assegnare a ciascuna voce di menu una lettera di scelta rapida appropriata.

Scrivi una funzione o un programma che accetta un insieme di parole: le voci di menu (come una matrice di stringhe o l'equivalente della tua lingua) e restituisce un dizionario o hashmap da una singola lettera a una voce di menu.

È possibile utilizzare un parametro e restituire un valore oppure utilizzare STDIN e inviare i risultati a STDOUT. Siete Non permesso di assumere una variabile globale / portata è già popolato con l'ingresso.

Algoritmo per determinare la lettera corretta

  • Fondamentalmente è la prima lettera disponibile della parola. Vedi ipotesi ed esempi di seguito.
  • Nel caso in cui tutte le lettere della voce non siano disponibili, il collegamento sarà (a letter) + (a number). La lettera che scegli dalla voce è arbitraria. Il numero dovrebbe iniziare da 0 ed essere incrementato di 1, in modo tale che tutte le scorciatoie siano univoche. Vedi il terzo esempio di seguito.

ipotesi

  • L'input sarà un Set, cioè nessuna ripetizione, ogni voce è unica.
  • La lunghezza dell'input può essere qualsiasi numero intero non negativo (fino a MAX_INT della tua lingua).
  • Distinzione tra maiuscole e minuscole: l'ingresso fa distinzione tra maiuscole e minuscole (ma rimarrà unico quando si ignora il caso). I risultati dovrebbero contenere le voci originali con il loro involucro originale. Tuttavia, le lettere di scelta rapida di output non fanno distinzione tra maiuscole e minuscole.
  • Tutte le parole di input non finiranno con i numeri.
  • Nessun "input malefico" verrà testato. "Input malefico" è tale che devi incrementare il contatore di una determinata lettera più di 10 volte.

Esempi

Gli esempi seguenti sono in JSON, ma puoi usare l'equivalente della tua lingua per un array e un dizionario o, nel caso in cui usi I / O STD, qualsiasi formato leggibile per i tuoi input e output (come csv, o anche space- valori separati).

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'}

Condizioni vincenti

Il codice più corto vince. È consentito solo ASCII.


"a" è già preso dalla prima voce. Quindi per "aa" poiché entrambe le sue lettere sono già occupate, ottiene a0. Lo stesso con b0-b2.
mattacolo

Cosa succede quando finisci i numeri?
nderscore,

@nderscore È davvero necessario?
Seequ,

Dovrebbe ['ab', 'a']dare {a:'ab', a0:'a'}o {b:'ab', a:'a'}?
Adám,

@ Adám sono entrambi accettabili. Sarebbe più semplice implementare il primo poiché si esegue la scansione dell'array di input in modo ordinato, ma se per qualche motivo si preferisce il secondo, procedere.
Jacob,

Risposte:


4

Javascript ( ES6 ) 106 105 100

Questa funzione accetta input come un array e genera un oggetto 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

risultati:

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"}

Ungolf / commentato:

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
}

Questo è bellissimo. Potrebbe non riuscire per l'input malvagio ['a', 'aa', 'aaa', 'aaaa', 'aaaaa', 'aaaaaa', 'aaaaaaa', 'aaaaaaaa', 'aaaaaaaaa', 'aaaaaaaaaa', 'aaaaaaaaaaa', 'aaaaaaaaaaaa'], ma penso che possiamo ignorare casi limite, vero?
Jacob,

@Jacob E cosa succede quando colpiamo 11? Non è possibile premere due volte un tasto in una scorciatoia da tastiera: P
nderscore

Hai un punto lì (anche se potrebbe essere possibile, data un'implementazione che attende fino alla fine dei tasti (circa 200 ms)). Ad ogni modo, aggiungerò alle ipotesi che nessun input malefico verrà testato.
Jacob,

2

Python 2.x - 176 170 157 114 byte

Approccio molto semplice, ma qualcuno deve dare il via al gioco.

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)

Esempi:

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'}

Penso che l'unica spiegazione richiesta sia il codice non golfato. (Questa in realtà è la versione originale)

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

Devo dire umile grazie a @Jacob. Il formato di input è semplicemente fantastico.
Seequ,

2

JavaScript (ECMAScript 6) - 107 caratteri

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)

Spiegazione:

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

test:

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"}

1

PHP> = 5,4 - 149 caratteri

Secondo gli standard di PHP (inserire qui gli snigger) , l'input non è JSON valido come utilizza 'invece di ", quindi sono stato un po 'sfacciato e sto usando l'input come una dichiarazione di variabile effettiva:

<?
$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);

Utilizzando gli esempi:

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"}

Non golfificato è piuttosto semplice:

<?
$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);

PHP ha dichiarazioni di salto? È così ... anni '90.
Seequ,

2
Non è necessario attenersi a JSON, ho fornito solo gli esempi in JSON, ma, come indicato nella domanda, è possibile scegliere qualsiasi formato leggibile per l'output o utilizzare l'equivalente della lingua per un dizionario. (Puoi salvare 13 caratteri rimuovendo l' json_encodeinvocazione).
Jacob,

echonon funziona con le matrici; ma print_r($c);lo farebbe, risparmiando 9 byte.
Tito

Ma questo non è insensibile alle maiuscole. str_split(strtoupper($w))e ucfirst($w[0])può risolverlo (+21); oppure $s=strtoupper($w);(+18)
Tito

1

PowerShell , 91 83 byte

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

Provalo online!

Genera un'eccezione se non viene trovato un collegamento corretto.

srotolato:

$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

0

PHP, 153 byte

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);

corri con php-r '<code>' <<EOF+ Invio + <word1>+ Invio + <word2>+ Invio + ... + EOF+ Invio

lavorando su argv per 155 byte :

$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);

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

(-13 byte con un globale definito: foreach($i as$w)anziché foreach($argv as$i=>$w)if($i))

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.