Générer des raccourcis clavier pour un menu


10

Raccourcis du menu

Traditionnellement, les menus utilisateur sont accessibles par des raccourcis clavier, tels que Alt + (a letter), ou même simplement en tapant la lettre lorsque toutes les zones de texte sont floues ( style gmail ).

Ta tâche

Étant donné les entrées de menu en entrée, votre tâche consiste à attribuer à chaque entrée de menu une lettre de raccourci appropriée.

Écrivez une fonction ou un programme qui accepte un ensemble de mots - les entrées de menu (sous forme de tableau de chaînes ou l'équivalent de votre langue) et renvoie un dictionnaire ou une table de hachage, d'une seule lettre à une entrée de menu.

Vous pouvez soit utiliser un paramètre et renvoyer une valeur, soit utiliser le STDIN et envoyer vos résultats à STDOUT. Vous n'êtes pas autorisé à supposer qu'une variable globale / portée est déjà remplie avec l'entrée.

Algorithme pour déterminer la bonne lettre

  • Fondamentalement, c'est la première lettre disponible du mot. Voir les hypothèses et exemples ci-dessous.
  • Si toutes les lettres de l'entrée ne sont pas disponibles, le raccourci sera (a letter) + (a number). La lettre que vous choisissez dans l'entrée est arbitraire. Le nombre doit commencer à 0 et être incrémenté de 1, de sorte que tous les raccourcis soient uniques. Voir le troisième exemple ci-dessous.

Hypothèses

  • L'entrée sera un ensemble, c'est-à-dire sans répétition, chaque entrée est unique.
  • La longueur de l'entrée peut être n'importe quel entier non négatif (jusqu'à MAX_INT de votre langue).
  • Sensibilité à la casse: L'entrée est sensible à la casse, (mais restera unique en ignorant la casse). Les résultats doivent contenir les entrées originales avec leur boîtier d'origine. Cependant, les lettres de raccourci de sortie ne sont pas sensibles à la casse.
  • Tous les mots saisis ne se termineront pas par des chiffres.
  • Aucune "mauvaise entrée" ne sera testée. "L'entrée du mal" est telle que vous devez incrémenter le compteur d'une certaine lettre plus de 10 fois.

Exemples

Les exemples ci-dessous sont en JSON, mais vous pouvez utiliser votre équivalent de langue pour un tableau et un dictionnaire, ou - dans le cas où vous utilisez des E / S STD - n'importe quel format lisible pour vos entrées et sorties (comme csv, ou même espace- valeurs séparées).

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

Conditions gagnantes

Le code le plus court gagne. Seul ASCII est autorisé.


"a" est déjà pris par la première entrée. Donc pour "aa" puisque ses deux lettres sont déjà occupées, il obtient a0. Idem avec b0-b2.
mattacular

Que se passe-t-il lorsque vous manquez de chiffres?
nderscore

@nderscore Est-ce vraiment nécessaire?
seequ

Devrait ['ab', 'a']donner {a:'ab', a0:'a'}ou {b:'ab', a:'a'}?
Adám

@ Adám les deux sont acceptables. Il serait plus facile de mettre en œuvre le premier puisque vous numérisez le tableau d'entrée de manière ordonnée, mais si pour une raison quelconque vous préférez le second, allez-y.
Jacob

Réponses:


4

Javascript ( ES6 ) 106 105 100

Cette fonction prend l'entrée comme un tableau et génère un objet 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

Résultats:

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

Non golfé / commenté:

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
}

C'est beau. Cela peut échouer pour la mauvaise entrée ['a', 'aa', 'aaa', 'aaaa', 'aaaaa', 'aaaaaa', 'aaaaaaa', 'aaaaaaaa', 'aaaaaaaaa', 'aaaaaaaaaa', 'aaaaaaaaaaa', 'aaaaaaaaaaaa'], mais je pense que nous pouvons ignorer ces cas extrêmes, n'est-ce pas?
Jacob

@Jacob Et que se passe-t-il lorsque nous frappons 11? Vous ne pouvez pas appuyer deux fois sur la même touche dans un raccourci clavier: P
nderscore

Vous avez un point là (bien que cela puisse être possible, étant donné une implémentation qui attend la fin des frappes (200 ms environ)). Quoi qu'il en soit, j'ajouterai aux hypothèses qu'aucune mauvaise entrée ne sera testée.
Jacob

2

Python 2.x - 176170157114 octets

Approche très simple, mais quelqu'un doit lancer le jeu.

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)

Exemples:

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

Je pense que la seule explication requise est le code non golfé. (Il s'agit en fait de la version 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

Je dois dire un humble merci à @Jacob. Le format d'entrée est tout simplement génial.
seequ

2

JavaScript (ECMAScript 6) - 107 caractères

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)

Explication:

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

Tests:

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 caractères

Selon les normes PHP (insérez des sniggers ici) , l'entrée n'est pas JSON valide car elle utilise à la 'place de ", donc j'ai été un peu effronté et j'utilise l'entrée comme une déclaration de variable réelle:

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

En utilisant les exemples:

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 golfifié, c'est assez basique:

<?
$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 a des déclarations de saut? C'est tellement ... 90's.
seequ

2
Vous n'avez pas à vous en tenir à JSON, je n'ai fourni que les exemples en JSON, mais, comme indiqué dans la question, vous pouvez choisir n'importe quel format lisible pour la sortie ou utiliser votre langue équivalente pour un dictionnaire. (Vous pouvez enregistrer 13 caractères en supprimant l' json_encodeinvocation).
Jacob

echone fonctionne pas avec les tableaux; mais le print_r($c);ferait, économisant 9 octets.
Titus

Mais ce n'est pas insensible à la casse. str_split(strtoupper($w))et ucfirst($w[0])peut résoudre cela (+21); ou $s=strtoupper($w);(+18)
Titus

1

PowerShell , 91 83 octets

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

Essayez-le en ligne!

Il lève une exception si un raccourci approprié est introuvable.

Déroulé:

$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 octets

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

courir avec php-r '<code>' <<EOF+ Entrée + <word1>+ Entrée + <word2>+ Entrée + ... + EOF+ Entrée

travailler sur argv pour 155 octets :

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

courir avec php -r '<code>' <word1> <word2> ...

(-13 octets avec un global défini: foreach($i as$w)au lieu de foreach($argv as$i=>$w)if($i))

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.