Implémenter une fonctionnalité de type t9

10

Votre défi aujourd'hui est d'implémenter une fonctionnalité de type t9 .

Vous implémenterez une fonction qui n'aura que 2 paramètres.
Vous recevrez 1 numéro de téléphone dans une chaîne et le contenu d'un fichier texte avec une liste de mots (ne supposez pas un style de nouvelle ligne spécifique).
Vous pouvez utiliser le lien https://raw.githubusercontent.com/eneko/data-repository/master/data/words.txt pour tester la fonctionnalité, ou utiliser /usr/share/dict/words(consultez Un fichier texte avec une liste de mots [fermé] pour en savoir plus information).

Vous pouvez supposer que vous recevrez toujours au moins 2 numéros.

Étant donné le nombre, vous lirez une liste de mots et retournerez les mots commençant par les lettres correspondant à ces mots. Cela signifie que l'entrée ne doit être composée que de 2 à 9.
Vous pouvez faire ce que vous voulez si vous recevez une entrée non valide.

Si aucune correspondance n'est trouvée, vous pouvez renvoyer une liste vide, null/ nilou 0.

N'oubliez pas que les touches du téléphone portable sont mappées à leurs caractères équivalents:

  • 0 et 1 ne sont pas valides
  • 2 correspondances [abc]
  • 3 appariés [def]
  • 4 matchs [ghi]
  • 5 correspondances [jkl]
  • 6 correspondances [mno]
  • 7 correspondances [pqrs]
  • 8 correspondances [tuv]
  • et 9 correspondances [wxyz]

Exemples:

f('52726')
//returns ["Japan","japan","Japanee","Japanese","Japanesque"...,"larbowlines"]

f('552')
//returns ["Kjeldahl","kjeldahlization","kjeldahlize"...,"Lleu","Llew"]

f('1234')
//makes demons fly out your nose or divide by 0

f('9999')
//returns ["Zyzzogeton"]

f('999999')
//returns [] or null/nil or 0

Après avoir exécuté votre fonction, vous pouvez l'imprimer comme vous le souhaitez.

Règles:

  • Les failles standard ne sont pas valides
  • Vous devez retourner quelque chose, même si c'est null/ nil
    Javascript retournera undefinedsi vous ne retournez pas quelque chose, donc cette règle.
  • Vous ne pouvez pas utiliser ou réimplémenter les réponses des autres ou copier ma mise en œuvre.
  • Vous pouvez supposer, pour Javascript, que le navigateur sera déjà ouvert et que le innerText/ textContentde l'élément automatique sera passé comme 2ème paramètre
  • Pour les langues compilées, vous ne pouvez pas passer d'arguments spéciaux au compilateur
  • Vous pouvez recevoir le nom de fichier sur les arguments du compilateur
  • Les variables, macros, variables globales, constantes, classes non standard et tout le tri passant d'autres valeurs à l'intérieur de la fonction seront considérés comme invalides.
  • En Javascript, les variables sans le mot clé varrendent votre code invalide
  • Votre fonction sera nommée f
  • Vous ne pouvez avoir et seulement que 2 arguments sur votre fonction
  • Essayez de garder votre code sous 500 secondes pour l'exécuter.
  • Vous n'avez pas à vous soucier des espaces blancs
  • Vous devez utiliser uniquement des caractères imprimables ASCII .
    Les exceptions sont les langues qui n'utilisent des caractères non-imprimables (APL et espaces blancs sont 2 exemples).

Notation:

  • Plus petit nombre d'octets gagne
  • La présence de caractères imprimables ASCII invalides dans votre réponse comptera comme la réponse codée en UTF-32.
    L'exception au codage fera que votre réponse sera comptée par caractères .
  • Seul le corps de la fonction compte, ne comptez rien d'autre que vous faites en dehors
  • Bonus de -30% si vous faites un système de prédiction basé sur le quartier ou les mots les plus courants
  • Bonus de -20% si vous ne renvoyez que les 5 premières correspondances pour chaque lettre correspondant au premier chiffre (par exemple: 245 renvoie 5 mots commençant par «a», 5 commençant par «b» et 5 commençant par «c» ).

Voici un exemple d'implémentation utilisant Javascript:

function f(phone, words)
{
    var keypad=['','','abc','def','ghi','jkl','mno','pqrs','tuv','wxyz'];
    var regex='';

    for(var i=0,l=phone.length;i<l;i++)
    {
        regex+='['+keypad[phone[i]]+']';
    }

    var regexp=new RegExp('\\s('+regex+'[a-z]*)\\s','gi');

    return words.match(regexp);
}

Pour l'exécuter, ouvrez le lien de liste et exécutez, par exemple:

f('9999',document.getElementsByTagName('pre')[0].innerText);
//returns [" Zyzzogeton "]

Cet exemple a été testé et fonctionne sous Opera 12.17 64bits sur Windows 7 Home Edition 64bits.

Ismael Miguel
la source
Le deuxième argument du programme est-il un nom de fichier contenant les mots ou la liste de mots elle-même?
Optimizer
@ MartinBüttner UTF-8 n'est pas injuste (il compte toujours les caractères ASCII comme étant 1 octet), mais j'ai changé la règle.
Ismael Miguel
@Optimizer Le 2ème argument est une liste de mots. Vous pouvez passer le nom de fichier sur un argument du compilateur et lire le fichier, si vous le souhaitez. Mais la seule chose qui compte, c'est le corps fonctionnel.
Ismael Miguel
@ MartinBüttner En comptant comme ASCII, il est compté comme octets. Vous voulez que je dise que le code APL aura 1 octet ayant la taille de 8 bits?
Ismael Miguel du
2
-1 pour des restrictions inappropriées
AJMansfield

Réponses:

3

CJam, 28 octets

q~{el{'h-_9/-D+3/}%s1$#!},p;

Prend des informations sous la forme de "<number>" [<list of words>]

Exemple:

"52726" ["Japan" "japan" "Japanee" "Japanese" "Japanesque" "larbowlines" "ablution" "ablutionary" "abluvion" "ably" "abmho" "Abnaki" "abnegate"]

Production:

["Japan" "japan" "Japanee" "Japanese" "Japanesque" "larbowlines"]

Je ne veux aucun bonus pour l'instant.

Essayez le code en ligne ici, mais pour les mesures de temps réelles, exécutez-le sur le compilateur Java

Notez que CJam représente des listes vides comme ""

Pour convertir la liste de mots bruts en liste CJam, utilisez le code suivant avec la liste de mots en entrée:

qN/p
Optimiseur
la source
"Vous recevrez 1 numéro de téléphone dans une chaîne et le contenu d'un fichier texte avec une liste de mots" -> pouvez-vous implémenter, sur un bloc différent, le code nécessaire pour lire le fichier dans une liste utilisable?
Ismael Miguel
@IsmaelMiguel Vous voulez dire non pas la partie de ce code, mais juste un code d'aide pour convertir la liste au format correct?
Optimizer
Exactement. Quel code ne suffit pas pour prouver qu'il peut utiliser une liste de mots comme exemples fournis. Mais j'ai voté de toute façon, je voulais juste ce code d'aide.
Ismael Miguel
Pouvez-vous l'ajouter à la réponse? En tant que montage, dans une autre partie
Ismael Miguel
Exactement. C'est ce dont je parle! Voyons si vous pouvez l'optimiser encore plus
Ismael Miguel
2

Java: 395

Cela forme un modèle d'expression régulière basé sur les lettres autorisées pour chaque numéro, puis clique sur un. * À la fin pour correspondre aux caractères suivants.

Voici la version golfée:

static ArrayList<String> f(String n,ArrayList<String> d){String[] k={"","","([A-Ca-c])","([D-Fd-f])","([G-Ig-i])","([J-Lj-l])","([M-Om-o])","([P-Sp-s])","([T-Vt-v])","([W-Zw-z])"};String r="";for(int i=0;i<n.length();++i)r+=k[n.charAt(i)-'0'];r += ".*";Pattern p=Pattern.compile(r);ArrayList<String> a=new ArrayList<String>();for(String w:dictionary)if(p.matcher(w).matches())a.add(w);return a;}

Et voici la version non golfée pour la lisibilité

public static ArrayList<String> f(String phoneNumber, ArrayList<String> dictionary) {

    String[] KEY_VALUES = {"", "", "([A-Ca-c])", "([D-Fd-f])", "([G-Ig-i])",
                                            "([J-Lj-l])", "([M-Om-o])", "([P-Sp-s])",
                                            "([T-Vt-v])", "([W-Zw-z])"};

    String regex = "";
    for (int i = 0; i < phoneNumber.length(); ++i) {
        regex += KEY_VALUES[phoneNumber.charAt(i) - '0'];
    }
    regex += ".*";
    Pattern p = Pattern.compile(regex);
    ArrayList<String> answers = new ArrayList<String>();
    for (String word : dictionary) {
        if (p.matcher(word).matches()) {
            answers.add(word);
        }
    }
    return answers;
}
Brian J
la source
Votre code va à l'encontre de la règle numéro 7: "Les variables, macros, variables globales, constantes, classes non standard et tout le tri passant d'autres valeurs à l'intérieur de la fonction seront considérés comme invalides." et cela va un peu à l'encontre de la règle numéro 3: "Vous ne pouvez pas utiliser ou réimplémenter les réponses des autres ou copier mon implémentation.", mais sur votre code, c'est un peu discutable. Et cela va également à l'encontre de la règle 9: "Votre fonction sera nommée f".
Ismael Miguel
@IsmaelMiguel Oups. La règle 7 peut être facilement corrigée en déplaçant la constante à l'intérieur de la fonction. Je le sortais juste de la fonction pour un meilleur style de programmation. La règle 9 est également une solution facile. J'avoue que je n'ai pas lu votre réponse, donc je n'ai pas intentionnellement essayé de la copier. Je peux retirer ma réponse si vous pensez qu'elle est trop proche pour le concours.
Brian J
Votre réponse est correcte. Vous avez un bug sur votre code. Sur la dernière constante ( ([W-Zw-z)]), elle devrait l'être ([W-Zw-z]). Et sur Code-golf, vous n'avez pas à vous soucier des styles de programmation et des bonnes pratiques: votre code doit simplement faire sa chose avec les paramètres requis. Si vous cochez ma réponse, vous verrez cette ligne: $s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];. C'est un terrible «crime» en PHP. Fondamentalement, je force PHP à convertir des constantes non existantes en chaînes. C'est parfaitement acceptable. Vous verrez également que je ne mets même pas la variable $tsur un tableau avant de l'utiliser comme telle
Ismael Miguel
@IsmaelMiguel Bonne prise sur l'erreur d'expression régulière. Merci de l'avoir signalé. Je vais essayer de jouer au golf demain; peut-être trouver quelques exemples Java sur ce site.
Brian J
Je ne suis pas un programmeur Java, mais je vous dis certaines choses. Vous pouvez consulter codegolf.stackexchange.com/questions/6671/… pour obtenir des conseils. Les conseils généraux incluent la suppression d'espaces inutiles (sauts de ligne, espaces, tabulations), les noms de variables d'une lettre et faites tout ce que vous pouvez pour réduire la taille du code autant que possible.
Ismael Miguel
1

C # .NET 4.5 235

Cela devrait fonctionner:

IEnumerable<string>F(string n,string d){IEnumerable<string>w=d.Split(null).ToList();string[]a={"","","abc","def","ghi", "jkl","mno","pqrs","tuv","wxyz"};foreach(var i in n){w=w.Where(x=>x.IndexOfAny(a[i-'0'].ToArray())>0);}return w;}
Chaossie
la source
Bienvenue chez PPCG. Votre code fonctionnera, mais vous devez encore le réduire beaucoup plus. En supprimant tous les espaces inutiles (espaces, tabulations, sauts de ligne), j'ai réussi à réduire votre code à 167 octets. Ce code peut être beaucoup plus réduit, j'en suis sûr. Je recommande de lire codegolf.stackexchange.com/questions/173/… pour raccourcir encore plus votre code. Pour vous aider un peu, la liste de mots est une chaîne séparée par des sauts de ligne, et vous semblez supposer qu'il est déjà possible d'y utiliser un foreach. Si vous vous attendez à ce qu'il soit déjà IEnumerable, incluez le code utilisé à l'extérieur
Ismael Miguel
@IsmaelMiguel TY Je vais l'examiner. La liste est un IEnumerable, il n'y a pas de code en dehors de ce que j'ai publié.
Chaossie
Si vous regardez la spécification de la fonction, vous verrez que le 2ème paramètre est également une chaîne. (Citant: "Vous recevrez 1 numéro de téléphone dans une chaîne et le contenu d'un fichier texte avec une liste de mots (ne supposez pas un style de nouvelle ligne spécifique).") Et vous avez 1 espace blanc inutile sur votre avar.
Ismael Miguel
J'ai remarqué des améliorations sur votre question et je vous ai donné un vote positif. Mais vous pouvez toujours enregistrer un octet sur votre avar. Mais je vois vraiment des améliorations notables! Continuez votre bon travail.
Ismael Miguel
1

Python 2 (155 octets)

Devrait également fonctionner en Python 3 avec les remplacements appropriés ( string-> bytes, bpréfixe sur les chaînes, etc.).

Je ne savais pas si avoir l' maketransappel en dehors de la fonction était considéré comme "juste"; sinon, la fonction fait 134 octets avec elle déplacée à l'intérieur.

EDIT: Suppression d'un octet d'une erreur stupide.

Avec préparé maketrans, 67 octets:

from string import maketrans
t=maketrans('abcdefghijklmnopqrstuvwxyz','22233344455566677778889999')

def f(n,w):
    return[x for x in w.split()if x.lower().translate(t).startswith(n)]

Avec maketransdans le corps, 134 octets:

from string import maketrans

def f(n,w):
    return[x for x in w.split()if x.lower().translate(maketrans('abcdefghijklmnopqrstuvwxyz','22233344455566677778889999')).startswith(n)]

Avec importet maketransdans le corps, 155 octets:

def f(n,w):
    return[x for x in w.split()if x.lower().translate(__import__('string').maketrans('abcdefghijklmnopqrstuvwxyz','22233344455566677778889999')).startswith(n)]

Appel d'essai:

print f('9999',open('words.txt','rt').read())
criptych se tient avec Monica
la source
Le maketransfait partie du corps de fonction. Vous devez le déplacer. Je ne sais pas si c'est même possible, mais vous pouvez essayer d'utiliser directement le import. Je pense l'avoir vu quelque part ... Mais votre code est vraiment sympa!
Ismael Miguel
Voulez-vous déplacer l'importation et l' appel dans le corps? Oui, je pense que cela peut aussi être fait.
Criptych se tient avec Monica
Je pensais t=(from stirng import maketrans)([...]). Je n'ai aucune idée si c'est même possible. Mais peut-être pouvez-vous utiliser from string import as x t=x([...])ce que je ne suis pas sûr si c'est possible aussi: /
Ismael Miguel
La bonne version est la dernière. Mais la réponse telle quelle est acceptable à mon avis. +1 pour __import__('string').maketran.
Ismael Miguel
OK merci. J'ai supprimé les réponses invalides.
Criptych se tient avec Monica
0

PHP 5.4+ (171 186-20% = 148,8 octets):

Eh bien, c'est une réponse assez énorme, mais bon.

J'espère que cela amènera plus de gens à répondre.

Cette fonction attend que le contenu brut soit lu.

Voici le code:

function f($_,$a){$s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];$a=preg_split('@\r\n|\r|\n@',$a);for($i=0;$c=$_[$i];++$i)foreach($a as$k=>$v)if(!strpos(1..$s[$c],$v[$i])||$t[$v[0]]++>4)unset($a[$k]);return$a;}

Cela fonctionne en vérifiant que la lettre figure dans la liste des lettres autorisées.

Exemple: l'entrée 36ferait pour vérifier si 1abca la première lettre du mot et qui 1defa la 2ème lettre.

J'ajoute 1donc il ne vérifie pas si la lettre est en 1ère position (qui reviendrait 0et qui serait évaluée false). if(!strpos(1..$s[$c],$v[$i]))ou if(!strpos($c.$s[$c],$v[$i]))aura le même effet, mais le 1er confond plus et j'aime ça.

À défaut, le mot sera supprimé.

Sans aucun mot, il renvoie un tableau vide.

Pour tester cela en ligne, allez sur http://writecodeonline.com/php/ et créez une variable simple avec un mot pour la ligne.

Un exemple testable:

function f($_,$a)
{
    $s=array(2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz);
    $a=preg_split('@\r\n|\r|\n@',$a);

    for($i=0;$c=$_[$i];++$i)
        foreach($a as$k=>$v)
            if(!strpos(1..$s[$c],$v[$i]) || $t[$v[0]]++>4)
                unset($a[$k]);
    return$a;
}

$lines=<<<WORDS
one
two
three
four
five
six
seven
eight
nine
ten
WORDS;

var_dump(f('36',$lines));

Cela devrait produire:

array(1) {
    [3]=>
      string(4) "four"
}

Pour travailler sur les anciennes versions de php, remplacez $s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];par$s=array(2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz);


Pour le bonus de 20%:

Pour réduire le code que j'ai simplement ajouté ||$t[$v[0]]++>4, qui vérifie combien de fois la première lettre a été utilisée.

En php, $tn'a pas besoin d'être défini, ce qui permet de réduire un gros morceau de 37,2 octets.

Pour voir cet effet, utilisez la variable suivante comme 2e argument:

$lines=<<<WORDS
one
two
three
four
five
six
seven
eight
nine
ten
twelve
time
tutor
test
truth
WORDS;
Ismael Miguel
la source