Prononcer des nombres

14

Concept

Se souvenir des chiffres peut être difficile. Se souvenir d'un mot peut être plus facile. Afin de mémoriser de grands nombres, j'ai créé un moyen de les prononcer d'une manière semblable à un leetspeak.

Règles

Chaque chiffre est d'abord remplacé par sa lettre correspondante:

0 => O
1 => I
2 => R
3 => E
4 => A
5 => S
6 => G
7 => T
8 => B
9 => P

Après le remplacement, deux choses supplémentaires sont effectuées pour améliorer la prononciation:

  • Entre deux consonnes, un Uest ajouté.

  • Entre deux voyelles, un Nest ajouté.

Exemples / cas de test

512431 => SIRANENI
834677081 => BENAGUTUTOBI
3141592 => ENINANISUPUR
1234567890 => IRENASUGUTUBUPO
6164817 => GIGABIT

Ce qui est impossible

  • Lettres et chiffres mélangés dans le même mot
  • Deux consonnes successives ou deux voyelles successives
  • Lettres qui ne figurent pas dans la liste ci-dessus
  • Autres personnages

Règles

Le but de ce est de créer un traducteur bidirectionnel pour ce concept.

  • Votre programme doit d'abord comprendre par lui-même s'il s'agit d'une traduction de lettre à numéro ou de numéro à lettre.
  • Il doit vérifier que l'entrée est correctement formée.
  • Si tout est correct, affichez la traduction.
  • Sinon, afficher un message d'erreur, rien, retourner une valeur de falsey ou planter le programme.

Détails

  • Le numéro / la chaîne d'entrée peut être entré dans le format de votre choix (stdin, argument, ...)
  • C'est le , donc la réponse la plus courte l'emporte.
  • Les failles standard sont interdites.
SteeveDroz
la source
11
Ne devrait pas l' GIGATESTERêtre GIGATESUTER?
kamoroso94
5
Habituellement, nous ne demandons pas que l'entrée soit `` correctement formée '', car c'est juste du code supplémentaire sans raison valable (voir la méta-question pour de bonnes recommandations de défi). De plus, que signifie «correctement formé»?
Okx
9
Si la validation des entrées est requise, vous devez inclure un lot décent de cas de test d' entrées non valides (en particulier les entrées en lettre uniquement qui sont presque valides). J'espère que ce sera en fait la partie principale du défi dans de nombreuses langues.
Martin Ender
2
Je suis d'accord avec @MartinEnder que vous devez ajouter des cas de test pour les cas non valides, comme AB23; AEI; BB; Z; ACE; giga; !@#$; -123; etc. En outre, sur la base des règles de validation, nous pouvons convertir 6164735732 => GIGATESTER, mais GIGATESTERentraînera une fausse valeur, à cause de ST(règle des deux consonnes successives). La façon dont votre défi est actuellement configuré, la partie principale du défi est la validation, au lieu de la conversion. Je suis d'accord avec ça, mais la validation devrait être définie un peu mieux dans ce cas.
Kevin Cruijssen
2
Votre programme doit d'abord comprendre par lui-même s'il s'agit d'une traduction de lettre à numéro ou de numéro à lettre. La traduction doit donc être à double sens? Le texte précédent et les cas de test suggèrent uniquement le nombre à la lettre
Luis Mendo

Réponses:

5

JavaScript (ES6), 130 octets

Prend l'entrée sous forme de chaîne dans les deux sens de traduction. Renvoie la traduction sous forme de chaîne ou falseen cas d'entrée non valide.

f=(n,k)=>(t=n.replace(/./g,(c,i)=>1/n?(!i|p^(p=27>>c&1)?'':'UN'[p])+s[c]:~(x=s.search(c))?x:'',p=s='OIREASGTBP'),k)?t==k&&n:f(t,n)

Démo

Arnauld
la source
Si cela ne fonctionne pas parfaitement, ne le postez pas.
Okx
Espérons que cela fonctionne maintenant comme prévu.
Arnauld
... ou planter lorsqu'il y a des caractères d'expression rationnelle réservés en entrée. Toujours valable
edc65
2

Japt , 61 59 92 85 84 octets

Je suis hors ligne pendant la majeure partie du (long) week-end, si d'autres problèmes sont découverts avec cela, veuillez demander à un mod de le supprimer pour moi jusqu'à ce que je puisse le résoudre.

Prend entrée comme une chaîne pour les deux opérations et renvoie une chaîne pour les deux aussi bien ou falsepour les entrées invalides nombre input.Assumes toujours contenir plusieurs chiffres, ajouter 1 octet remplacer avec Un<space>si ce n'est pas valide. Renvoie falsepour le cas de test GIGATESTERmais, selon les règles, cela devrait être une entrée non valide.


V="OIREASGTBP"UÉ?¡VgXÃe"%v"²_i1'NÃe"%V"²_i1'UÃ:!Uè"%v%v|%V%V|[^{V}NU]" ©Ur"N|U" £VaX

Essayez-le: chiffres -> lettres ou lettres -> chiffres


  • 2 4 octets économisés grâce à obarakon , qui m'a également convaincu de reprendre cela après l'avoir abandonné plus tôt. Je souhaite qu'il ne l'ait pas fait!
  • 33 26 25 (!) Octets sacrifiés en implémentant une solution rapide (c'est-à-dire, encore à jouer au golf) pour vérifier la validité des entrées.

Explication

(Encore à mettre à jour vers la dernière version)

                          :Implicit input of string U.
V="..."                   :Assign the string of letters to variable V, in order.
UÉ                        :Subtract 1 from U, which will give a number (truthy) if the input is a number or NaN (falsey) if the input is a string.
?                         :If it's a number then
¡                         :    Map over the input string, replacing each character (digit) with ...
VgX                       :      the character in string V at index X, the current digit.
à                        :    End mapping.
e                         :    Recursively replace ...
"%v"²                     :      every occurrence of 2 vowels (RegEx) ...
_i1'N                     :      with the current match with an "N" inserted at index 1.
à                        :    End replacement.
e                         :    Another recursive replacement of ...
"%V"²                     :      every occurrence of 2 non-vowel characters (i.e., consonants) ...
_i1'U                     :      with the current match with a "U" inserted at index 1.
à                        :    End replacement.
:                         :Else, if it's a string then
Uè"%v%v|%V%V|[^{V}NU]"    :    Count the number of matches of 2 successive vowels OR 2 successive non-vowels OR any character not in contained in string V plus N & U.
                          :    (The longest part of this code is the fecking input validation!)
?                         :    If that count is greater than 0 then
T                         :       Return 0.
:                              Else
Ur"N|U"                   :        Replace every occurrence of "N" OR "U" in string U with nothing.
£                         :        Map over the string, replacing each character (letter) with ...
VaX                       :         the index of the current character X in string V.
                          :Implicit output of resulting string
Hirsute
la source
Ne semble pas gérer les entrées invalides telles queAEI
Emigna
@Emigna: Ah, bon sang! Vous imaginez, après avoir été brûlé par la première "Règle" au départ, nous aurions pensé à lire le reste des règles! : \ J'ai pris la section "Ce qui est impossible" pour impliquer que nous n'aurions pas à gérer aucun de ces points. Correction à venir sous peu.
Shaggy
2

Python 3 , 147 octets

lambda c:c in"0134"
def f(n):
 o="";a=b=1-x(n[0])
 for i in n:
  a=x(i)
  if a==b:o+="UN"[a]
  o+="OIREASGTBP"["0123456789".index(i)];b=a
 print(o)

Essayez-le en ligne!

irréparable
la source
1

Java (OpenJDK 8) , 416 410 399 382 376 370 octets

-2 octets grâce à @Cyoce

-17 octets de plus grâce à une idée de @Cyoce

-6 octets grâce à @KevinCruijssen

s->{String c="[RSGTBP]",v="[OIEA]",o="([256789])",e="([0134])";boolean b=s.matches("(c$|v$|(c|vN)(?=v)|(cU|v)(?=c))+".replace("c",c).replace("v",v));int i=-1;for(s=b?s.replaceAll("[UN]",""):s.matches("[0-9]+")?s.replaceAll(e+"(?="+e+")","$1N").replaceAll(o+"(?="+o+")","$1U"):i/0+"";i<9;s=b?s.replace(v,c):s.replace(c,v)){c=++i+"";v="OIREASGTBP".charAt(i)+"";}return s;}

Essayez-le en ligne!

Ugh, le remplacement de java est tellement verbeux.

Fonction qui prend une chaîne et renvoie la chaîne traduite de chiffre -> lettre ou vice versa. Plantage sur une entrée non valide (vous pouvez le voir dans l'exemple tio où il génère les valeurs correctes pour les 10 premiers cas de test, puis se bloque avec une erreur de division par zéro qui apparaît dans la vue de débogage)

Non golfé (les premier et dernier termes de la boucle for sont retirés pour plus de lisibilité)

s-> {
    String c="[RSGTBP]", v="[OIEA]", o="([256789])", e="([0134])"; 
    boolean b=s.matches("(c$|v$|(c|vN)(?=v)|(cU|v)(?=c))+".replace("c",c).replace("v",v)); // lovely regex, explained below
    int i=-1;
    s= b? 
        s.replaceAll("[UN]",""); // remove N's and U's
        :s.matches("[0-9]+")?
        s.replaceAll(e+"(?="+e+")","$1N").replaceAll(o+"(?="+o+")","$1U"); // add N's and U's for separating vowels and consonants
        :i/0+""; // throw an error, looks like a sting for the ternary
    for(;i<9;) { 
        c=++i+"";
        v="OIREASGTBP".charAt(i)+"";
        s=b?s.replace(v,c):s.replace(c,v); // if it started with numbers, go to letters, or vice versa
    }
    return s;
}

Le regex pour faire correspondre les nombres est simple, mais voici le regex pour faire correspondre les lettres aux nombres

(c$|v$|(c|vN)(?=v)|(cU|v)(?=c))+
(                             )+   every part of the word is
 c$                                a consonant at the end of the word
   |v$                             or a vowel at the end of the word
      |(c|vN)(?=v)                 or a consonant or a vowel + N followed by a vowel
                  |(cU|v)(?=c)     or a consonant + U or a vowel followed by a consonant


with c = [RSGTBP] and v = [OIEA]
PunPun1000
la source
Non pas que cela améliore considérablement votre nombre d'octets massifs, mais vous pouvez supprimer les parenthèses autour(s)->
Cyoce
@Cyoce chaque octet aide
PunPun1000
puisque toutes vos branches de l' ifinstruction sont des affectations (qui renvoient une valeur), essayez de remplacer le if... else if... elsepar l'opérateur conditionnel ?:, en le faisant précéder de Object _=pour en faire une instruction valide. Je ne sais pas si cela aiderait réellement le nombre d'octets, mais je pense que oui.
Cyoce
Deux petites choses que vous pouvez jouer au golf. Vous pouvez supprimer la chaîne t, car vous ne l'utilisez qu'une seule fois. Devient t.charAt(i)+""alors "OIREASGTBP".charAt(i)+""( -4 octets ). Et vous pouvez placer la dernière ligne à l'intérieur de la boucle for après l' i<9;intérieur de la déclaration for-loop. Il devient donc for(;i<9;s=b?s.replace(v,c):s.replace(c,v)){( -1 octet ). Oh, et vous pouvez également mettre celui s=b?...qui vient juste après l' int i=-1;intérieur de la boucle for: for(s=b?...;i<9;...( -1 octet ).
Kevin Cruijssen
1

PHP; 129 127 267 259 228 octets

$l=IOREASGTBP;$n=1023456789;ctype_digit($s=$argn)?:$s=preg_replace("#U|N#","",strtr($o=$s,$l,$n));for($r=$c=($t=strtr($s,$n,$l))[$i++];$d=$t[$i++];)$r.=((trim($c,AEIO)xor$x=trim($d,AEIO))?X:UN[!$x]).$c=$d;echo$o?$o==$r?$s:"":$r;

Exécuter en tant que pipe avec -nRou l' essayer en ligne .

panne

$l=IOREASGTBP;$n=1023456789;
# if not digits, translate letters to digits and remember original
ctype_digit($s=$argn)?:$s=preg_replace("#U|N#","",strtr($o=$s,$l,$n));
# translate digits to letters:
for($r=$c=($t=strtr($s,$n,$l))                      # result = first letter
    [$i++];$d=$t[$i++];)                            # loop through letters
    $r.=((trim($c,AEIO)xor$x=trim($d,AEIO))?"":UN[!$x]) # append delimiter if needed
        .$c=$d;                                         # append next letter
# 
echo
    $o              # if original was remembered,
        ?$o==$r         # compare original to final result
            ?$s         # if equal, print digits
            :X          # else print X (as error message)
        :$r;        # else print letters
Titus
la source
1

Java 8, 312 308 304 301 294 290 octets

s->{String r="",x="([AEIOU])",y="([BGNPRST])",z="0O1I2R3E4A5S6G7T8B9P";for(int c:s.getBytes())r+=c!=78&c!=85?z.charAt((c=z.indexOf(c)+(c<58?1:-1))<0?0:c):"";return s.matches("(("+x+y+")*"+x+"?)|(("+y+x+")*"+y+"?)|\\d*")?r.replaceAll(x+"(?="+x+")","$1N").replaceAll(y+"(?="+y+")","$1U"):"";}

-4 octets (308 → 304) pour un bug-fix (n'arrive pas souvent que le nombre d'octets diminue quand je corrige un bug dans mon code ..: D)

EDIT: utilise une approche différente de la réponse Java de @ PunPun1000 en créant d'abord la chaîne de retour dans une boucle for sur les caractères, puis utilise une expression rationnelle plus abstraite pour la valider dans le retour-ternaire (l'entrée est soit tous les chiffres, ou les voyelles et consonnes données sont-elles alternées (donc sans voyelles ni consonnes adjacentes).

Explication:

Essayez-le ici.

s->{                                   // Method with String parameter and String return-type
  String r="",                         //  Result-String
    x="([AEIOU])",y="([BGNPRST])",     //  Two temp Strings for the validation-regex
    z="0O1I2R3E4A5S6G7T8B9P";          //  And a temp-String for the mapping
  for(int c:s.getBytes())              //  Loop over the characters of the input-String
    r+=                                //   Append to the result-String:
       c!=78&c!=85?                    //    If the character is not 'N' nor 'U':
        z.charAt(                      //     Get the character from the temp-String `z`
         (c=z.indexOf(c)+              //      by getting the character before or after the current character
            +(c<58?1:-1))              //      based on whether it's a digit or not
             <0?0:c)                   //      and a 0-check to prevent errors on incorrect input like '!@#'
       :                               //    Else:
        "";                            //     Append nothing
                                       //  End of loop (implicit / single-line body)
  return s.matches("(("+x+y+")*"+x+"?)|(("+y+x+")*"+y+"?)|\\d*")?
                                       //  If the input is valid
                                       //  (Only containing the vowels and consonants of `x` and `y`, without any adjacent ones. Or only containing digits)
    r                                  //   Return the result
     .replaceAll(x+"(?="+x+")","$1N")  //    after we've added 'N's if necessary
     .replaceAll(y+"(?="+y+")","$1U")  //    and 'U's if necessary
   :"";                                //  Or return an Empty String if invalid
}                                      // End of method

L'expression rationnelle de validation:

(([AEIOU][BGNPRST])*[AEIOU]?)|(([BGNPRST][AEIOU])*[BGNPRST]?)|\\d*
Kevin Cruijssen
la source
0

05AB1E , 76 octets

.•.Ÿ^91Ý•Ul„nuSKDXSKg0QVvXyk}JYP©0Êi®}¤«SXuèŒ2ùv…U NSy0èìžMuyåOè})Jᨹd_iQ®P

Essayez-le en ligne!

Renvoie la valeur falsifiée 0pour une entrée non valide.

Emigna
la source
0

Bash ,241 238 235 octets

q=OIREASGTBP;[[ $1 == +([0-9]) ]]&&(x=`tr 0-9 $q<<<$1`;m={B,G,P,R,S,T};n={A,E,I,O};for i in `eval echo $m$m$n$n`;{ a=${i::1};b=${i:1:1};x=${x//$a$b/$a'U'$b};a=${i:2:1};b=${i:3:1};x=${x//$a$b/$a'N'$b};};echo $x)||tr $q 0-9<<<$1|tr -d UN

Essayez-le en ligne!

Moins golfé:

q=OIREASGTBP;                          save string in q
[[ $1 == +([0-9]) ]]&&(                if argument 1 is only digits
x=`tr 0-9 $q<<<$1`;                    save in x each digit translated to corresponding letter
m={B,G,P,R,S,T};
n={A,E,I,O};
for i in `eval echo $m$m$n$n`;{        generates all combinations of vowels and consonants
                                       BBAA BBAE ... TTOI TTOO
   a=${i::1};                          saves first consonant in a
   b=${i:1:1};                         saves second consonant in b
   x=${x//$a$b/$a'U'$b};               insets U between consonants
   a=${i:2:1};                         saves first vowel in a
   b=${i:3:1};                         saves second vowel in b
   x=${x//$a$b/$a'N'$b};               inserts N between vowels
};
echo $x                               echoes result
)||                                   if argument contains letters
  tr $q 0-9<<<$1|tr -d UN             translates letter to corresponding number and deletes U and N
marcosm
la source
0

PHP, 268 octets

$v=OIEA;$l=RSGTBP;$d="0134256789";$c=ctype_digit;$p=preg_replace;echo!$c($a=$argn)?$c($e=strtr($p(["#\d|[$v]{2,}|[$l]{2,}#","#[$v]\KN(?=[$v])#","#[$l]\KU(?=[$l])#"],[_,"",""],$a),$v.$l,$d))?$e:_:$p(["#[$v](?=[$v])#","#[$l](?=[$l])#"],["$0N","$0U"],strtr($a,$d,$v.$l));

Essayez-le en ligne!

Jörg Hülsermann
la source
0

Perl, 127 octets

126 octets + 1 octet de ligne de commande

$i="AEIOU]";$;=OIREASGTBP;1/!/[^$;NU\d]|[$i{2}|[^\d$i{2}/;eval"y/0-9$;NU/$;0-9/d";s/[$i\K(?=[$i)/N/g;s/[^N\d$i\K(?=[^\d$i)/U/g

Usage:

 echo -n "512431" | perl -p entry.pl

Devrait suivre toutes les règles du défi - peut accepter des lettres ou des chiffres et commettra une erreur (division par zéro) si la validation échoue

Jarmex
la source
La validation a des faux positifs en entrée NOet US.
Value Ink
0

Rubis , 205 + 1 = 206 octets

Utilise l' -pindicateur pour +1 octet. Maintenant avec un système exhaustif de validation des entrées.

d,w=%w"0-9 OIREASGTBP"
~/^\d+$/?($_.tr!d,w
gsub /([#{a='AEIO])(?=\g<1>)'}/,'\0N'
gsub /([^#{a}/,'\0U'):(+~/^(([AEIO])(N(?=[AEIO])|(?=\g<4>)|$)|([RSGTBP])(U(?=\g<4>)|(?=\g<2>|$)))+$/;$_.tr!("NU","").tr!w,d)

Essayez-le en ligne!

Encre de valeur
la source
Cela ne semble pas convertir les lettres en chiffres, ni effectuer de validation!
Jarmex
@Jarmex oops, validation ajoutée! C'est un énorme contrôle de validation mais je n'ai pas beaucoup de choix en la matière
Value Ink
0

Python 3, 741 octets

from functools import reduce;c=0;e="";n="NU";v="AEIOU";l="OIREASGTBPNU";x=('0','O'),('1','I'),('2','R'),('3','E'),('4','A'),('5','S'),('6','G'),('7','T'),('8','B'),('9','P');s=input()
try:
    int(s);y=reduce(lambda a,kv:a.replace(*kv),x,s)
    for i in y:
        e+=i
        if i in v:
            z=True
            try:
                if y[c+1] in v:e+="N"
            except:
                pass
        else:
            z=False
            try: 
                if not y[c+1] in v:e+="U"
            except:
                pass
        c+=1
except:
    for i in s:
        if not i in l:
            p
    y=reduce(lambda a,kv:a.replace(*kv[::-1]),x,s)
    for i in y: 
        if not i in n:e+=i
print(e)

Essayez-le en ligne!

Il y a beaucoup de place pour l'amélioration, je sais.

LyricLy
la source
0

sed, 123 octets

s/[0134]/_&_/g
s/[25-9]/=&=/g
ta
y/OIREASGTBPU/0123456789N/
s/N//g
q
:a
s/__/N/g
s/==/U/g
y/0123456789_/OIREASGTBP=/
s/=//g

Explication

Tout d' abord, nous entourent chiffres avec _(pour les voyelles) ou =(pour les consonnes).

Si nous n'avons effectué aucune substitution, nous convertissons les lettres en chiffres, c'est donc une simple substitution, et supprimons Uet N. Alors quittez.

Sinon, nous passons à l'étiquette a, où nous traitons des voyelles consécutives, puis des consonnes consécutives. Transformez ensuite les chiffres en lettres et supprimez les caractères marqueurs que nous avons introduits dans la première étape.

Toby Speight
la source
0

Python3, 246 octets

v=lambda x:x in"AEIO"
V="OIREASGTBP"
i=input()
r=__import__("functools").reduce
print(r(lambda x,y:x+(("U",""),("","N"))[v(x[-1])][v(y)]+y,map(lambda x:V[x],map(int,i)))if i.isdigit()else r(lambda x,y:x*10+V.index(y),filter(lambda x:x in V,i),0))    

explication:

  • mapper l'entrée à une liste d'int
  • mapper la liste des int à leur position dans l'alphabet
  • réduire la liste en ajoutant un accumulateur, plus un élément d'un tuple dict , plus l'élément actuel
    • le tuple dict est une table de vérité basée sur deux éléments, être une voyelle ou non
Setop
la source
0

JavaScript (ES6), 120

Une fonction prenant l'entrée comme une chaîne. Il renvoie la chaîne correctement traduite si l'entrée est valide, sinon false ou la fonction se bloque.

n=>(t=n=>n.replace(/./g,d=>1/d?(v-(v=d<5&d!=2)?'':'UN'[v])+z[d]:~(a=z.search(d))?a:'',v=2,z='OIREASGTBP'))(q=t(n))==n&&q

Moins golfé

n => 
{
  var t = n => { // function to translate, no check for invalid input
    var v = 2; // 1 = digit map to vowel, 0 = digit map to consonant, start with 2
    var z = 'OIREASGTBP'; // digits mapping
    return n.replace(/./g,
      d => 1/d // digit / alpha check
        ? ( // if digit
            w = v, // save previous value of v
            v = d < 5 & d != 2, // check if current digit will map to wovel or consonant
            (w != v 
             ? '' // if different - wovel+consonant or consonant+wovel or start of input
             : 'UN'[v] // if equal, insert required separator
            ) + z[d] // add digit translation
          )
        : ( // if alpha
             a = z.search(d), // look for original digit. Could crash if d is a reserved regexp char (not valid input)
             a != -1 ? a : '' // if digit found add to output, else do nothing
          )
    )
  }

  var q = t(n); // translate input an put in q
  if (t(q) == n) // translate again, result must be == to original input
    return q; // if ok return result
  else
    return false; // else return false
}

Tester

var F=
n=>(t=n=>n.replace(/./g,d=>1/d?(v-(v=d<5&d!=2)?'':'UN'[v])+z[d]:~(a=z.search(d))?a:'',v=2,z='OIREASGTBP'))(q=t(n))==n&&q

;`512431 => SIRANENI
834677081 => BENAGUTUTOBI
3141592 => ENINANISUPUR
1234567890 => IRENASUGUTUBUPO
6164817 => GIGABIT`
.split('\n')
.forEach(x => {
  var [a,b] = x.match(/\w+/g)
  var ta = F(a)
  var tb = F(b)
  console.log(a==tb ? 'OK':'KO', a + ' => '+ ta)
  console.log(b==ta ? 'OK':'KO', b + ' => '+ tb)
})

function go() {
  O.textContent = F(I.value)
}

go()
<input id=I value='NUNS' oninput='go()'>
<pre id=O></pre>

edc65
la source