Створення ярликів клавіатури для меню


10

Ярлики меню

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

Ваше завдання

Враховуючи записи меню як вхідні дані, ваше завдання - надати кожному запису меню відповідний короткий лист.

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

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

Алгоритм визначення правильної літери

  • В основному це перша доступна літера цього слова. Дивіться припущення та приклади нижче.
  • Якщо всі листи вхідні не доступні, це буде ярлик (a letter) + (a number). Який лист ви виберете із запису довільним. Число повинно починатися від 0 і збільшуватися на 1 - таким чином, щоб усі ярлики були унікальними. Дивіться третій приклад нижче.

Припущення

  • Вхід буде набором, тобто немає повторень, кожен запис унікальний.
  • Довжина вводу може бути будь-яким невід’ємним цілим числом (до MAX_INT вашої мови).
  • Чутливість до регістру: Вхідні дані залежать від регістру (але залишатимуться унікальними при ігноруванні регістру) Результати повинні містити оригінальні записи з оригінальним кожухом. Однак вихідні ярлики не відрізняються від регістру.
  • Усі введені слова не закінчуються цифрами.
  • Жоден "злий вклад" не буде перевірений. "Злий вхід" такий, що вам потрібно збільшити лічильник певної літери більше 10 разів.

Приклади

Приклади нижче наведені в JSON, але ви можете використовувати свій мовний еквівалент для масиву та словника, або - у випадку, якщо ви використовуєте STD I / O - будь-який читаний формат для введення та виводу (наприклад, 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.


"a" вже прийнято першим записом. Тож для "аа", оскільки обидва її листи вже прийняті, він отримує a0. Те саме з b0-b2.
матакулярний

Що відбувається, коли у вас закінчуються цифри?
nderscore

@nderscore Це дійсно потрібно?
seequ

Слід ['ab', 'a']дати {a:'ab', a0:'a'}чи {b:'ab', a:'a'}?
Adám

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

Безголів / Прокоментував:

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.