Номер телефону в розмовних словах


33

Мета

Напишіть програму або функцію, яка переводить числовий номер телефону в текст, що спрощує його вимову. Коли цифри повторюються, їх слід читати як "подвійний n" або "потрійний n".

Вимоги

Вхідні дані

Рядок цифр.

  • Припустимо, що всі символи - це цифри від 0 до 9.
  • Припустимо, рядок містить принаймні один символ.

Вихідні дані

Слова, розділені пробілами, про те, як ці цифри можна прочитати вголос.

  • Перекладіть цифри до слів:

    0 "ой"
    1 "один"
    2 "два"
    3 "три"
    4 "чотири"
    5 "п'ять"
    6 "шість"
    7 "сім"
    8 "вісім"
    9 "дев'ять"

  • Коли однакова цифра повторюється двічі поспіль, напишіть «подвійне число ».

  • Коли однакова цифра повторюється тричі поспіль, напишіть «потрійне число ».
  • Коли одна і та ж цифра повторюється чотири і більше разів, напишіть «подвійне число » для перших двох цифр і оцініть решту рядка.
  • Між кожним словом є рівно один пробільний символ. Єдиний провідний або кінцевий простір є прийнятним.
  • Вихідні дані не враховують регістр.

Оцінка балів

Вихідний код з найменшими байтами.

Випробування

input        output
-------------------
0123         oh one two three
4554554      four double five four double five four
000          triple oh
00000        double oh triple oh
66667888     double six double six seven triple eight
19999999179  one double nine double nine triple nine one seven nine

38
Кожен, хто цікавиться "мовленнєвим гольфом", повинен зазначити, що "подвійний шість" вимагає більше часу, ніж "шість шість". З усіх числових можливостей тут лише "потрійна семеро" зберігає склади.
Фіолетовий П

13
@ Purple P: І, як я впевнений, ви знаєте, "double-u double-u double-u"> "world wide web" ..
Час Браун

11
Я голосую за те, щоб змінити цей лист на "дуб".
Hand-E-Food

8
Я знаю, що це лише інтелектуальна вправа, але я маю перед собою законопроект про газ із номером 0800 048 1000, і я читав би це як "о вісімсот о чотири вісім одна тисяча". Групування цифр важливе для людських читачів, і деякі зразки, такі як "0800", трактуються спеціально.
Майкл Кей

3
@PurpleP Кожен, хто цікавиться чіткістю мови, однак, особливо під час розмови по телефону, може використати "подвійний 6", оскільки зрозуміліше, що динамік означає дві шістдесят і не повторив число 6 випадково. Люди - не роботи: P
Вибачте і відновіть Моніку

Відповіді:


10

05AB1E , 53 52 51 50 49 байт

γε€T2äθ¬MÊi¨₃1ǝR]˜“Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‹¶½¿“#s踻

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

Пояснення:

γ                      # split input in groups of consecutive equal digits
 ε              ]      # for each group
  €T                   #  add a 10 before each digit (66 -> [10, 6, 10, 6])
    2äθ                #  keep only the second half of that list
       ¬MÊi     ]      #  if the first element is not the maximum
           ¨           #   drop the last element
            ₃1ǝ        #   replace the second element with 95
               R       #   reverse the list
˜                      # flatten
 “...“                 # compressed string: "oh one two ... nine double triple"
      #                # split on spaces
       sè              # index (wraps around, so 95 yields "triple")
         ¸»            # join with spaces

1
О, Mтакож дивиться всередині списків, коли визначає максимальне ціле число в стеку? Не знав цього. Звучить щось запам’ятати. :)
Кевін Круїссен

16

8088 Асамблея, IBM PC DOS, 164 159 156 155 байт

Двійковий:

00000000: d1ee 8a0c 03f1 53fd ac3a d075 0343 e2f7  ......S..:.u.C..
00000010: 85db 741c 5f8a d043 f6c3 0174 0a57 bd64  ..t._..C...t.W.d
00000020: 0155 83eb 0374 0957 bd5d 0155 4b4b 75f7  .U...t.W.].UKKu.
00000030: 8ad0 2c2f 7213 518a f0b0 24b1 31bf 6a01  ..,/r.Q...$.1.j.
00000040: fcf2 aefe ce75 fa59 57e2 bc5a 85d2 740c  .....u.YW..Z..t.
00000050: b409 cd21 b220 b402 cd21 ebef c364 6f75  ...!. ...!...dou
00000060: 626c 6524 7472 6970 6c65 246f 6824 6f6e  ble$triple$oh$on
00000070: 6524 7477 6f24 7468 7265 6524 666f 7572  e$two$three$four
00000080: 2466 6976 6524 7369 7824 7365 7665 6e24  $five$six$seven$
00000090: 6569 6768 7424 6e69 6e65 24              eight$nine$

Створіть і випробуйте виконуваний файл xxd -rзверху або завантажте PHONE.COM .

Нерозбірний список:

D1 EE       SHR  SI, 1              ; point SI to DOS PSP (80H) for input string
8A 0C       MOV  CL, BYTE PTR[SI]   ; load input string length into CX
03 F1       ADD  SI, CX             ; move SI to end of input 
53          PUSH BX                 ; push a 0 to signal end of output stack 
        CHAR_LOOP:
FD          STD                     ; set LODS direction to reverse 
AC          LODSB                   ; load next char from [SI] into AL, advance SI 
3A D0       CMP  DL, AL             ; is it same as previous char? 
75 03       JNZ  NEW_CHAR           ; if not, it's a different char 
43          INC  BX                 ; otherwise it's a run, so increment run length
E2 F7       LOOP CHAR_LOOP          ; move on to next char 
        NEW_CHAR: 
85 DB       TEST BX, BX             ; is there a run greater than 0? 
74 1C       JZ   GET_WORD           ; if not, look up digit name 
5F          POP  DI                 ; get name for the current digit 
8A D0       MOV  DL, AL             ; save current char in DL 
43          INC  BX                 ; adjust run count (BX=1 means run of 2, etc)
F6 C3 01    TEST BL, 1              ; is odd? if so, it's a triple
74 0A       JZ   IS_DBL             ; is even, so is a double 
57          PUSH DI                 ; push number string ("one", etc) to stack
BD 0164     MOV  BP, OFFSET T       ; load "triple" string 
55          PUSH BP                 ; push to stack 
83 EB 03    SUB  BX, 3              ; decrement run count by 3 
74 09       JZ   GET_WORD           ; if end of run, move to next input char 
        IS_DBL: 
57          PUSH DI                 ; push number string to stack
BD 015D     MOV  BP, OFFSET D       ; load "double" string 
55          PUSH BP                 ; push to stack 
4B          DEC  BX                 ; decrement by 2
4B          DEC  BX
75 F7       JNZ  IS_DBL             ; if not end of run, loop double again 
        GET_WORD: 
8A D0       MOV  DL, AL             ; save current char into DL
2C 2F       SUB  AL, '0'-1          ; convert ASCII char to 1-based index 
72 13       JB   NOT_FOUND          ; if not a valid char, move to next
51          PUSH CX                 ; save outer loop counter 
8A F0       MOV  DH, AL             ; DH is the index to find, use as scan loop counter
B0 24       MOV  AL, '$'            ; word string is $ delimited
B1 31       MOV  CL, 031H           ; search through length of word data (49 bytes)
BF 016A     MOV  DI, OFFSET W       ; reset word data pointer to beginning
FC          CLD                     ; set DF to scan forward for SCAS 
        SCAN_LOOP: 
F2/ AE      REPNZ SCASB             ; search until delimiter '$' is found in [DI]
FE CE       DEC  DH                 ; delimiter found, decrement counter 
75 FA       JNZ  SCAN_LOOP          ; if counter reached 0, index has been found 
59          POP  CX                 ; restore outer loop position
57          PUSH DI                 ; push string on stack 
        NOT_FOUND:
E2 BC       LOOP CHAR_LOOP          ; move to next char in input 
        OUTPUT_STACK: 
5A          POP  DX                 ; get string from top of stack 
85 D2       TEST DX, DX             ; it is the last? 
74 0C       JZ   EXIT               ; if so, exit 
B4 09       MOV  AH, 09H            ; DOS display string function 
CD 21       INT  21H                ; write string to console 
B2 20       MOV  DL, ' '            ; load space delimiter 
B4 02       MOV  AH, 02H            ; DOS display char function 
CD 21       INT  21H                ; write char to console 
EB EF       JMP  OUTPUT_STACK       ; continue looping 
        EXIT: 
C3          RET                     ; return to DOS 

D   DB "double$" 
T   DB "triple"
W   DB "$oh$","one$","two$","three$","four$","five$","six$","seven$","eight$","nine$" 

TL; DR:

Вхідний рядок читається праворуч зліва, щоб полегшити пошук трійки. Вихід натискається на стек x86 для спрощення змінити порядок відображення, а також полегшити перестановку слів "подвійний" і "потрійний", щоб передувати імені цифри.

Якщо наступна цифра відрізняється від останньої, назву шукають у списку слів і натискають на стек. Оскільки в машинному коді немає офіційного поняття "індексований масив рядків змінної довжини", список слів сканується i(індекс слова) кількість разів для роздільника рядка ( $), щоб знайти відповідне слово. Корисно, що x86 має пару коротких інструкцій ( REPNZ SCASBщо схоже на memchr()C), що спрощує це (спасибі CISC !).

Якщо цифра така ж, як і попередня, лічильник на довжину "пробігу" збільшується і продовжує циклічно ліворуч на вході. Після закінчення запуску ім'я цифри береться з стека, оскільки його потрібно буде розміщувати після "подвійного" або "потрійного" для кожної групи. Якщо довжина пробігу непарна (а довжина запуску - це > 1), ім'я цифри з наступним рядком "потрійний" висувається до стека, а довжина виконання зменшується на 3. Оскільки довжина запуску тепер буде парною, крок повторюється для "подвійного", поки довжина пробігу не дорівнює 0.

Коли рядок введення доходить до кінця, стек викидається з кожною збереженою рядком, записаною на екран у зворотному порядку.

I / O:

Автономний виконуваний комп'ютер DOS, вхід з виводу командного рядка на консоль.

enter image description here

Завантажте та протестуйте PHONE.COM .


repne scasbє memchr(або strchrякщо ви знаєте, що це буде хіт), ні strstr.
Пітер Кордес

CH = 0 при введенні процесу гарантується стандартом, чи це саме те, що потрібно робити в деяких версіях DOS? Зауважую, ви припускаєте, що mov cl, byte[si] це еквівалентно movzx cx, byte [si]. Цікаво, чи використання іншого reg, наприклад AH, для підрахунку, dec ah / jnzа loopне врятувало б щось від того, що не потрібно натискати / попсувати CX. Можливо, ні, і у вас немає 16-бітових регістрів, які дозволяли б отримати 1-байт dec.
Пітер Кордес

1
@PeterCordes, тому що CH=0я переходжу на fysnet.net/yourhelp.htm , який для будь-якого розумного випуску DOS завжди дорівнює нулю, те ж саме BX. Добре подумав про нульове розширення mov, хоча технічно я не думаю, що movzxце доступно в 808x (зберігаючи цільову платформу IBM PC 5150 і все). Я поспілкувався з усіма регістрами якнайкраще, щоб зберегти байти, але якщо ви бачите щось, що я, ймовірно, пропустив, будь ласка, дайте мені знати!
640 Кб

1
Точніше назвати це memchrІМО. Ім'я "рядкової інструкції" вводить людей в оману, думаючи, що вони працюють на C рядках неявної довжини, але насправді вони працюють на строках явної довжини, таких як std::stringбуфери Як memcpy, memset(movs / stos), memchr/ memrchr(повторно скасувати з DF = 0 або 1), і memcmp(повторити cmps). Єдиний еквівалент C - repe scasце strspnтому, що я не думаю, що для цього є memфункція. Можна навіть описати stoswабо stosdяк, wmemsetнаприклад.
Пітер Кордес

1
movzxкоштує додатковий байт опкоду, і так, це було введено лише з 386. Набрати простіше було описати той факт, що ви робите злиття в малому байті і припускаючи, що це правильно нульове розширення. Якщо ви знаєте CX або, принаймні, CH = 0, тоді так, щоб у гольфі завжди переходити movдо CL. Але поза грою в гольф, йти в байтах навантаження х86 є movzxі movsx: вони уникають будь - яких помилкових залежностей або інший парціального регістра витівки. У сучасних процесорах із призначенням dword вони настільки ж швидкі, як і mov завантаження dword .
Пітер Кордес

9

05AB1E , 61 56 53 52 51 байт

γvyDg;LàäRv… ‹¶½¿#yg蓊瀵‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“#yè])áðý

-9 байт завдяки @Grimy .

Спробуйте в Інтернеті або перевірте всі тестові справи .

Пояснення:

γ               # Split the (implicit) input into substrings of equal adjacent characters
                #  i.e. "199999991779" → ["1","9999999","1","77","9"]
 v              # Loop over each substring `y`:
   Dg           #  Get the length of a copy of the substring
     ;          #  Halve it
      L         #  Create a list in the range [1, length/2], where odd lengths are
                #  automatically truncated/floored
                #   i.e. "1" (length=1) → 0.5 → [1,0]
                #   i.e. "9999999" (length=7) → 3.5 → [1,2,3]
       à        #  Pop and push the maximum of this list
  y     ä       #  Divide the string into that many parts
                #   → ["1"]
                #   → ["999","99","99"]
         R      #  Reverse the list
                #   → ["99","99","999"]
  v             # Inner loop over each item `y`:
    ‹¶½¿       #  Push dictionary word: "  double triple"
         #      #  Split it on spaces: ["","","double","triple"]
          yg    #  Get the length of the current item `y`
            è   #  And use it to (0-based) index into the list
   “Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“
                #  Push dictionary string "oh two three four five six seven eight nine"
     #          #  Split it on spaces: ["oh","two","three",...,"nine"]
      yè        #  Use `y` to index into the string-list (with automatic wrap-around,
                #  so since there are 10 words, it basically indexes with a single digit
                #  due to an implicit modulo-10)
                #   i.e. "77" → "seven"
 ]              # Close both loops
  )             # Wrap all values on the stack into a list
   á            # Only keep letters, which removes the empty strings from the list
    ðý          # And join the list on spaces
                # (after which the result is output implicitly)

Дивіться цей мінний наконечник 05AB1E (розділ Як користуватися словником? ), Щоб зрозуміти, чому … ‹¶½¿це так " double triple"і “Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“є "oh two three four five six seven eight nine".


1
@Grimy Ах, звичайно .. Я додав if(length>=4)раніше додавання решти, але звичайно це не потрібно для цілих чисел розміру 1,2,3, тому що ;Å2¨3ª£воля залишить рядки недоторканими (просто загорнувшись у список, який ми все одно вирівнюємо після карти). Дякуємо, що помітили! І з нетерпінням чекаю вашої відповіді Åγ. У мене справді було відчуття, що першу частину можна якось зробити коротше.
Кевін Круїссен

1
Dg;LàäR- все-таки байт коротший āɨšJõKі набагато більше схожий на те, що у вас був.
Grimmy

1
@Grimy Ах, це дійсно закрито до того, що я спочатку мав, мені це подобається. :) Знову дякую!
Кевін Кройсейсен

1
@Grimy Ви змогли знайти ще один гольф, про який я забув .., áа õKне в кінці. :)
Кевін Круїссен

1
Приємна знахідка á! Ось 51 та ще один . 50 відчуває можливим.
Grimmy

7

QuadR , 137 байт SBCS

Заголовок справи з провідним пробілом.

∊¯2↑¨@(∊∘⎕A)⍵
(.)\1*
{⍺←(,¨⎕D)⎕R('OhOneTwoThreeFourFiveSixSevenEightNine'(∊⊂⊣)⎕A)⋄' 'w←⍺,⊃⍵:⍬⋄1=≢⍵:⍺⍵⋄3=≢⍵:'Triple',w'Double',w,∇2↓⍵}⍵M

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

ϵ nlist (сплющити)
¯2↑¨ візьміть два останні символи (прокладка зліва з пробілом) кожного символу
@ на позиціях, де
(∊∘⎕A) символи є великими літерами A lphabet
 у результаті операції PCRE Замінити…

(.) будь-який персонаж
\1 слідує за собою
*  нуль або більше разів, замінюється результатом наступного…

{…}⍵M "dfn"; є М атч вищевказаного зразка

('OhOneTwoThreeFourFiveSixSevenEightNine'()⎕A) Застосуйте таку анонімну функцію мовчання з довгою строкою та великими літерами A великого lphabet як лівих аргументів:

 членство (букв у довгій рядку великого алфавіту)

 розділи (з новим розділом, що починається, коли є членом

 лівий аргумент (тобто довга рядок)

()⎕R PCRE R замінить наступні зразки цими словами:

⎕D цифри від 0 до 9

 трактуйте кожного як окремий зразок

⍺← призначити цю функцію для заміни в (для в lphabetise)

потім,

⊃⍵ перший персонаж матчу

, як струна

 застосувати до нього

w← призначити це w(для слова )

' '∊: Якщо пробіл є його членом (тобто якщо збіг був порожнім):

 не повернути нічого (стає порожнім рядком)

 інше,

1=≢⍵: якщо один дорівнює знакам символів (тобто його довжині):

⍺⍵ алфавіту цієї цифри

 інше,

3=≢⍵: якщо три дорівнює кількості символів у матчі (тобто його довжині):

'Triple',w подати "Потрійний" до w ord

 інше,

2↓⍵ крапля до цифр з матчу

 повторювати це

w, передчуття слова

'Double', подати "Подвійний"


6

JavaScript (ES6),  161 160 152  144 байт

Вихід включає єдиний провідний простір.

s=>[n=>' '+'oh/one/two/three/four/five/six/seven/eight/nine'.split`/`[n],'$1 double$2','triple$2'].map(r=>s=s.replace(/(\S*)( \S+)\2|\d/g,r))&&s

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

або Дивіться відформатований вихідний код

Як?

Перетворення обробляється в три етапи:

  1. замініть кожну цифру відповідним англійським словом, перед яким пробіл
  2. замініть кожен візерунок "X X"на"double X"
  3. замініть кожен візерунок "double X X"на"triple X"

Для збереження байтів ми використовуємо однаковий регулярний вираз для всіх кроків:

/(\S*)( \S+)\2|\d/g

яка працює наступним чином:

(\S*)  -> 1st capturing group: any word, or nothing at all
( \S+) -> 2nd capturing group: a space, followed by a word
\2     -> a copy of the 2nd capturing group
|\d    -> or try to capture a digit instead (for step 1)

На кроці 1 ми використовуємо функцію зворотного виклику, яка вибирає правильне слово з таблиці пошуку:

  • "799999"" seven nine nine nine nine nine"

На кроці 2 ми замінюємо "$1 double$2":

  • " (seven)( nine)( nine)"" seven double nine"
  • "( nine)( nine) nine"" double nine nine"

На кроці 3 ми замінюємо "triple$2":

  • " (double)( nine)( nine)"" triple nine"



3

Пітон 2 , 171 169 168 байт

s=input()
while s:c=s[0];n=(s[1:2]==c)+(s[:3]==c*3!=s[1:4]);print'   eellpbiurotd'[-n:0:-2]+'oh one two three four five six seven eight nine'.split()[int(c)],;s=s[1+n:]

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

-1 байт, завдяки Джитце


Бий мене знову! Збережіть 1 байт так
Jitse

@Jitse, це не працює 1312;)
TFeld

Ах, ти маєш рацію!
Джице

Як щодо цього: ['','double ','triple '][n]до ' eellpbiurotd'[-n:0:-2]168 байт: Спробуйте в Інтернеті!
Jitse

Крім того, також 168 байт
Jitse

3

Perl 5 -p , 111 байт

s/(\d)\1/ double$1/g;s/\w+(\d)\1/triple$1/g;s/\d/' '.qw(oh one two three four five six seven eigth nine)[$&]/ge

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

Пояснення:

s/(\d)\1/ double$1/g; # Replace non-overlapping double digits with " double<digit>"
s/\w+(\d)\1/triple$1/g; # Replace remaining double digits preceded by "double" with "triple<digit>"
s/\d/' '.qw(oh one two three four five six seven eigth nine)[$&]/ge # Replace digits with " <word>"

1
Поголив кілька байтів: 106
Xcali

3

Scala , 213 байт

Зрозумів. Якимось чином рекурсивна версія, яку я намагався побудувати, була сильно більш багатослівною, ніж ця (хоча все-таки рекурсивна, але лише в одному випадку). Функція fприймає вхідний рядок телефонного номера і виводить його фонетику з пробілом пробілу.

var u="oh one two three four five six seven eight nine" split " "
"(.)\\1*".r.replaceAllIn(s,x=>{var o=x.matched
var k=u(o(0)-48)+" "
o.length match{case 3=>"triple "+k
case 1=>k
case _=>"double "+k+f(o drop 2)}})

Спробуйте в Інтернеті!
Редагувати : -8b завдяки DrY Wit!

Скала , 215 байт

І ось з'являється провідна версія пробілів, на два байти чомусь довше (навіть при масовому рефакторингу).

var u="oh one two three four five six seven eight nine" split " "
"(.)\\1*".r.replaceAllIn(s,x=>{var o=x.matched
var k=u(o(0)-48)
" , double , triple ".split(",")(if(o.length>3){k+=f(o drop 2);1}else o.length-1)+k})

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


2
Ви можете зберегти 8 байт, замінивши (o(0)+"").toIntна o(0)-48.
Доктор Y Віт

Добре молодець @DrYWit спасибі!
В. Куртуа

3

PHP , 174 169 166 159 байт

for(;$s=strspn($argn,$d=$argn[$i],$i++);$s==3?($i+=2)+print'triple ':$s<2?:++$i+print'double ',print[oh,one,two,three,four,five,six,seven,eight,nine][$d].' ');

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

Для кожної цифри в індексі $iпочинаючи від 0:

  • Якщо проміжок однієї цифри, починаючи з місця розташування $i, дорівнює 3, друкується 'triple 'і додається 2 до$i наступної ітерації.
  • Якщо проміжок однієї і тієї ж цифри, що починається з місця розташування $i, дорівнює або більше 2, але не дорівнює 3, друкується 'double 'та додається 1, $iтому наступна ітерація перейде через одну цифру.
  • Друкує слово для цифри та пробілу.
  • $i++.

2

Сітківка 0,8,2 , 105 байт

+`(.)\1
=$1
.
 $&
= =
triple
=
double
9
nine
8
eight
7
seven
6
six
5
five
4
four
3
three
2
two
1
one
0
oh

Спробуйте в Інтернеті!Виводить провідний простір. Пояснення: Спочатку я спробував регулярний вираз, який автоматично збігається з 2 або 3 цифрами, але підхід @ Арнольда виявився гравцем. Пояснення:

+`(.)\1
=$1

З'єднайте пари однакових цифр і замініть першу на a =. Потім повторіть, щоб для непарного числа друга остання цифра була також замінена на a= .

.
 $&

Розмістіть цифри (і =).

= =
triple

Обробіть корпус із трьох однакових цифр.

=
double
9
nine
8
eight
7
seven
6
six
5
five
4
four
3
three
2
two
1
one
0
oh

Замініть усі решта символів словами.


2

Желе , 59 байт

⁵;`,0;$Ɗ€Ẏ;`Ø0ṭ;-œṣjƭƒV€‘$ị“¡ıc⁴Ṛ⁽]@ɱ2¦Ż©Ẉḷ$Æ!)ɗ[ı8ɱḃ%ċ»Ḳ¤K

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

Монадичне посилання, яке бере аргумент рядка з цифр і повертає рядок Jelly з розділеними пробілами слова. Коли викликається повною програмою, виводиться неявно.


2

T-SQL 2017, 238 байт

Додано кілька перерв рядків, щоб зробити його читабельним

WHILE''<left(@,1)SELECT @=stuff(@,1,iif(p<4,p,2),'')+
iif(p=1,' ',iif(p=3,' triple ',' double '))
+trim(substring('oh  one  two  threefour five six  seveneightnine',left(@,1)*5,5))
FROM(SELECT~-patindex('%[^'+left(@,1)+']%'+'^',@)p)z
PRINT @

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


2

C ++, 382 байти

Це не суперклевер, але комусь потрібно було написати версію C ++. Рекурсивна функція R проходить через вхідний рядок і підраховує повторювані значення. Якщо є більше 3 повторів, вона робить вигляд, що було 2 повтори, потім перемотайте назад і повторіть спробу.

Ще кілька джерел символів, ймовірно, можуть бути витіснені з #defineмайором, але я впевнений, що кращий альго міг би вичавити більше.

#include <iostream>
#include <sstream>
using namespace std;
char*n[]={"oh","one","two","three","four","five","six","seven","eight","nine"};
void R(ostream& s,const char*r,char p='x',int c=0){if(*r==p)R(s,r+1,p,c+1);else
{if(c>1){if(c>= 4){s<<"double ";r-=(c-2);}else if(c==3)s<< "triple ";else if(c==2)s<< "double ";
}if(c >0)s<<n[p-'0']<<" ";if(!*r)return;R(s,r+1,*r,1);}}

void check(const char* in, const char* out)
{
    std::stringstream ss;
    R(ss,in);
    if (out == ss.str()) std::cout << "PASS: "; else std::cout << "FAIL! ";
    std::cout << in << "\n< " << out << "\n> " << ss.str() << std::endl;
}

int main(int c,char**argv)
{
    if (argv[1] == std::string("test"))
    {
        check("0123"         ,"oh one two three ");
        check("4554554"      ,"four double five four double five four ");
        check("000"          ,"triple oh ");
        check("00000"        ,"double oh triple oh ");
        check("66667888"     ,"double six double six seven triple eight ");
        check("19999999179"  ,"one double nine double nine triple nine one seven nine ");
    }
    else
    {
        char* v = argv[1];
        R(std::cout,v);
        std::cout << std::endl;
    }
}

і перевірка тестових випадків:

pa-dev01$ ./a.out test
PASS: 0123
< oh one two three
> oh one two three
PASS: 4554554
< four double five four double five four
> four double five four double five four
PASS: 000
< triple oh
> triple oh
PASS: 00000
< double oh triple oh
> double oh triple oh
PASS: 66667888
< double six double six seven triple eight
> double six double six seven triple eight
PASS: 19999999179
< one double nine double nine triple nine one seven nine
> one double nine double nine triple nine one seven nine

1
Чи потрібна насправді частина для гольфу #include <sstream>? Або ви могли пересунути це вниз після гольф частини для тестової функції? Я думаю, що для набору тексту std::ostream&sпотрібно буде менше місця, ніж using namespace std;якщо тільки немає інших місць, де вам потрібно std::.
Пітер Кордес


2

Perl 6 , 96 93 байт

{S:g/(.)$0?[$0{}<!$0>]?/{(<triple double>X$)[3-$/.comb]}{+$/??uniname(~$0).words[1]!!'oh'} /}

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

Це анонімний код коду, який приймає число і повертає рядок з числами у великому регістрі, наприклад 0123 => oh ONE TWO THREE з одним пробілом.

Це було видалено на деякий час, поки я не з'ясував, як використовувати захоплення в пошуку, але це слід виправити зараз.




1

Oracle SQL, 578 байт (у відформатованому вигляді)

Рішення жодним чином не є коротким, тому розміщуйте його у форматованому вигляді.

with r(s) as
(select x from t
  union all
 select case
           when length(regexp_substr(s, '(.)(\1)+')) = 3 
           then regexp_replace(s, '^...')
           else regexp_replace(s, '^(.)\1|^.')
        end
   from r
  where s is not null)
select listagg(decode(length(r),  2, 'double ',  3, 'triple ') ||
               decode(substr(r, 1, 1), 0, 'oh', to_char(to_date(substr(r, 1, 1), 'j'), 'jsp')), ' ')
               within group (order by rownum)
  from (select regexp_replace(s, lag(s) over (order by length(s)) || '$') r
          from r order by length(s) desc);

Тест у SQL * Plus

SQL> create table t(x) as select /*'45547777777774'*/ '1999999910079' from dual;

Table created.

SQL> set pages 0
SQL> with r(s) as
  2  (select x from t
  3    union all
  4   select case
  5             when length(regexp_substr(s, '(.)(\1)+')) = 3
  6             then regexp_replace(s, '^...')
  7             else regexp_replace(s, '^(.)\1|^.')
  8          end
  9     from r
 10    where s is not null)
 11  select listagg(decode(length(r),  2, 'double ',  3, 'triple ') ||
 12                 decode(substr(r, 1, 1), 0, 'oh', to_char(to_date(substr(r, 1, 1), 'j'), 'jsp')), ' ')
 13                 within group (order by rownum)
 14    from (select regexp_replace(s, lag(s) over (order by length(s)) || '$') r
 15            from r order by length(s) desc);
one double nine double nine triple nine one double oh seven nine

Основна хитрість полягає в тому, що цифри, перетворені на слова, використовуючи моделі формату Oracle замість жорстко закодованих літералів "один" ... "дев'ять".


будь-який шанс отримати цей гольф? здається, ви можете видалити купу пробілів. Я також уявляю, що ви можете переписати WHERE s не є нульовим для WHERE s> ''
t-clausen.dk

1
Ви можете зберегти кілька символів, замінюючи то , що після того, як union allз select regexp_replace(s,case when length(regexp_substr(s, '(.)(\1)+')) = 3 then '^...' else '^(.)\1|^.' end) from r.
Стів Касс


1

(Roblox) Lua 5.1 , 166 байт

for I,N in('111 triple 11 double 1 '):gmatch'(%d+)(%D+)'do for i,n in('0oh1one2two3three4four5five6six7seven8eight9nine'):gmatch'(.)(%l+)'do s=s:gsub(i*I,N..n)end end

Переконайтесь s, що заздалегідь задане значення рядка, заповнене лише цифрами; це буде змінна зміна. Результат буде містити провідний космічний [\u20] персонаж.


Ласкаво просимо на сайт! Оскільки Lua може приймати дані за допомогою стандартних методів , це суперечить правилам вимагати sвже мати дані. Крім цього, у вас є хороший перший пост! Я рекомендую вам включити посилання на веб-сайт для тестування, наприклад, tio.run/#lua, щоб інші могли перевірити ваше рішення
caird coinheringaahing

Привіт. Варіант Lua, на якому я тестував (Rbx.Lua), не містить методів введення, хоча у пісочниці є методи друку, попередження та помилки.
VisualPlugin Rōblox
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.