Números telefónicos ilegibles

19

Usted sabe cómo recibe un mensaje de correo de voz y la conexión de la persona no fue excelente, y está tratando de encontrar la manera de devolverle la llamada, pero no está seguro de si fue un "5" o un "8". ¿dijo?

Ese es este desafío.

La buena noticia es que la persona que llama leyó su número dos veces, pero está confuso en ambos lugares.

Su programa debería recibir información como esta:

5551231234 / 5551231234

Donde los primeros diez dígitos son la primera vez que se dice el número de teléfono en el correo de voz y el segundo conjunto es la segunda vez que se dice. Solo que ... se verá más así:

555?ABC1_36? / 55?522_1?234
  • Un dígito seguido de un signo de interrogación significa que esa es la mejor suposición para ese dígito (por ejemplo, "5?" Significa "probablemente un 5, comparar con repetir").
  • Un guión bajo indica un dígito faltante conocido, algo demasiado borroso por la estática para ser descifrado.
  • Las letras son solo eso: letras. Trátelos como sus respectivos dígitos
    • ABC -> 2, DEF -> 3, GHI -> 4, JKL -> 5, MNO -> 6, PQRS -> 7, TUV -> 8, WXYZ -> 9
    • Todas las entradas de muestra usan mayúsculas (puede omitir de manera segura una llamada ToUpper ())
    • Si su idioma funciona mejor en minúsculas, puede usar libremente minúsculas para la entrada y omitir una llamada a ToLower (). Solo tenga en cuenta eso en su respuesta.

También puede asumir las siguientes llamadas de juicio:

5? / _     -> 5  //5 is the best guess we have, use it
5? / 5?    -> 5  //uncertain, but matching
5? / 4?    -> ?  //conflict
 5 / 4     -> ?  //conflict
5? / 4     -> 4  //solid information overrides possible value
 5 / 4?    -> 5  //solid information overrides possible value
 _ / _     -> ?  //no information available

Además, puede suponer que todas las entradas contendrán números de teléfono de diez dígitos, sin incluir los signos de interrogación. Las entradas que no tienen diez dígitos (p 1234567 / 1234567. Ej. ) Pueden tratarse como insolubles (salida falsey) o generar un error.

Entrada

Una línea de caracteres 0-9A-Z _?/, como se describió anteriormente.

Salida

Si se puede analizar a un único número de teléfono válido de diez dígitos, envíe el número de teléfono. De lo contrario, muestra alguna forma de indicación de error (por ejemplo, -1, falso o una línea vacía).

Las victorias más cortas, como de costumbre.

Entradas de muestra:

1234567890 / 1234567890
1234567890? / 1234567890
123456789_ / 1234567890
1234567890? / 123456789_
1234567890 / 1234567890?
1234567890 / 123456789_
123456789_ / 1234567890?
1234567890? / 1234567890?
1234567890? / 1234567891?
123456789_ / 123456789_
555CALLUS1 / 5552255871
404_12?6039 / 4041?1560_9
_GETREVENGE / 16?36?_2838_
1?691460_50 / 16_14609?50
61?08977211 / 612?897725?1
40?0INSTA__ / 8?00_NSTI?LL
3985_534?10 / 39?8?5053_10
7__7294?737 / 7797299?_37
28?897_384?1 / _8?89763861
271168090_ / 27116800?09
6802?148343 / 67?01148343
94_11628?2?6? / 9491162_47?
17?4285_689 / 1__26?52689
6_311?95_38 / 6731194?7?38
380?7DRAGON / 3807378?5?66
4?647_93236 / 5646?6?9__36
365?268898_ / 366267?7?984
GRATEDBATE / IRATEDBATE
5307_079?93 / ____8_____
535_3_0255 / 52?5_3_024?5
55_____088 / 54?2397207?7?
6_48398_95 / _946?398?6_5?
_0_312_3_1 / 81?53123?1?71
____1_____ / 64?255?508?61
8427820607 / 6?424?8?__6?07
50_3707__6 / 52?8375?74?56
615___8255 / 62?526?983?2?1?
__652618__ / 8365261__0
149___933_ / 1_9677?92?31
___7?281562 / 3438?28154?2
5?7?7?___8?3?7?4 / 57_855837_
605_272481 / 605427__81
86?569__731 / 88560?0?7721
1__91654?15 / 17?9?9165715
800NWABODE / 80069ABI?DE
8___9017_0 / 8_2494?12?9_
_024?5?91?470 / 304?17908?7_
42510704_2 / 4_51070492
9338737_89 / 93_873PLUS
327762_401 / 327_MASH01
33093_2058 / 3309_12058
4061_33578 / 40619_3578
559_383197 / 559938_197
94_9746084 / 9459746_84
1_37655238 / 163POLKA_T
_672FRIZZY / 767237499_
8_76318872 / TIP63188_2
51_8404321 / 5178404_21
358_030314 / 358603_314
2597_85802 / 25979_5802
77141_1408 / 7714_91408
330858_457 / 330_586457
4686079_39 / 46_6079239
86457508_6 / 8_45750826
523226626_ / _23BANNANA
_ISSY_ISSY / 44__9548?79?
6?00B_YJILT / 800289KILL?
2?52803___0 / 1526?0390?61?
FI?ND___T?HE / EAS?T?EREGGS?
0_231?95_38 / 0723194?7?38
0?647_39236 / 0646?6?3__36
025?267798_ / 06?6265?9?984
0061_33578 / _0619_3578

Solo me aseguré de que todos los casos límite posibles están cubiertos (las primeras 11 entradas), pero aparte de eso, es bastante aleatorio.

Actualizar

Cuatro entradas en la parte inferior agregadas con ceros a la izquierda (a sugerencia de Jonathan Allan).

Salida correcta para las entradas de muestra:

https://pastebin.com/gbCnRdLV

Basado en la salida de la entrada de Jonathan Allan (la salida formateada era ideal).

Draco18s
fuente
¿Tenemos que tomar las entradas como una sola cadena, separadas por " / ", o podemos simplemente tomarlas como dos entradas estándar?
L3viathan
@ L3viathan Originalmente había concebido la idea de tener que tomar una sola cadena.
Draco18s
77
@ La cadena única de Draco18s no aporta nada al desafío
fəˈnɛtɪk
1
@ fəˈnɛtɪk Nadie dijo nada en el sandbox, pero no tengo nada en contra de usar pares de entrada. Fue exactamente como lo concebí originalmente.
Draco18s
1
¿Quién deja un mensaje de voz usando letras para su número de teléfono?
Jonathan Allan

Respuestas:

3

Jalea , 84 bytes

+4 bytes: creo que probablemente debería comportarse igual en todos los casos, por lo que he convertido los enteros de búsqueda del teclado a caracteres de dígitos usando +49Ọ.

”?e‘ḣ@µ”_eḤ‘ẋ@
;Ṃµ68DṬ+3RØAṁẇ@€FT+49Ọȯµ€Fṡ2i”?Ḃ$ÐḟÇ€
ḟ⁶ṣ”/Ç€ZLÐṂ€Q€LỊ$ÐfF€Ḣ€ḟ”_µL⁼⁵ȧ

Una función que toma la cadena en el formato especificado y devuelve el número de teléfono como una lista de caracteres o cero si no es válido. Como programa, esto se imprime como si fuera una cadena.

La forma en que funciona podrían repetir el número más veces
(por ejemplo "123456789_ / 123456789_ / 1234567890")
... o incluso solo decirlo una vez, y se aplicará la lógica definida.

Pruébalo en línea! , o ver todas las entradas de muestra .

¿Cómo?

”?e‘ḣ@µ”_eḤ‘ẋ@ - Link 1, helper to vary the length of a 2-slice: list s
”?             - literal '?'
  e            - exists in s                   (1 or 0)
   ‘           - increment                     (2 or 1)
    ḣ@         - head with reversed @rguments  (s or s[:1] - removes 2nd value if not '?')
      µ        - monadic chain separation, call that t
       ”_      - literal '_'
         e     - exists in t                   (1 or 0)
          Ḥ    - double                        (2 or 0)
           ‘   - increment                     (3 or 1)
            ẋ@ - repeat t that many times      (t*3 or t - [`_`]->['_','_','_'])

;Ṃµ68DṬ+3RØAṁẇ@€FT+49Ọȯµ€Fṡ2i”?Ḃ$ÐḟÇ€ - Link 2, reformat a phone number: char list of [0-9][A-Z], p
;                                     - concatenate p with
 Ṃ                                    - minimum of p - (?<_<0<1<...<9<A<...<Z - never "?" however, since it only follows a digit.)
                                      -   - this is simply to make a 2-slice with the last character on the left, as used at the very end of this link.
  µ                                   - monadic chain separation call that q
                       µ€             - monadic chain separation, for €ach v in q do:
   68                                 -   literal 68
     D                                -   cast to a decimal list -  [6,8]
      Ṭ                               -   untruth                -  [0,0,0,0,0,1,0,1]
       +3                             -   add 3                  -  [3,3,3,3,3,4,3,4]
         R                            -   range                  -  [[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3,4],[1,2,3],[1,2,34]]
          ØA                          -   uppercase alphabet     -  ABCDEFGHIJKLMNOPQRSTUVWXYZ
            ṁ                         -   mould like the range ^ -  [ABC,DEF,GHI,JKL,MNO,PQRS,TUV,WXYZ]
             ẇ@€                      -   sublist v exists in that? for €ach, with reversed @rguments
                F                     -   flatten        (e.g. 'E' -> [0,1,0,0,0,0,0,0]; '4' -> [0,0,0,0,0,0,0,0]
                 T                    -   truthy indexes (e.g. 'E' -> [2]; '4' -> [])
                  +49                 - add 49
                     Ọ                - cast to character
                      ȯ               -   or             (e.g. 'E' -> [3]; '4' -> '4')
                         F           - flatten
                          ṡ2          - all slices of length 2
                                 Ðḟ   - filter discard if:
                                $     -   last two links as a monad:
                            i         -     first index of
                             ”?       -     literal '?'   (first index returns 0 if none exists)
                               Ḃ      -   mod 2 (so this filter discards pairs starting with '?')
                                   Ç€ - call the last link (1) as a monad for €ach slice

ḟ⁶ṣ”/Ç€ZLÐṂ€Q€LỊ$ÐfF€Ḣ€ḟ”_µL⁼⁵ȧ - Main link: string (or char list) s
ḟ                               - filter discard any:
 ⁶                              - literal ' '
  ṣ                             - split on:
   ”/                           - literal '/'
     Ç€                         - call the last link (2) as a monad for €ach
       Z                        - transpose
         ÐṂ€                    - filter, for €ach, keep items with minimal:
        L                       -   length
            Q€                  - de-duplicate €ach
                 Ðf             - filter keep items with:
                $               - last two links as a monad:
              L                 -   length
               Ị                -   insignificant? (=1 effectively here)
                   F€           - flatten €ach
                     Ḣ€         - head €ach
                       ḟ        - filter discard any of:
                        ”_      -   literal '_'
                          µ     - monadic chain separation, call that r
                           L    - length(r)
                             ⁵  - literal 10
                            ⁼   - equal?
                              ȧ - and r (0 if r did not result in a 10-digit list, else r)
Jonathan Allan
fuente
Parece que puede haber un error, 55_____088 / 54?2397207?7?debe resolverse a 5523972088: todos los dígitos faltantes están presentes y los dígitos inciertos a la derecha están disponibles a la izquierda. Sin embargo, todos los casos simplistas se ejecutan.
Draco18s
Ah, eliminé lo que pensé que era un filtro redundante, no lo era. Arreglando ...
Jonathan Allan
He estado allí antes, ¡y no era golf! ;)
Draco18s
Ooof que me tomó un tiempo (encontré un error diferente mientras lo estaba probando), lo recuperé al mismo número de bytes que simplemente agregando el filtro cuando lo solucioné (sí).
Jonathan Allan
@ Draco18s: ¿te parece bien todo? Podría ser bueno dar el resultado esperado para los casos de prueba en la pregunta, o tal vez simplemente separar los inválidos.
Jonathan Allan
7

Python 2 , 314 307 274 bytes

lambda s:g(*''.join(q<n<"["and`(int(n,36)-4-(n>"R")-(n>"Y"))//3`or n for n in s).split(" / "))
def g(a,b,s=str.startswith):
 if b:c,d,e,f=a[0],a[1:],b[0],b[1:];b=(c==e and[c,q][c=="_"]or"_"in c+e and min(c,e)or[q,c,e][s(f,q)-s(d,q)])+g(d[s(d,q):],f[s(f,q):])
 return b
q="?"

Pruébalo en línea!

ovs
fuente
5

Python 3, 549 530 509 453 449 410 406 394 393 391 bytes

Estoy seguro de que esto se puede mejorar, pero es un comienzo:

def f(e,z,q="?",u=str.isnumeric):
 if e+z in(e,z):return""
 o,O,t,T,*x=e[0],e[1:2],z[0],z[1:2],e[1:],z[1:]
 if"?"in o+t:return f([e,x[0]][o==q],z)
 if u(o):
  if u(t):return t+f(*x)if O==q!=T else o+f(*x)if o==t or T==q!=O else 1
  return o+f(*x)
 if u(t):return t+f(*x)
def g(s):
 for a,b in zip(map(chr,range(65,91)),"2223334445556667777888999"):s=s.replace(a,b)
 return f(*s.split(" / "))

Estoy usando str.translatelas letras y una función de contenedor gpara hacer las entradas en el formato en el que las quiero. La función real fes recursiva y fallará para entradas ambiguas. Sin embargo, todavía tengo muchas repeticiones allí, así que estoy seguro de que hay mucho margen de mejora.

Mejoras:

  • ahorró 19 bytes combinando condiciones
  • guardado 21 bytes con ternaries
  • ahorró 56 bytes usando una comprensión del diccionario en lugar del diccionario manual, gracias a @TuukkaX
  • ahorró 4 bytes al cambiar al método sugerido por @ovs, con la mejora de @ TuukkaX
  • ahorró 38 bytes con mejoras de @ovs (y se eliminó el último espacio en blanco extraíble)
  • ahorró 4 bytes poniendo definición str.isnumericen un argumento de palabra clave
  • guardado 12 bytes con operadores de comparación combinados (por ejemplo T==q!=O)
  • guardado 1 byte al convertirse not(e or z)en e+z in(e,z).
  • ahorró 2 bytes al guardar los de uso frecuente (E,Z)
L3viatán
fuente
Esto contiene una comprensión del diccionario que no contiene los valores predeterminados de la fila superior. Odio las secuencias de 3, pero podrían reemplazarse con matemáticas.
Yytsi
@ovs Nice. Sin map(chr,range(65,91))embargo, el alfabeto se puede cambiar a .
Yytsi
2
RE: Haciendo de este un wiki comunitario para renunciar a la reputación, el consenso sería no , solo acepte la amable ayuda y acéptelo como lo ha hecho.
Jonathan Allan
1
Juro que cada vez que vuelvo aquí esta respuesta se
acorta
3

JavaScript (ES6), 180 190 188 bytes

Editar: +10 +9 bytes para cumplir con la regla de salida falsa


Toma las dos cadenas de entrada en sintaxis de curry (a)(b). Devuelve falseo una cadena que representa el número de teléfono adivinado.

a=>b=>!(s=(F=a=>a.match(/(.\??)|_/g).map(([x,y])=>(x<=9?++x:parseInt(x,36)*.32-(x>'Y'))|(x!='_'&!y)*16))(a).map((x,i)=>(x=(d=x^(y=F(b)[i]),x>y)?x:y)&&(d&16|!(d%x))?--x&15:a).join``)[10]&&s

Cómo funciona

Paso # 1 - Analizando las cadenas de entrada

Primero definimos la F()función que traduce una cadena en una matriz de enteros aplicando las siguientes reglas:

  • el guión bajo se convierte a 0
  • un dígito N o una letra equivalente se convierte en (N + 1) O 16 (por ejemplo, "2" → 19, "R" → 24)
  • un dígito N o una letra equivalente seguida de un signo de interrogación se convierte a N + 1 (por ejemplo, "2?" → 3, "R?" → 8)

Que puede interpretarse al revés de la siguiente manera:

  • 0 desconocido
  • [ 1 .. 10 ]poco confiable
  • [ 17 .. 26 ]confiable

Aplicamos F()a ambos ay b. Esto nos da un par de enteros (x, y) para cada dígito en el número de teléfono, correspondientes a las dos posibles interpretaciones.

Paso # 2 - Adivinando los dígitos

Para cada par (x, y) , calculamos:

  • d = x XOR y
  • x = MAX (x, y) siempre se prefieren valores confiables a valores no confiables

Si x == 0 , significa que ambas entradas son caracteres de subrayado. Entonces, el dígito es desconocido en este caso.

Si x! = 0 , podemos deducir con seguridad el dígito si se cumple una de las siguientes condiciones:

condition       | interpretation
----------------+------------------------------------------------------
(d AND 16) != 0 | one input is unreliable and the other one is reliable
d == 0          | both inputs are identical
d == x          | one input is an underscore

Las dos últimas condiciones se pueden combinar !(d % x). De ahí la fórmula final:

x && (d & 16 || !(d % x))

Si es verdadero, convertimos x nuevamente al dígito adivinado calculando (x - 1) Y 15 .

Casos de prueba

(Solo los 50 primeros porque el fragmento de consola no puede admitir más historial de salida).

Arnauld
fuente
1234567890? / 1234567890?debe resolver a 1234567890. En este momento, su código sale, lo 123456789?que es aún menos informativo que la entrada. Assume: 5? / 5? -> 5 //uncertain, but matching
Draco18s
@ Draco18s Al contrario de lo que dije, incluí 51 casos de prueba. Así que el primero se dejó caer y todo cambió una fila. (Ahora arreglado. Perdón por eso.)
Arnauld
Aaah Aún así, debería generar algún tipo de valor de error o falsa para esos casos de prueba. Pero por lo demás se ve bien.
Draco18s
2

Perl 5 , 211 bytes

... sin sangría y \ n líneas nuevas

@i=map{y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/22233344455566677778889999/;$_}split' / ',shift;
print map{
  $_=join'',map{s,(\d\??|_),,;$1}@i;
  /((\d)\??\2\??|(\d)\??_|_(\d)\??|(\d)\d\?|\d\?(\d))$/;$2//$3//$4//$5//$6//'?'
}1..10

Pruébalo en línea!

Kjetil S.
fuente
Parece que está devolviendo "lo mejor que puede" ( 83652618?0) en lugar de algún tipo de valor falso o de error.
Draco18s
Que es lo que el rompecabezas quería si no me equivoco. Mire los casos bajo el encabezado "También puede asumir las siguientes llamadas de juicio". ¿O no?
Kjetil S.
Lo sentimos, nunca recibí una notificación de su respuesta (sin mencionar). La sección que hice para las llamadas de juicio utiliza un ?para indicar que no hay forma de resolver la información faltante, que luego debe pasar a la sección Salida:...Otherwise output some form of error indication (e.g. -1, false, or an empty line).
Draco18s
2

Retina, 150 140 136 bytes

Guardado algunos bytes gracias a Kritixi Lithos

T`?L`#22233344455566677778889
./.

(?<=(\d)(\w#?){9}).#|.#(?=(\w#?){9}(\d)(?!#))
$1$4
#

_(?=.{9}(.))|(?<=(.).{9})_
$1$2
^(\d*)\1$|.*
$1

Pruébalo en línea!

Explicación:

La primera línea transforma todo ?en la entrada #y todas las letras en sus equivalentes numéricos. Luego eliminamos los espacios y /de la entrada. Las siguientes dos líneas se ocupan de los casos de "conjetura versus certeza" (por ejemplo 5? \ 4, serían reemplazados por 4 \ 4). Después de eliminar todos los #s, las líneas 8 y 9 tratan con los _casos "número vs. " (se _ \ 3convierte 3 \ 3). Luego, si ambas mitades de la cadena coinciden, conservamos los primeros 10 dígitos. De lo contrario, el número de teléfono no es válido, por lo que eliminamos todo.

Solución alternativa de 160 bytes que funciona para números de teléfono de longitud arbitraria (e igual tamaño): TIO

adicto a las matemáticas
fuente
Puede cambiar (/|_)a [/_]para guardar 1 byte. También creo que se puede utilizar ;en lugar de xpor lo que [^x]puede llegar a ser\w
Kritixi Lithos
1

PHP, 251 236 bytes

for(;a&$c=preg_replace(["#[^_?](?!\?)#","#_#"],["$0k","?<"],join("-",$argv))[++$i];)${$k+="-"==$c}.=$c<_&$c>=A?0|(ord($c)-($c>W)-($c>P)-59)/3:$c;for(;$c=${1}[$k+1];)echo($n=${1}[$k])==($m=${2}[$k++])|($b=${2}[$k++])!=$c?$c>$b?$n:$m:"?";

toma entrada de la línea de comando; ejecutar -nro probarlo en línea .

Descompostura

# A: transform input
                                    # 2. replace single chars with two-character chunk and make sortable:
                                    #   replace "_" with "?<", append "k" to everything else not followed by "?"
for(;a&$c=preg_replace(["#[^_?](?!\?)#","#_#"],["$0k","?<"],join("-",$argv))[++$i];)    # (unknown "<" < unsure "?" < certain "k")
${$k+="-"==$c}.=                # if "-", next argument
        $c<_&$c>=A              # if letter
            ?0|(ord($c)-($c>W)-($c>P)-59)/3 # then translate to digit
            :$c                             # else don´t
    ;
# B: evaluate
for(;$c=${1}[$k+1];)            # loop through arguments: $c=command 2
    echo
        ($n=${1}[$k])                   # $n=digit 2
        ==                          # if digits are equal
        ($m=${2}[$k++])                 # $m=digit 3
        |
        ($b=${2}[$k++])             # $b=command 3
        !=$c                        # or "commands" are not
            ?$c>$b?$n:$m            # then get the one with the more definitive "command"
            :"?"                    # else conflict/unknown
    ;

campos de golf

  • preg_replace primero: -8 bytes
  • join: -2
  • $$ken lugar de $t[$k]: -5
Titus
fuente
1

PHP, 200 + 8 bytes

inspirado en la solución Arnaulds .

for($s=join($argv);$c=ord($s[$i++]);$i+=$x)$t[]=$c>90?63:15&($c<65?$c:($c-($c>80)-($c>87)-59)/3)|16*$x="?"==$s[$i];for(;$p++<10;)echo chr(($e=$t[$p]^$d=$t[$p+10])&48|!(15&$e)?min($t[$p],$d)&15|48:63);

toma datos de los argumentos de la línea de comandos; ejecutar -nro probarlo en línea .

modificaciones para cumplir con la restricción de salida de error: (imprimir Xpara un número incompleto):

  • eliminar |48(-3 bytes)
  • reemplazar echo chr(...);con $r.=...;echo$r>1e10?X:$r;(+11 bytes)

Descompostura

for($s=join($argv);$c=ord($s[$i++]);    # loop through characters of arguments
    $i+=$x)                             # skip "?"
$t[]=
    $c>90                               # if "_"
        ?63                             # then 32+16+15
        :                               # else
            15&(                            # lower 4 bits of
            $c<65                               # if digit
            ?$c                                 # then digit
            :($c-($c>80)-($c>87)-59)/3          # else letter mapped to digit
        )
        |16*$x="?"==$s[$i]                  # if next char is "?", add 16
;
for(;$p++<10;)echo chr( # loop through translated arguments
    (
        $e=$t[$p]^      # 2. $e=difference
        $d=$t[$p+10]    # 1. $d=char from 2nd argument
    )&48                # if certainties differ
    |!(15&$e)           #    or digits do not
    ?min($t[$p],$d)&15|48   # then pick the more definite digit (15|48 -> "?")
    :63             # else "?"
);

campos de golf

  • evitar preg_replace_callback(-10 bytes)
  • confiar en la entrada de 10 dígitos (-9)
  • y golf adicional (-8)
  • remoto joindelimitador (-7)
  • $xAsignación movida al final (-2)
Titus
fuente
1

Perl 5 -pl , 173 bytes

sub t{$_=pop;y/A-Z/22233344455566677778889999/;/_|\d\??/g}@e=m|\S+|g;@a=t$e[0];$_=join"",map{$_.=shift@a;s/^(.+)\1$/$1/||s/_//||s/..../_/||s/.\?//;$_}t$e[2];s/\?//;$_ x=!/_/

Pruébalo en línea!

Xcali
fuente