Скарбовані телефонні номери


19

Ви знаєте, як ви отримуєте повідомлення голосової пошти, і зв’язок людини не був чудовим, і ви намагаєтесь зрозуміти, як їх передзвонити, але ви не впевнені, чи це "5" чи "8" сказав?

Ось цей виклик.

Хороша новина полягає в тому, що той, хто телефонує, зчитував їх номер двічі, але це зібрано в обох місцях.

Ваша програма повинна взяти такий вклад:

5551231234 / 5551231234

Якщо перші десять цифр - це перший раз, коли телефонний номер промовляється в голосовій пошті, а другий - вдруге. Тільки ... це буде виглядати приблизно так:

555?ABC1_36? / 55?522_1?234
  • Цифра, що супроводжується знаком питання, означає, що це найкраща здогадка для цієї цифри (наприклад, "5?" Означає "ймовірно, 5, порівняти з повтором").
  • Підкреслення вказує на відому пропущену цифру, щось занадто розмите статикою, щоб її взагалі розшифрувати.
  • Листи - це саме те, що: букви. Ставтесь до них як до відповідних цифр
    • ABC -> 2, DEF -> 3, GHI -> 4, JKL -> 5, MNO -> 6, PQRS -> 7, TUV -> 8, WXYZ -> 9
    • Усі вхідні зразки використовують великі регістри (ви можете сміливо опускати виклик ToUpper ())
    • Якщо ваша мова краще працює в нижньому регістрі, ви можете вільно використовувати малі літери для введення та опускати виклик ToLower (). Просто зауважте, що у своїй відповіді.

Ви також можете припустити наступні виклики рішення:

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

Крім того, ви можете припустити, що всі входи містять десятизначні телефонні номери, не включаючи знаки запитання. Вхідні дані, які не мають десяти цифр (наприклад 1234567 / 1234567), можуть бути розцінені як нерозв'язні (фальсифікований вихід) або помилка.

Вхідні дані

Один рядок символів 0-9A-Z _?/, як описано вище.

Вихідні дані

Якщо його можна розібрати на один дійсний десятизначний номер телефону, виведіть номер телефону. В іншому випадку виведіть певну форму вказівки на помилку (наприклад, -1, помилковий або порожній рядок).

Найкоротші виграші, як зазвичай.

Зразки входів:

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

Я лише страхував, що всі можливі кращі випадки висвітлюються (перші 11 записів), але крім цього, це набагато випадково.

Оновлення

Чотири записи внизу додані з провідними нулями (за пропозицією Джонатана Аллана).

Правильний вихід для зразків входів:

https://pastebin.com/gbCnRdLV

Виходячи з результатів запису Джонатана Аллана (форматований вихід був ідеальним).


Чи потрібно приймати входи як єдиний рядок, відокремлений " / ", або ми можемо просто прийняти їх як два стандартних введення?
L3viathan

@ L3viathan Я спочатку задумував ідею як необхідність взяти одну струну.
Draco18s

7
@ Один рядок Draco18s нічого не викликає у виклик
fəˈnɛtɪk

1
@ fəˈnɛtɪk У пісочниці ніхто нічого не сказав, але я не маю нічого проти використання вхідних пар. Це було саме так, як я спочатку це задумав.
Draco18s

1
Хто залишає голосову пошту, використовуючи літери для свого номера телефону ?!
Джонатан Аллан

Відповіді:


3

Желе , 84 байти

+4 байти - Я думаю, що він, ймовірно, повинен вести себе однаково у всіх випадках, тому я перетворив цілі числа пошуку клавіатури назад у цифрові символи, використовуючи +49Ọ.

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

Функція, яка приймає рядок у визначеному форматі і повертає номер телефону у вигляді списку символів або нуля, якщо недійсний. Як програма, це друкується так, ніби це рядок.

Те, як це працює, вони могли повторити число більше разів
(наприклад "123456789_ / 123456789_ / 1234567890")
... або навіть сказати це лише один раз, і визначена логіка буде застосована.

Спробуйте в Інтернеті! або переглянути всі зразки даних .

Як?

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

Схоже, може виникнути помилка, 55_____088 / 54?2397207?7?слід вирішити 5523972088: всі пропущені цифри присутні, а невизначені цифри праворуч - зліва. Усі спрощені випадки працюють.
Draco18s

Ах, я зняв те, що, на мою думку, було зайвим фільтром, це не було. Виправлення ...
Джонатан Аллан

Був там раніше - і це був не гольф! ;)
Draco18s

Отож, це зайняло мене деякий час (я виявив іншу помилку, коли я її тестував), повернув її до того ж байтового числа, що й лише додавання фільтра, коли виправляв це так (коли).
Джонатан Аллан

@ Draco18s - чи все тобі добре виглядає? Було б добре дати очікуваний результат для тестових випадків у питанні, а може, просто відокремити недійсні.
Джонатан Аллан

7

Python 2 , 314 307 274 байт

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

Спробуйте в Інтернеті!


5

Пітон 3, 549 530 509 453 449 410 406 394 393 391 байт

Я впевнений, що це можна вдосконалити, але це початок:

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

Я використовую str.translateдля букв і функцію обгортки, gщоб зробити введення у тому форматі, в якому я їх хочу. Фактична функція fє рекурсивною і не працює при неоднозначних введеннях. У мене все ще багато повторень, тому я впевнений, що є багато можливостей для вдосконалення.

Покращення:

  • збережено 19 байт шляхом комбінування умов
  • врятували 21 байт з тернарями
  • збережено 56 байт, використовуючи розуміння словника замість словника вручну, завдяки @TuukkaX
  • зберегли 4 байти, перейшовши на метод, запропонований @ovs, з удосконаленням @ TuukkaX
  • збережено 38 байт з поліпшеннями від @ovs (і останнє знімне пробіл видалено)
  • збережено 4 байти, додавши визначення str.isnumericв аргумент ключового слова
  • збережено 12 байт із комбінованими операторами порівняння (наприклад T==q!=O)
  • збережено 1 байт, перетворившись not(e or z)на e+z in(e,z).
  • збережено 2 байти, зберігаючи часто використовувані (E,Z)

Це містить розуміння словника, яке не містить стандартних значень верхнього рядка. Я ненавиджу послідовності 3, але вони можуть бути замінені математикою.
Yytsi


@ovs Nice. Алфавіт можна змінити на map(chr,range(65,91))хоч.
Yytsi

2
RE: Зробити цю вікі-спільноту для відмови від репутації, консенсусу було б ні , просто прийміть добру допомогу та зарахуйте її як ви.
Джонатан Аллан

1
Я клянусь, щоразу, коли я повертаюся сюди, ця відповідь стає коротшою: D
Draco18s

3

JavaScript (ES6), 180 190 188 байт

Редагувати: +10 +9 байт, щоб відповідати правилу ложних даних


Займає два вхідні рядки в синтаксисі currying (a)(b). Повертає falseабо рядок, або репрезентативний номер телефону.

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

Як це працює

Крок №1 - Розбір рядків введення

Спочатку визначаємо F()функцію, яка переводить рядок у масив цілих чисел, застосовуючи такі правила:

  • підкреслення перетворюється на 0
  • цифра N або еквівалентна літера перетворюється в (N + 1) АБО 16 (наприклад, "2" → 19, "R" → 24)
  • цифра N або еквівалентна літера з наступним знаком допиту перетворюється на N + 1 (наприклад, "2?" → 3, "R?" → 8)

Що можна трактувати навпаки так:

  • 0 невідомо
  • [ 1 .. 10 ]ненадійний
  • [ 17 .. 26 ]надійний

Ми застосовуємо і F()до, aі до b. Це дає нам пару цілих чисел (x, y) для кожної цифри телефонного номера, що відповідає двом можливим тлумаченням.

Крок №2 - Відгадування цифр

Для кожної пари (x, y) обчислюємо:

  • d = x XOR y
  • x = MAX (x, y) надійні значення завжди віддають перевагу ненадійним

Якщо x == 0 , це означає, що обидва входи є символами підкреслення. Отже, цифра в цьому випадку невідома.

Якщо x! = 0 , ми можемо сміливо виводити цифру, якщо виконується одна з наступних умов:

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

Останні дві умови можна злити !(d % x). Звідси остаточна формула:

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

Якщо це правда, ми перетворюємо х назад у відгадану цифру, обчислюючи (x - 1) І 15 .

Тестові справи

(Лише 50 перших, оскільки фрагмент консолі не може підтримувати більше вихідних даних.)


1234567890? / 1234567890?має вирішити 1234567890. Зараз ваш код виводить, 123456789?що навіть менш інформативно, ніж вхідний. Assume: 5? / 5? -> 5 //uncertain, but matching
Draco18s

@ Draco18s Всупереч сказаному я включив 51 тестовий випадок. Тож перший був скинутий і все змістилося на один ряд. (Виправлено. Вибачте з цього приводу.)
Арнольд

Ааа. Тим не менш, він повинен вивести якесь значення фальси або помилки для цих тестових випадків. Але інакше виглядає добре.
Draco18s

2

Perl 5 , 211 байт

... без відступу та \ n нових рядків

@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

Спробуйте в Інтернеті!


Схоже, його повернення "найкраще, що можна" ( 83652618?0), а не якесь значення фальси чи помилки.
Draco18s

Якого саме головоломки хотіли, якщо я не помиляюся. Подивіться на справи під заголовком "Ви можете додатково припустити наступні виклики рішення". Чи ні?
Kjetil S.

На жаль, ніколи не отримували сповіщення про вашу відповідь (жодного згадування). У розділі, який я зробив для викликів судового рішення, використовується а, ?щоб вказати, що немає способу вирішити відсутність інформації, яка потім повинна потрапити в розділ Вихідні дані:...Otherwise output some form of error indication (e.g. -1, false, or an empty line).
Draco18s

2

Сітківка, 150 140 136 байт

Збережено кілька байтів завдяки Kritixi Lithos

T`?L`#22233344455566677778889
./.

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

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

Спробуйте в Інтернеті!

Пояснення:

Перший рядок перетворює всі ?вхідні дані в #усі літери в їх числові еквіваленти. Потім видаляємо пробіли і /з вводу. Наступні два рядки стосуються випадків "здогадки проти визначеності" (наприклад 5? \ 4, замінюються б на 4 \ 4). Після вилучення всіх #s рядки 8 та 9 мають справу з "числом проти _" ( _ \ 3стає 3 \ 3). Потім, якщо обидві половини рядка збігаються, ми зберігаємо перші 10 цифр. Інакше номер телефону недійсний, тому ми видаляємо все.

Альтернативне 160-байтове рішення, яке працює для телефонних номерів довільної довжини (і рівного розміру): TIO


Ви можете змінити (/|_)на, [/_]щоб зберегти 1 байт. Також я думаю, що ви можете використовувати ;замість xтого, що [^x]може стати\w
Kritixi Lithos

1

PHP, 251 236 байт

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

приймає введення з командного рядка; запустіть -nrабо спробуйте в Інтернеті .

зламатися

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

гольф

  • preg_replace по-перше: -8 байт
  • join: -2
  • $$kзамість $t[$k]: -5

1

PHP, 200 + 8 байт

натхненний рішенням Арнольдса .

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

приймає дані з аргументів командного рядка; запустіть -nrабо спробуйте в Інтернеті .

модифікації, щоб відповідати обмеженню виводу помилок: (друк Xдля неповного числа):

  • видалити |48(-3 байти)
  • замінити echo chr(...);на $r.=...;echo$r>1e10?X:$r;(+11 байт)

зламатися

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

гольф

  • обійти preg_replace_callback(-10 байт)
  • розраховуйте на 10-значний вхід (-9)
  • та додатковий гольф (-8)
  • знятий joinроздільник (-7)
  • переміщене $xзавдання до кінця (-2)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.