Pronunciar números

14

Concepto

Recordar los números puede ser difícil. Recordar una palabra puede ser más fácil. Con el fin de memorizar grandes números, creé una forma de pronunciarlos de forma similar a un discurso.

Reglas

Cada dígito se reemplaza primero por su letra correspondiente:

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

Después del reemplazo, se hacen dos cosas adicionales para mejorar la pronunciación:

  • Entre dos consonantes, Use agrega a.

  • Entre dos vocales, Nse agrega a.

Ejemplos / casos de prueba

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

Que es imposible

  • Letras y números mezclados en la misma palabra
  • Dos consonantes sucesivas o dos vocales sucesivas.
  • Cartas que no están en la lista de arriba
  • Otros personajes

Reglas

El objetivo de este es crear un traductor bidireccional para este concepto.

  • Su programa primero debe entender por sí mismo si se trata de una traducción de letra a número o de número a letra.
  • Debe verificar que la entrada esté bien formada.
  • Si todo es correcto, muestre la traducción.
  • De lo contrario, muestre un mensaje de error, nada, devuelva un valor falso o bloquee el programa.

Detalles

  • El número / cadena de entrada se puede ingresar en el formato que desee (stdin, argumento, ...)
  • Este es el , por lo que gana la respuesta más corta.
  • Las lagunas estándar están prohibidas.
SteeveDroz
fuente
11
No debe GIGATESTERser GIGATESUTER?
kamoroso94
55
Por lo general, no pedimos que la entrada se 'forme correctamente', ya que es solo un código adicional sin una buena razón (consulte la meta pregunta para obtener buenas recomendaciones de desafío). Además, ¿qué significa 'formado adecuadamente'?
Okx
99
Si se requiere validación de entrada, debe incluir un lote decente de casos de prueba de inválido entradas (especialmente entradas de solo letras que son casi válidas). Espero que esto sea realmente la parte principal del desafío en muchos idiomas.
Martin Ender
2
Estoy de acuerdo con @MartinEnder en que debe agregar algunos casos de prueba para casos no válidos, como AB23; AEI; BB; Z; ACE; giga; !@#$;-123; etc. Además, según las reglas de validación, podemos convertir 6164735732 => GIGATESTER, pero GIGATESTERresultará en un valor falso, debido a ST(regla de dos consonantes sucesivas). Según la configuración actual de su desafío, la parte principal del desafío es la validación, en lugar de la conversión. Estoy de acuerdo con eso, pero la validación debería definirse un poco mejor en ese caso.
Kevin Cruijssen
2
Su programa primero debe entenderse por sí mismo si se trata de una traducción de letra a número o de número a letra. ¿Entonces la traducción tiene que ser bidireccional? El texto anterior y los casos de prueba solo sugieren números a letras
Luis Mendo

Respuestas:

5

JavaScript (ES6), 130 bytes

Toma la entrada como una cadena en ambas formas de traducción. Devuelve la traducción como una cadena o falseen caso de una entrada no válida.

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)

Manifestación

Arnauld
fuente
Si no funciona perfectamente, no lo publique.
Okx
Esperemos que ahora funcione como se esperaba.
Arnauld
... o bloquearse cuando hay caracteres regexp reservados en la entrada. Sin embargo
edc65
2

Japt , 61 59 92 85 84 bytes

Estoy desconectado durante la mayor parte del (largo) fin de semana, si se descubren más problemas con esto, solicite a un mod que lo elimine hasta que pueda solucionarlo.

Toma la entrada como una cadena para ambas operaciones y devuelve una cadena para ambas o falsepara una entrada no válida. Supone que las entradas de números siempre contendrán varios dígitos, agregue 1 byte reemplazando por Un<space>si no es válido. Devuelve falsepara el caso de prueba GIGATESTERpero, de acuerdo con las reglas, eso debería ser una entrada no válida.


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

Pruébelo: Números -> Letras o Letras -> Números


  • 2 4 bytes guardados gracias a obarakon , quien también me convenció para retomar esto después de que lo abandoné antes. ¡Ojalá no lo hubiera hecho!
  • 33 26 25 (!) Bytes se sacrificaron implementando una solución rápida (es decir, aún no se ha desarrollado completamente) para verificar la validez de la entrada.

Explicación

(Aún no se ha actualizado a la última versión)

                          :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
Lanudo
fuente
No parece manejar entradas no válidas comoAEI
Emigna
@Emigna: ¡Ah, maldita sea! ¡Imaginaría que después de ser quemado por la primera "Regla" inicialmente, habríamos pensado leer el resto de las reglas! : \ Tomé la sección "Qué es imposible" para dar a entender que no tendríamos que manejar ninguno de esos puntos.
Shaggy
2

Python 3 , 147 bytes

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)

Pruébalo en línea!

irapsaged
fuente
1

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

-2 bytes gracias a @Cyoce

-17 bytes más gracias a una idea de @Cyoce

-6 bytes gracias a @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;}

Pruébalo en línea!

Ugh, el reemplazo de Java es tan detallado.

Función que toma una cadena y devuelve la cadena traducida de número -> letra o viceversa. Se bloquea en una entrada no válida (puede ver esto en el ejemplo de tio donde se obtienen los valores correctos para los primeros 10 casos de prueba y luego se bloquea con un error de división por cero que se muestra en la vista de depuración)

Sin golf (el primer y el último término del bucle for se extraen para facilitar la lectura)

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

La expresión regular para hacer coincidir los números es simple, pero aquí está la expresión regular para hacer coincidir las letras con los números.

(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
fuente
No es que mejore significativamente su recuento masivo de bytes, pero puede eliminar los paréntesis(s)->
Cyoce
@Cyoce cada byte ayuda
PunPun1000
Dado que todas sus ramas de la ifdeclaración son asignaciones (que devuelven un valor), intente reemplazar el if... else if... elsecon el operador condicional ?:, prefacio Object _=para que sea una declaración válida. No estoy seguro de si esto realmente ayudaría al conteo de bytes, pero creo que lo hará.
Cyoce
Dos cosas pequeñas que puedes jugar al golf. Puede eliminar la cadena t, porque solo la usa una vez. Entonces se t.charAt(i)+""convierte en "OIREASGTBP".charAt(i)+""( -4 bytes ). Y puede colocar la última línea dentro del ciclo for después de la i<9;declaración dentro del ciclo for. Entonces se convierte en for(;i<9;s=b?s.replace(v,c):s.replace(c,v)){( -1 byte ). Ah, y también puedes poner el s=b?...que viene justo después del int i=-1;ciclo for: for(s=b?...;i<9;...( -1 byte ).
Kevin Cruijssen
1

PHP; 129 127 267 259 228 bytes

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

Ejecutar como tubería -nRo probarlo en línea .

Descompostura

$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
fuente
1

Java 8, 312 308 304 301 294 290 bytes

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 bytes (308 → 304) para una corrección de errores (no sucede a menudo que el recuento de bytes disminuya cuando soluciono un error en mi código ...: D)

EDITAR: utiliza un enfoque diferente al de la respuesta Java de @ PunPun1000 al crear primero la cadena de retorno en un ciclo for sobre los caracteres, y luego usa una expresión regular más abstracta para validarla en el ternario de retorno (la entrada es todos dígitos, o son las vocales y consonantes dadas alternadas (sin vocales ni consonantes adyacentes).

Explicación:

Pruébalo aquí.

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

La validación regex:

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

05AB1E , 76 bytes

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

Pruébalo en línea!

Devuelve el valor falso 0para una entrada no válida.

Emigna
fuente
0

Golpetazo ,241 238 235 bytes

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

Pruébalo en línea!

Menos golfizado:

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
marcom
fuente
0

PHP, 268 bytes

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

Pruébalo en línea!

Jörg Hülsermann
fuente
0

Perl, 127 bytes

Línea de comando de 126 bytes + 1 byte

$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

Uso:

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

Debe seguir todas las reglas de desafío: puede aceptar letras o números y producirá un error (división por cero) si falla la validación

Jarmex
fuente
La validación tiene falsos positivos en la entrada NOy US.
Value Ink
0

Rubí , 205 + 1 = 206 bytes

Utiliza la -pbandera para +1 byte. Ahora con un exhaustivo sistema de validación de entrada.

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)

Pruébalo en línea!

Tinta de valor
fuente
¡Esto no parece convertir letras en números, ni hace ninguna validación!
Jarmex
@Jarmex ¡Uy, validación agregada! Es una gran verificación de validación, pero no tengo muchas opciones al respecto
Value Ink el
0

Python 3, 741 bytes

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)

Pruébalo en línea!

Hay mucho margen de mejora, lo sé.

LyricLy
fuente
0

sed, 123 bytes

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

Explicación

Primero, rodeamos los dígitos con _(para vocales) o =(para consonantes).

Si no hicimos ninguna sustitución, estamos convirtiendo letras a dígitos, por lo que es una simple sustitución y eliminar U yN . Entonces déjalo.

De lo contrario, nos ramificamos para etiquetar a, donde tratamos con vocales consecutivas y luego consonantes consecutivas. Luego transforme los dígitos en letras y elimine los caracteres marcadores que presentamos en el primer paso.

Toby Speight
fuente
0

Python3, 246 bytes

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

explicación:

  • entrada de mapa a una lista de int
  • lista de mapas de int a su posición en el alfabeto
  • reducir la lista agregando acumulador, más un elemento de un dict tupla , más el elemento actual
    • La dict tuple es una tabla de verdad basada en dos elementos, ser vocal o no
Setop
fuente
0

JavaScript (ES6), 120

Una función que toma la entrada como una cadena. Devuelve la cadena traducida correctamente si la entrada es válida, de lo contrario es falsa o la función se bloquea.

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

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

Prueba

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
fuente