Генерация сочетаний клавиш для меню

10

Ярлыки меню

Традиционно, пользовательские меню доступны с помощью сочетаний клавиш, таких как Alt + (a letter)или даже простое нажатие на букву, когда все текстовые поля не сфокусированы ( стиль gmail ).

Твое задание

С учетом пунктов меню в качестве входных данных ваша задача состоит в том, чтобы назначить каждой записи меню правильную комбинацию букв.

Напишите функцию или программу, которая принимает набор слов - записи меню (в виде массива строк или вашего языкового эквивалента) и возвращает словарь или хэш-карту из одной буквы в элемент меню.

Вы можете либо использовать параметр и вернуть значение, либо использовать STDIN и вывести свои результаты в STDOUT. Вы не можете предполагать, что глобальная переменная / область видимости уже заполнена вводом.

Алгоритм определения правильного письма

  • По сути это первая доступная буква слова. Смотрите предположения и примеры ниже.
  • В случае, если все буквы ввода не доступны, ярлык будет (a letter) + (a number). Какое письмо вы выбираете из записи - произвольное. Число должно начинаться с 0 и увеличиваться на 1, чтобы все ярлыки были уникальными. Смотрите третий пример ниже.

Предположения

  • На входе будет Set, то есть без повторов, каждая запись уникальна.
  • Длина ввода может быть любым неотрицательным целым числом (до MAX_INT вашего языка).
  • Чувствительность к регистру: ввод чувствителен к регистру (но при игнорировании регистра будет оставаться уникальным). Результаты должны содержать исходные записи с оригинальным регистром. Однако выходные ярлыки не чувствительны к регистру.
  • Все вводимые слова не будут заканчиваться цифрами.
  • Никакой «злой вклад» не будет проверен. «Злой ввод» таков, что вам нужно увеличить счетчик определенной буквы более чем в 10 раз.

Примеры

Приведенные ниже примеры приведены в формате JSON, но вы можете использовать свой языковой эквивалент для массива и словаря или - в случае использования ввода-вывода STD - любой читаемый формат для ввода и вывода (например, csv или даже пробел). разделенные значения).

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

Условия выигрыша

Самый короткий код выигрывает. Разрешен только ASCII.

Иаков
источник
«а» уже занято первой записью. Таким образом, для «аа», поскольку обе его буквы уже заняты, он получает а0. То же самое с b0-b2.
Mattacular
Что происходит, когда у вас заканчиваются номера?
nderscore
@nderscore Это действительно необходимо?
seequ
Должен ['ab', 'a']дать {a:'ab', a0:'a'}или {b:'ab', a:'a'}?
адам
@ Adám оба приемлемы. Было бы проще реализовать первое, так как вы сканируете входной массив упорядоченным образом, но если по какой-то причине вы предпочитаете второе - сделайте это.
Джейкоб

Ответы:

4

Javascript ( ES6 ) 106 105 100

Эта функция принимает входные данные в виде массива и выводит объект 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

Результаты:

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

Ungolfed / прокомментировал:

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
источник
Это прекрасно. Это может не сработать из-за зла ['a', 'aa', 'aaa', 'aaaa', 'aaaaa', 'aaaaaa', 'aaaaaaa', 'aaaaaaaa', 'aaaaaaaaa', 'aaaaaaaaaa', 'aaaaaaaaaaa', 'aaaaaaaaaaaa'], но я думаю, что мы можем игнорировать такие крайние случаи, не так ли?
Джейкоб
@Jacob А что будет, когда мы ударим 11? Вы не можете нажать одну клавишу дважды в сочетаниях клавиш: P
nderscore
У вас есть точка (хотя это возможно, учитывая реализацию, которая ожидает до конца нажатия клавиш (200 мс или около того)). В любом случае, я добавлю к предположениям, что такой злой вклад не будет проверен.
Джейкоб
2

Python 2.x - 176 170 157 114 байт

Очень простой подход, но кто-то должен начать игру.

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)

Примеры:

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

Я думаю, что единственное обязательное объяснение - это код без правил. (Это на самом деле оригинальная версия)

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
источник
Я должен сказать скромное спасибо @Jacob. Формат ввода просто великолепен.
seequ
2

JavaScript (ECMAScript 6) - 107 символов

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)

Объяснение:

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

тесты:

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
источник
1

PHP> = 5,4 - 149 символов

В соответствии со стандартами PHP (здесь вставьте фрагмент кода) ввод не является допустимым JSON, поскольку он использует 'вместо него ", поэтому я был немного дерзким, и я использую Input как фактическое объявление переменной:

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

Используя примеры:

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

Без гольфа это довольно просто:

<?
$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
источник
В PHP есть объявления о переходе? Это так ... 90-х годов.
seequ
2
Вам не нужно придерживаться JSON, я предоставил только примеры в JSON, но, как указано в вопросе, вы можете выбрать любой читаемый формат для вывода или использовать свой языковой эквивалент для словаря. (Вы можете сохранить 13 символов, удалив json_encodeвызов).
Джейкоб
echoне работает с массивами; но print_r($c);сделал бы это, сэкономив 9 байтов.
Титус
Но это не чувствительно к регистру. str_split(strtoupper($w))и ucfirst($w[0])может решить это (+21); или $s=strtoupper($w);(+18)
Титус
1

PowerShell , 91 83 байта

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

Попробуйте онлайн!

Выдает исключение, если правильный ярлык не найден.

раскатали:

$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
источник
0

PHP, 153 байта

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

запустить с помощью php-r '<code>' <<EOF+ Enter + <word1>+ Enter + <word2>+ Enter + ... + EOF+ Enter

работает над argv для 155 байтов :

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

бежать с php -r '<code>' <word1> <word2> ...

(-13 байт с определенным глобальным: foreach($i as$w)вместо foreach($argv as$i=>$w)if($i))

Titus
источник