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


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
}

Это прекрасно. Это может не сработать из-за зла ['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

Я должен сказать скромное спасибо @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"}

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

В 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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.