Generuj skróty klawiaturowe dla menu

10

Skróty menu

Tradycyjnie menu użytkownika są dostępne za pomocą skrótów klawiaturowych, takich jak Alt + (a letter), a nawet po prostu naciśnięcie litery, gdy wszystkie pola tekstowe są nieaktywne ( styl Gmaila ).

Twoje zadanie

Biorąc pod uwagę pozycje menu jako dane wejściowe, Twoim zadaniem jest nadanie każdej pozycji menu odpowiedniej litery skrótu.

Napisz funkcję lub program, który akceptuje zestaw słów - pozycje menu (jako tablicę ciągów lub odpowiednik języka) i zwraca słownik lub skrót od jednej litery do pozycji menu.

Możesz albo użyć parametru i zwrócić wartość, albo użyć STDIN i wyprowadzić wyniki do STDOUT. Teraz nie wolno zakładać zmienną globalną / zakres jest już wypełniona wejścia.

Algorytm określający właściwą literę

  • Zasadniczo jest to pierwsza dostępna litera tego słowa. Zobacz założenia i przykłady poniżej.
  • W przypadku, gdy wszystkie litery wpisów nie są dostępne, skrót będzie (a letter) + (a number). Która litera, którą wybierzesz z wpisu, jest dowolna. Liczba powinna zaczynać się od 0 i być zwiększana o 1 - tak, aby wszystkie skróty były unikalne. Zobacz trzeci przykład poniżej.

Założenia

  • Wejście będzie zbiorem, tzn. Bez powtórzeń, każdy wpis jest unikalny.
  • Długość wejścia może być dowolną nieujemną liczbą całkowitą (do MAX_INT twojego języka).
  • Rozróżnianie wielkości liter: w danych wejściowych rozróżniana jest wielkość liter, (ale pozostanie unikalna, gdy ignoruje wielkość liter). Wyniki powinny zawierać oryginalne wpisy w oryginalnej obudowie. Jednak w wyjściowych literach skrótów nie jest rozróżniana wielkość liter.
  • Wszystkie wprowadzone słowa nie kończą się cyframi.
  • Żadne „złe wejście” nie będzie testowane. „Złe wejście” powoduje, że musisz zwiększyć licznik pewnej litery więcej niż 10 razy.

Przykłady

Poniższe przykłady są w języku JSON, ale możesz użyć swojego odpowiednika językowego dla tablicy i słownika lub - w przypadku korzystania ze STD I / O - dowolnego czytelnego formatu dla danych wejściowych i wyjściowych (np. Csv, a nawet spacja- wartości rozdzielone).

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

Warunki wygranej

Najkrótszy kod wygrywa. Dozwolone jest tylko ASCII.

Jakub
źródło
„a” jest już zajęty przez pierwszy wpis. Tak więc dla „aa”, ponieważ obie litery są już zajęte, dostaje a0. To samo z b0-b2.
mattacular
Co się stanie, gdy zabraknie numerów?
nderscore
@nderscore Czy to naprawdę konieczne?
patrz
Powinien ['ab', 'a']dać {a:'ab', a0:'a'}lub {b:'ab', a:'a'}?
Adám
@ Adám oba są dopuszczalne. Byłoby łatwiej zaimplementować to pierwsze, ponieważ skanujesz tablicę wejściową w uporządkowany sposób, ale jeśli z jakiegoś powodu wolisz ten drugi - skorzystaj z niego.
Jacob

Odpowiedzi:

4

JavaScript ( ES6 ) 106 105 100

Ta funkcja przyjmuje dane wejściowe jako tablicę i generuje obiekt 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

Wyniki:

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

Niegolfowane / komentowane:

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
źródło
To jest piękne. Może się nie powieść w przypadku złego wkładu ['a', 'aa', 'aaa', 'aaaa', 'aaaaa', 'aaaaaa', 'aaaaaaa', 'aaaaaaaa', 'aaaaaaaaa', 'aaaaaaaaaa', 'aaaaaaaaaaa', 'aaaaaaaaaaaa'], ale myślę, że możemy zignorować takie przypadki skrajne, prawda?
Jacob
@Jacob A co się stanie, kiedy uderzymy 11? Nie można nacisnąć tego klawisza dwa razy w skrócie klawiaturowym: P
nderscore
Masz rację (choć może być to możliwe, biorąc pod uwagę implementację, która czeka do końca naciśnięcia klawisza (około 200 ms)). W każdym razie dodam do założeń, że żaden taki zły wkład nie zostanie przetestowany.
Jacob
2

Python 2.x - 176 170 157 114 bajtów

Bardzo proste podejście, ale ktoś musi zacząć grę.

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)

Przykłady:

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

Wydaje mi się, że jedynym wymaganym wyjaśnieniem jest niepoznany kod. (To faktycznie jest oryginalna wersja)

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
patrz
źródło
Muszę powiedzieć pokornie dziękuję @Jacob. Format wejściowy jest po prostu świetny.
patrz
2

JavaScript (ECMAScript 6) - 107 znaków

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)

Wyjaśnienie:

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

Testy:

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
źródło
1

PHP> = 5,4 - 149 znaków

Zgodnie ze standardami PHP (wstaw tutaj sniggery) , dane wejściowe nie są poprawne JSON, ponieważ są używane 'zamiast ", więc byłem trochę bezczelny i używam Input jako rzeczywistej deklaracji zmiennej:

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

Korzystając z przykładów:

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

Bez golfa jest to dość podstawowe:

<?
$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
źródło
PHP ma deklaracje skoku? To takie ... lata 90-te.
patrz
2
Nie musisz trzymać się JSON, podałem tylko przykłady w JSON, ale, jak stwierdzono w pytaniu, możesz wybrać dowolny czytelny format wyjściowy lub użyć swojego odpowiednika językowego dla słownika. (Możesz zapisać 13 znaków, usuwając json_encodewywołanie).
Jacob
echonie działa z tablicami; ale print_r($c);zrobiłby to, oszczędzając 9 bajtów.
Tytus
Ale to nie jest bez znaczenia wielkość liter. str_split(strtoupper($w))i ucfirst($w[0])może rozwiązać ten problem (+21); lub $s=strtoupper($w);(+18)
Tytus
1

PowerShell , 91 83 bajtów

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

Wypróbuj online!

Zgłasza wyjątek, jeśli nie znaleziono odpowiedniego skrótu.

Rozwinięty:

$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
źródło
0

PHP, 153 bajty

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

uruchom z php-r '<code>' <<EOF+ Enter + <word1>+ Enter + <word2>+ Enter + ... + EOF+ Enter

praca na argv dla 155 bajtów :

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

Biegnij z php -r '<code>' <word1> <word2> ...

(-13 bajtów ze zdefiniowanym globalnym: foreach($i as$w)zamiast foreach($argv as$i=>$w)if($i))

Tytus
źródło