Numeri di telefono confusi


19

Sai come ricevi un messaggio vocale e la connessione della persona non era eccezionale, e stai cercando di capire come richiamarli, ma non sei sicuro che si trattasse di un "5" o di un "8" disse?

Questa è questa sfida.

La buona notizia è che il chiamante ha letto il loro numero due volte, ma è confuso in entrambi i posti.

Il tuo programma dovrebbe ricevere input in questo modo:

5551231234 / 5551231234

Dove le prime dieci cifre sono la prima volta che il numero di telefono viene detto nella segreteria telefonica e il secondo set è la seconda volta che viene detto. Solo ... sarà più simile a questo:

555?ABC1_36? / 55?522_1?234
  • Una cifra seguita da un punto interrogativo significa che è la migliore ipotesi per quella cifra (es. "5?" Significa "probabilmente un 5, confronta con ripetizione").
  • Un carattere di sottolineatura indica una cifra mancante nota, qualcosa di troppo confuso da elettricità statica per essere decifrato.
  • Le lettere sono proprio questo: lettere. Trattali come le loro rispettive cifre
    • ABC -> 2, DEF -> 3, GHI -> 4, JKL -> 5, MNO -> 6, PQRS -> 7, TUV -> 8, WXYZ -> 9
    • Tutti gli input di esempio usano maiuscole (puoi tranquillamente omettere una chiamata ToUpper ())
    • Se la tua lingua funziona meglio in minuscolo, puoi utilizzare liberamente le lettere minuscole per l'input e omettere una chiamata ToLower (). Basta notare che nella tua risposta.

Puoi anche assumere le seguenti chiamate di giudizio:

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

Inoltre, puoi presumere che tutti gli ingressi conterranno numeri di telefono a dieci cifre, esclusi i punti interrogativi. Gli input che non sono di dieci cifre (ad es. 1234567 / 1234567) Possono essere trattati come irrisolvibili (output di falsi) o generare un errore.

Ingresso

Una riga di caratteri 0-9A-Z _?/, come descritto sopra.

Produzione

Se può essere analizzato su un singolo numero di telefono a dieci cifre valido, emettere il numero di telefono. Altrimenti emette una qualche forma di indicazione di errore (ad es. -1, falso o una riga vuota).

Vittorie più brevi, come al solito.

Ingressi campione:

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

Ho solo assicurato che ogni possibile caso limite è coperto (le prime 11 voci), ma a parte questo, è praticamente casuale.

Aggiornare

Quattro voci in basso aggiunte con zeri iniziali (su suggerimento di Jonathan Allan).

Uscita corretta per gli ingressi campione:

https://pastebin.com/gbCnRdLV

Basato sull'output della voce di Jonathan Allan (l'output formattato era l'ideale).


Dobbiamo prendere gli input come una singola stringa, separati da " / "o possiamo semplicemente prenderli come due input standard?
L3viathan,

@ L3viathan Inizialmente avevo concepito l'idea di dover prendere una singola stringa.
Draco18s

7
@ Draco18s stringa singola non porta nulla alla sfida
f 22nɛtɪk

1
@ fəˈnɛtɪk Nessuno ha detto nulla nella sandbox, ma non ho nulla contro l' utilizzo delle coppie di input. Era il modo in cui l'ho concepito inizialmente.
Draco18s

1
Chi lascia un messaggio vocale usando le lettere per il proprio numero di telefono ?!
Jonathan Allan,

Risposte:


3

Gelatina , 84 byte

+4 byte - Penso che probabilmente dovrebbe comportarsi allo stesso modo in tutti i casi, quindi ho convertito i numeri interi di ricerca della tastiera in caratteri numerici usando +49Ọ.

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

Una funzione che accetta la stringa nel formato specificato e restituisce il numero di telefono come elenco di caratteri o zero se non valido. Come programma, questo viene stampato come se fosse una stringa.

Il modo in cui funziona potrebbe ripetere il numero più volte
(ad es. "123456789_ / 123456789_ / 1234567890")
... o anche dirlo una sola volta, e si applicherà la logica definita.

Provalo online! o vedere tutti gli input di esempio .

Come?

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

Sembra che ci possa essere un errore, 55_____088 / 54?2397207?7?dovrebbe risolversi in 5523972088: tutte le cifre mancanti sono presenti e le cifre incerte sulla destra sono disponibili sulla sinistra. Tutti i casi semplicistici però funzionano.
Draco18s

Ah, ho rimosso quello che pensavo fosse un filtro ridondante, non lo era. Riparazione ...
Jonathan Allan,

Ci sono già stato - e non era golf! ;)
Draco18s

Ooof che mi ha richiesto un po 'di tempo (ho trovato un bug diverso mentre lo stavo testando), lo ho riportato allo stesso conteggio dei byte come solo aggiungendo nuovamente il filtro quando lo risolvo così (wow).
Jonathan Allan,

@ Draco18s - ti sembra tutto a posto? Potrebbe essere utile fornire l'output previsto per i casi di test nella domanda, o forse semplicemente separare quelli non validi.
Jonathan Allan,

7

Python 2 , 314 307 274 byte

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="?"

Provalo online!


5

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

Sono sicuro che questo può essere migliorato, ma è un inizio:

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(" / "))

Sto usando str.translateper le lettere e una funzione wrapperg per creare gli input nel formato in cui li voglio. La funzione effettiva fè ricorsiva e fallirà per input ambigui. Ho ancora molte ripetizioni lì dentro, quindi sono sicuro che ci sia un sacco di spazio per migliorare.

miglioramenti:

  • salvato 19 byte combinando le condizioni
  • salvato 21 byte con ternari
  • salvato 56 byte usando una comprensione del dizionario invece del dizionario manuale, grazie a @TuukkaX
  • salvato 4 byte passando al metodo suggerito da @ovs, con il miglioramento di @ TuukkaX
  • salvato 38 byte con miglioramenti da @ovs (e l'ultimo spazio bianco rimovibile rimosso)
  • salvato 4 byte inserendo la definizione str.isnumericin un argomento di parola chiave
  • salvato 12 byte con operatori di confronto combinati (ad es. T==q!=O)
  • salvato 1 byte trasformandolo not(e or z)in e+z in(e,z).
  • salvato 2 byte salvando quello usato frequentemente (E,Z)

Questo contiene una comprensione del dizionario che non contiene i valori predefiniti della riga superiore. Odio le sequenze di 3, ma quelle potrebbero essere sostituite con la matematica.
Yytsi,


@ovs Nice. L'alfabeto può essere cambiato in map(chr,range(65,91))però.
Yytsi,

2
RE: Rendendo questo un wiki della comunità per rinunciare alla reputazione, il consenso sarebbe no , basta accettare il gentile aiuto e accreditarlo come hai fatto tu.
Jonathan Allan,

1
Lo giuro ogni volta che torno qui questa risposta si
riduce

3

JavaScript (ES6), 180 190 188 byte

Modificare: +10 +9 byte per rispettare la regola di output errata


Accetta le due stringhe di input nella sintassi del curry (a)(b) . Restituisce uno falseo una stringa che rappresenta il numero di telefono indovinato.

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

Come funziona

Passaggio n. 1: analisi delle stringhe di input

Definiamo prima il F() funzione che traduce una stringa in un array di numeri interi applicando le seguenti regole:

  • il carattere di sottolineatura viene convertito in 0
  • viene convertita una cifra N o una lettera equivalente (N + 1) OPPURE 16 (ad es. "2" → 19, "R" → 24)
  • una cifra N o una lettera equivalente seguita da un segno di interrogazione viene convertita in N + 1 (ad es. "2?" → 3, "R?" → 8)

Che può essere interpretato al contrario come segue:

  • 0sconosciuto
  • [ 1 .. 10 ]inaffidabile
  • [ 17 .. 26 ] affidabile

Facciamo domanda F()per entrambi ae b. Questo ci dà una coppia di numeri interi (x, y) per ogni cifra nel numero di telefono, corrispondente alle due possibili interpretazioni.

Passaggio 2: indovinare le cifre

Per ogni coppia (x, y) , calcoliamo:

  • d = x XOR y
  • x = MAX (x, y) → i valori affidabili sono sempre preferiti a quelli inaffidabili

Se x == 0 , significa che entrambi gli input sono caratteri di sottolineatura. Quindi, la cifra non è nota in questo caso.

Se x! = 0 , possiamo tranquillamente dedurre la cifra se una delle seguenti condizioni è vera:

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

Le ultime due condizioni possono essere unite !(d % x). Da qui la formula finale:

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

Se vero, riconvertiamo x nella cifra indovinata calcolando (x - 1) E 15 .

Casi test

(Solo i primi 50 perché lo snippet della console non supporta più cronologia di output.)


1234567890? / 1234567890?dovrebbe risolvere a 1234567890. In questo momento il tuo codice genera un output 123456789?che è persino meno informativo dell'input. Assume: 5? / 5? -> 5 //uncertain, but matching
Draco18s

@ Draco18s Contrariamente a quanto affermato, ho incluso 51 casi di test. Quindi il primo è stato abbandonato e tutto è cambiato di una riga. (Ora risolto. Mi dispiace per quello.)
Arnauld

Aaah. Tuttavia, dovrebbe generare una sorta di falsità o valore di errore per questi casi di test. Ma per il resto sembra buono.
Draco18s

2

Perl 5 , 211 byte

... senza rientri e \ n righe

@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

Provalo online!


Sembra che restituisca "il meglio che può" ( 83652618?0) piuttosto che una sorta di falsità o valore di errore.
Draco18s

Qual è ciò che il puzzle voleva se non sbaglio. Guarda i casi sotto l'intestazione "Puoi inoltre assumere le seguenti sentenze". O no?
Kjetil S.

Siamo spiacenti, non ho mai ricevuto una notifica della tua risposta (nessuna menzione). La sezione che avevo fatto per le chiamate di giudizio usa a ?per indicare che non c'è modo di risolvere le informazioni mancanti, che dovrebbero quindi passare alla sezione Output:...Otherwise output some form of error indication (e.g. -1, false, or an empty line).
Draco18s

2

Retina, 150 140 136 byte

Risparmio di pochi byte grazie a Kritixi Lithos

T`?L`#22233344455566677778889
./.

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

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

Provalo online!

Spiegazione:

La prima riga trasforma tutto ?in input #e tutte le lettere nei loro equivalenti numerici. Quindi rimuoviamo gli spazi e /dall'input. Le prossime due righe si occuperanno dei casi "indovinare contro certezza" (es. 5? \ 4Sarebbero sostituiti da 4 \ 4) Dopo aver rimosso tutte le #s, le righe 8 e 9 trattano i _casi "numero vs. " (_ \ 3 diventa 3 \ 3). Quindi, se entrambe le metà della stringa corrispondono, manteniamo le prime 10 cifre. Altrimenti, il numero di telefono non è valido, quindi rimuoviamo tutto.

Soluzione alternativa a 160 byte che funziona con numeri di telefono di lunghezza arbitraria (e dimensioni uguali): TIO


È possibile modificare (/|_)in [/_]per salvare 1 byte. Inoltre penso che tu possa usare ;invece xche così [^x]può diventare\w
Kritixi Lithos il

1

PHP, 251 236 byte

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:"?";

accetta input dalla riga di comando; corri con -nro provalo online .

abbattersi

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

golfings

  • preg_replace primo: -8 byte
  • join: -2
  • $$kanziché $t[$k]: -5

1

PHP, 200 + 8 byte

ispirato alla soluzione di 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);

accetta input dagli argomenti della riga di comando; corri con -nro provalo online .

modifiche per rispettare la limitazione dell'output di errore: (stampare Xper un numero incompleto):

  • rimuovi |48(-3 byte)
  • sostituire echo chr(...);con$r.=...;echo$r>1e10?X:$r; (+11 byte)

abbattersi

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

golfings

  • aggirare preg_replace_callback(-10 byte)
  • fare affidamento su un input di 10 cifre (-9)
  • e golf aggiuntivo (-8)
  • rimosso joindelimitatore (-7)
  • spostato il $xcompito alla fine (-2)

1

Perl 5 -pl , 173 byte

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=!/_/

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.