Numer telefonu w mowie

33

Cel

Napisz program lub funkcję, która tłumaczy numeryczny numer telefonu na tekst, który ułatwia powiedzenie. Kiedy cyfry są powtarzane, należy je czytać jako „podwójne n” lub „potrójne n”.

Wymagania

Wkład

Ciąg cyfr.

  • Załóżmy, że wszystkie znaki są cyframi od 0 do 9.
  • Załóżmy, że ciąg zawiera co najmniej jeden znak.

Wydajność

Słowa, oddzielone spacjami, o tym, jak cyfry te można odczytać na głos.

  • Przetłumacz cyfry na słowa:

    0 „o” „
    1” jeden „
    2” dwa „
    3” trzy „
    4” cztery „
    5” pięć „
    6” sześć „
    7” siedem „
    8” osiem „
    9” dziewięć ”

  • Gdy ta sama cyfra zostanie powtórzona dwa razy z rzędu, napisz „podwójna liczba ”.

  • Kiedy ta sama cyfra zostanie powtórzona trzy razy z rzędu, napisz „ liczba potrójna ”.
  • Gdy ta sama cyfra zostanie powtórzona cztery lub więcej razy, napisz „podwójną liczbę ” dla pierwszych dwóch cyfr i oceń resztę ciągu.
  • Między każdym słowem jest dokładnie jedna spacja. Dopuszczalna jest pojedyncza przestrzeń wiodąca lub końcowa.
  • W danych wyjściowych nie jest rozróżniana wielkość liter.

Punktacja

Kod źródłowy z najmniejszą liczbą bajtów.

Przypadki testowe

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
Hand-E-Food
źródło
38
Każdy zainteresowany „golfem mowy” powinien zauważyć, że „podwójna szóstka” zajmuje więcej czasu niż „sześć sześć”. Ze wszystkich możliwych tu liczb, tylko „potrójna siódemka” oszczędza sylaby.
Purple P
13
@Purple P: I jestem pewien, że wiesz, że „double-u double-u double-u”> „world wide web”.
Chas Brown
11
Głosuję za zmianą tego listu na „dub”.
Hand-E-Food
8
Wiem, że to tylko ćwiczenie intelektualne, ale mam przed sobą rachunek za gaz o numerze 0800 048 1000 i przeczytałbym to jako „och, osiemset, cztery, osiem tysięcy”. Grupowanie cyfr jest znaczące dla czytelników, a niektóre wzorce, takie jak „0800”, są traktowane specjalnie.
Michael Kay
3
@PurpleP Jednak każdy, kto jest zainteresowany klarownością mowy, szczególnie, gdy rozmawia przez telefon, może chcieć użyć „podwójnego 6”, ponieważ jest wyraźniejsze, że głośnik oznacza dwie szóstki i nie powtórzył przypadkowo liczby 6. Ludzie nie są robotami: P
Przeproś i przywróć Monikę

Odpowiedzi:

10

05AB1E , 53 52 51 50 49 bajtów

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

Wypróbuj online!

Wyjaśnienie:

γ                      # 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
Ponury
źródło
1
Aha, Mrównież przegląda listy podczas określania maksymalnej liczby całkowitej na stosie? Nie wiedziałem tego. Brzmi jak coś do zapamiętania. :)
Kevin Cruijssen
16

8088 Montaż, IBM PC DOS, 164 159 156 155 bajtów

Dwójkowy:

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$

Zbuduj i przetestuj plik wykonywalny xxd -rz góry lub pobierz PHONE.COM .

Niezmontowany wykaz:

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:

Łańcuch wejściowy jest odczytywany od prawej do lewej, aby ułatwić znalezienie potrójnego. Dane wyjściowe są wypychane na stos x86, aby uprościć odwracanie kolejności wyświetlania, a także ułatwić uporządkowanie słów „podwójnych” i „potrójnych” przed nazwą cyfry.

Jeśli następna cyfra jest inna niż ostatnia, nazwa jest sprawdzana na liście słów i przekazywana na stos. Ponieważ nie ma formalnej koncepcji „indeksowanej tablicy ciągów o zmiennej długości” w kodzie maszynowym, lista słów jest skanowana i(indeks słowa) kilka razy, aby separator łańcucha ( $) znalazł odpowiednie słowo. Pomocne jest to, że x86 ma parę krótkich instrukcji ( REPNZ SCASBpodobnych do memchr()C), co upraszcza to (dzięki CISC !).

Jeśli cyfra jest taka sama jak poprzednia, licznik długości „przebiegu” jest zwiększany i kontynuuje zapętlanie w lewo na wejściu. Po zakończeniu wybierania nazwa cyfry jest pobierana ze stosu, ponieważ będzie trzeba ją wstawić po „podwójnej” lub „potrójnej” dla każdej grupy. Jeśli długość cyklu jest nieparzysta (a długość cyklu wynosi> 1 ), nazwa cyfry, po której następuje ciąg „potrójny”, jest wypychana na stos, a długość przebiegu jest zmniejszana o 3. Ponieważ długość przebiegu będzie teraz parzysta, krok powtarza się dla „podwójnego”, aż długość przebiegu wyniesie 0.

Gdy łańcuch wejściowy osiągnie koniec, stos jest wyrzucany z każdym zapisanym łańcuchem zapisywanym na ekranie w odwrotnej kolejności.

I / O:

Samodzielny plik wykonywalny DOS dla komputera PC, wprowadzany z wyjścia wiersza poleceń do konsoli.

enter image description here

Pobierz i przetestuj PHONE.COM .

640 KB
źródło
repne scasbjest memchr(lub strchrjeśli wiesz, że będzie hit), nie strstr.
Peter Cordes
Czy CH = 0 przy wejściu do procesu jest gwarantowane przez standard, czy może właśnie tak dzieje się w niektórych wersjach DOS? Zauważam, że zakładasz, że mov cl, byte[si] to jest równoważne movzx cx, byte [si]. Zastanawiam się, czy użycie innego regu, na przykład AH, do liczenia dec ah / jnzzamiast zamiast loopzaoszczędziłoby czegokolwiek przed niepotrzebnym push / popem CX. Prawdopodobnie nie i nie masz żadnych 16-bitowych regów, które pozwoliłyby na 1 bajt dec.
Peter Cordes
1
@PeterCordes, na CH=0I go przez fysnet.net/yourhelp.htm , który dla każdego rozsądnego wydania DOS jest zawsze zerowany, to samo z BX. Dobra myśl o zerowym rozszerzeniu mov, choć technicznie nie sądzę, że movzxjest dostępna na 808x (utrzymanie platformy docelowej na IBM PC 5150 i wszystkich innych). Bawiłem się wszystkimi rejestrami najlepiej, jak mogłem, aby zapisać bajty, ale jeśli zobaczysz coś, co prawdopodobnie przegapiłem, daj mi znać!
640 KB
1
Dokładniej jest to nazwać memchrIMO. Nazewnictwo „instrukcji ciągu” wprowadza w błąd ludzi, którzy myślą, że pracują na ciągach C o niejawnej długości, ale tak naprawdę działają na ciągach takich jak std::stringbufor lub. Jak memcpy, memset(movs / stos), memchr/ memrchr(repne scas z DF = 0 lub 1) i memcmp(powtórz cmps). Jedynym odpowiednikiem C repe scasjest strspnto, że nie sądzę, aby istniała dla tego memfunkcja. Można nawet opisać stoswalbo stosdjako wmemsetnp.
Peter Cordes
1
movzxkosztuje dodatkowy bajt opcodu, i tak, został wprowadzony tylko z 386. Po prostu łatwiej było napisać, że opisujesz fakt, że wykonujesz scalanie małobajtowe i zakładając, że jest poprawnie rozszerzony o zero. Jeśli znasz CX lub przynajmniej CH = 0, to tak dla golfa zawsze idź movdo CL. Ale poza golfem, instrukcje ładowania bajtów x86 to movzxi movsx: unikają fałszywych zależności lub innych shenaniganów z częściowym rejestrem. W nowoczesnych procesorach z dwordowym miejscem docelowym są one tak szybkie, jak mov obciążenia dworda .
Peter Cordes,
9

05AB1E , 61 56 53 52 51 bajtów

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

-9 bajtów dzięki @Grimy .

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

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

Zobacz moją wskazówkę 05AB1E (sekcja Jak korzystać ze słownika? ), Aby zrozumieć, dlaczego … ‹¶½¿jest " double triple"i “Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“jest "oh two three four five six seven eight nine".

Kevin Cruijssen
źródło
1
@Grimy Ah, oczywiście .. Dodałem if(length>=4)przed dodaniem reszty, ale oczywiście nie jest to konieczne dla liczb całkowitych wielkości 1,2,3, ponieważ ;Å2¨3ª£pozostawi ciągi nietknięte (tylko owinięte w listę, którą spłaszczamy po mapie). Dzięki za zauważenie! I czekam na Twoją odpowiedź Åγ. Rzeczywiście miałem wrażenie, że pierwsza część może być wykonana w jakiś sposób znacznie krócej.
Kevin Cruijssen
1
Dg;LàäRjest wciąż bajt krótszy niż āɨšJõKi znacznie bardziej podobny do tego, co pierwotnie miałeś.
Grimmy
1
@Grimy Ach, to naprawdę jest zamknięte na to, co początkowo miałem, podoba mi się. :) Dzięki jeszcze raz!
Kevin Cruijssen
1
@Grimy Udało mi się znaleźć jeszcze jednego golfa, o którym zapomniałem ... ázamiast õKna końcu. :)
Kevin Cruijssen
1
Niezłe znalezisko z á! Oto 51 i jeszcze jeden . 50 wydaje się możliwe.
Grimmy
7

QuadR , 137 bajtów SBCS

Walizka na tytuł z wiodącym odstępem.

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

Wypróbuj online!

ε nlist (Spłaszczenie)
¯2↑¨ podejmuje ostatnie dwa znaki (wyściółki na lewej przestrzeni) każdego z bohaterów
@ w miejscach, gdzie
(∊∘⎕A)  znaki są członkami wielkiej A lphabet
 w wyniku operacji poniżej PCRE próżniowej ...

(.) dowolna postać
\1  po którym następuje
* zero lub więcej razy, jest zastępowany wynikiem następującego…

{…}⍵M „dfn”; to M powyższego wzoru

('OhOneTwoThreeFourFiveSixSevenEightNine'()⎕A)  Zastosuj następującą anonimową funkcję ukrytą z długim łańcuchem i alfabetem A jako lewymi argumentami:

 członkostwo (liter w długim łańcuchu wielkimi literami)

 partycje (z nową partycją rozpoczynającą się za każdym razem, gdy jest członkiem

 lewy argument (tj. długi ciąg)

()⎕R PCRE R. EUmieãæ następujące wzory z tymi słowami:

⎕D cyfry od 0 do 9

 traktuj każdy jako osobny wzór

⍺← przypisać tę funkcję zastępczą do (za pomocą lphabetise)

następnie,

⊃⍵ pierwsza postać meczu

, jako ciąg

 zastosować się do tego

w← przypisz to do w( słowa )

' '∊: Jeśli spacja jest jego członkiem (tzn. Jeśli dopasowanie było puste):

 nic nie zwraca (staje się pustym ciągiem)

 jeszcze,

1=≢⍵: jeśli jeden równa się liczbie znaków w dopasowaniu (tj. jego długości):

⍺⍵ alfabetycznie tę cyfrę

 jeszcze,

3=≢⍵: jeśli trzy równa się liczbie znaków w dopasowaniu (tj. jego długości):

'Triple',w prepend „Triple” dla wag ord

 jeszcze,

2↓⍵ upuść na cyfry z meczu

 powrócić do tego

w, dodaj słowo

'Double', przedrostek „Double”

Adám
źródło
6

JavaScript (ES6),  161 160 152  144 bajtów

Dane wyjściowe zawierają jedną wiodącą przestrzeń.

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

Wypróbuj online!

lub Zobacz sformatowany kod źródłowy

W jaki sposób?

Konwersja jest przetwarzana w trzech krokach:

  1. zamień każdą cyfrę na odpowiednie angielskie słowo poprzedzone spacją
  2. zastąpienia każdego wzoru "X X"z"double X"
  3. zastąpienia każdego wzoru "double X X"z"triple X"

Aby zapisać bajty, używamy tego samego wyrażenia regularnego dla wszystkich kroków:

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

który działa w następujący sposób:

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

W kroku 1 używamy funkcji zwrotnej, która wybiera właściwe słowo z tabeli odnośników:

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

W kroku 2 zastępujemy "$1 double$2":

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

W kroku 3 zastępujemy "triple$2":

  • " (double)( nine)( nine)"" triple nine"
Arnauld
źródło
4

Wolfram Language (Mathematica) , 115 bajtów

{Switch[L=Tr[1^{##}],1," ",3," triple ",_," double "],If[#<1,"oh",IntegerName@#],If[L>3,#0@##3,""]}&@@@Split@#<>""&

Wypróbuj online!

Pobiera na wejściu listę cyfr. Dane wyjściowe obejmują wiodącą przestrzeń.

attinat
źródło
4

Stax , 56 bajtów

ÇÖ◘⌡¿╒ô╞Γ▓8m☻t7♦3├(Ä⌂≤(┬Ω☻9▲ç╕C╞⌡òσ╗─╣╥─☻╪▼⌡5■ÿ,(┬¥?☺÷•±

Uruchom i debuguj

rekurencyjny
źródło
3

Python 2 , 171 169 168 bajtów

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:]

Wypróbuj online!

-1 bajt, dzięki Jitse

TFeld
źródło
Pokonaj mnie jeszcze raz! Zapisz 1 bajt jak tak
Jitse
@Jitse, to nie działa 1312;)
TFeld
Ach, masz rację!
Jitse
Jak o tym jednym następnie: ['','double ','triple '][n]do ' eellpbiurotd'[-n:0:-2]168 bajtów: Spróbuj online!
Jitse
Alternatywnie, również 168 bajtów
Jitse
3

Perl 5 -p , 111 bajtów

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

Wypróbuj online!

Wyjaśnienie:

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>"
pustkowie
źródło
1
Ogolono
3

Scala , 213 bajtów

Rozumiem. W jakiś sposób wersja rekurencyjna, którą próbowałem zbudować, była znacznie bardziej szczegółowa niż ta (choć wciąż jest rekurencyjna, ale tylko w jednym przypadku). Funkcja fprzyjmuje jako ciąg wejściowy numer telefonu i przekazuje fonetykę za pomocą spacji końcowej.

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

Wypróbuj online!
Edytować : -8b dzięki DrY Wit!

Scala , 215 bajtów

I oto nadchodzi wiodąca wersja białych znaków, z jakiegoś powodu o dwa bajty dłuższa (nawet przy masowym refaktoryzacji).

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

Wypróbuj online!

V. Courtois
źródło
2
Możesz zapisać 8 bajtów, zastępując (o(0)+"").toIntje o(0)-48.
Dr Y Wit
Oof dobrze zrobione @DrYWit dzięki!
V. Courtois
3

PHP , 174 169 166 159 bajtów

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].' ');

Wypróbuj online!

Dla każdej cyfry o indeksie $irozpoczynającym się od 0:

  • Jeśli rozpiętość tej samej cyfry, zaczynając od lokalizacji, $ijest równa 3, drukowane'triple ' i dodaje 2, aby w $inastępnej iteracji przeskoczyły 2 cyfry.
  • Jeśli rozpiętość tej samej cyfry, zaczynając od lokalizacji, $ijest równa lub większa niż 2, ale nie jest równa 3, drukuje 'double 'i dodaje 1 do$i następna iteracja spowodowała przeskok 1 cyfry.
  • Wyświetla słowo dla cyfry i spacji.
  • $i++.
Noc 2
źródło
2

Retina 0.8.2 , 105 bajtów

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

Wypróbuj online! Generuje wiodącą przestrzeń. Objaśnienie: Początkowo próbowałem wyrażenia regularnego, które automatycznie dopasowuje 2 lub 3 cyfry, ale podejście @ Arnaulda okazało się bardziej golfistyczne. Wyjaśnienie:

+`(.)\1
=$1

Dopasuj pary identycznych cyfr i zastąp pierwszą cyfrą =. Następnie powtórz, aby dla liczby nieparzystej druga ostatnia cyfra została również zastąpiona przez =.

.
 $&

Umieść cyfry (i =) na zewnątrz.

= =
triple

Obsługuj przypadek trzech identycznych cyfr.

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

Zamień wszystkie pozostałe znaki na słowa.

Neil
źródło
2

Galaretka , 59 bajtów

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

Wypróbuj online!

Łącze monadyczne, które przyjmuje jako argument ciąg znaków cyfrowych i zwraca ciąg galaretki słów oddzielonych spacją. Wywoływany jako pełny program, daje wynik niejawnie.

Nick Kennedy
źródło
2

T-SQL 2017, 238 bajtów

Dodano kilka podziałów wiersza, aby było czytelne

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 @

Wypróbuj online

t-clausen.dk
źródło
2

C ++, 382 bajty

To nie jest super-mądry, ale ktoś musiał napisać wersję C ++. Funkcja rekurencyjna R przechodzi przez ciąg wejściowy i zlicza powtarzane wartości. Jeśli są więcej niż 3 powtórzenia, to udaje, że były 2 powtórzenia, następnie przewija do tyłu i próbuje ponownie.

Kilka innych znaków źródłowych prawdopodobnie można by wycisnąć z #definemajor, ale jestem pewien, że lepszy algo mógłby wycisnąć więcej.

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

i weryfikacja przypadków testowych:

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
Mark Lakata
źródło
1
Czy część golfowa rzeczywiście potrzebuje #include <sstream>? Czy mógłbyś to przesunąć w dół po części golfowej dla funkcji testowej? Myślę, że pisanie std::ostream&szajęłoby mniej miejsca niż using namespace std;, chyba że są inne miejsca, w których potrzebujesz std::.
Peter Cordes,
253 bajty
ceilingcat
2

Perl 6 , 96 93 bajtów

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

Wypróbuj online!

Jest to anonimowy blok kodu, który pobiera liczbę i zwraca ciąg z cyframi pisanymi wielkimi literami, np 0123 => oh ONE TWO THREE Z pojedynczym końcowym odstępem.

Zostało to na chwilę usunięte, dopóki nie dowiedziałem się, jak używać przechwytywania w widoku z wyprzedzeniem, ale teraz powinno to zostać naprawione.

Jo King
źródło
1

Czerwony , 242 bajty

func[s][b:[copy t skip t]parse s[any[change[b t ahead not t](rejoin["triple "t])|
change b(rejoin["double "t])| skip]]foreach c s[prin either i:
find"0123456789"c[rejoin[pick[:oh:one:two:three:four:five:six:seven:eight:nine]index? i" "]][c]]]

Wypróbuj online!

Galen Iwanow
źródło
1

Scala , 253 bajty

def g(s:String):String={val t="oh one two three four five six seven eight nine".split(" ")(s(0)-48)
s.length match{case 3=>"triple "+t;case 2=>"double "+t;case 1=>t;case _=>"double "+t+" "+g(s drop 2)}}
s=>"(.)\\1*".r.findAllIn(s).map(g(_)) mkString " "

Wypróbuj online!

Dr Y Wit
źródło
1

Oracle SQL, 578 bajtów (w sformatowanej formie)

Rozwiązanie nie jest w żaden sposób zwięzłe, więc opublikuj je w sformatowany sposób.

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

Testuj w 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

Główną sztuczką jest to, że cyfry zamieniane są na słowa przy użyciu modeli w formacie Oracle zamiast na stałe literałów „jeden”… „dziewięć”.

Dr Y Wit
źródło
jest jakaś szansa na grę w golfa? wygląda na to, że możesz usunąć kilka spacji. Wyobrażam sobie również, że możesz przepisać GDZIE nie jest zerowe, GDZIE s> ''
t-clausen.dk
1
Można zapisać kilka znaków zastępując co po union allz select regexp_replace(s,case when length(regexp_substr(s, '(.)(\1)+')) = 3 then '^...' else '^(.)\1|^.' end) from r.
Steve Kass
1

JavaScript, 142 bajty

s=>s.replace(/(.)(\1\1(?!\1)|\1|)/g,t=>(t[2]?' triple ':t[1]?' double ':' ')+'oh one two three four five six seven eight nine'.split` `[t[0]])

Wypróbuj online!

tsh
źródło
1

(Roblox) Lua 5.1 , 166 bajtów

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

Upewnij się, że sjest to wstępnie zdefiniowana wartość ciągu wypełniona tylko cyframi; będzie to zmienna do modyfikacji. Rezultatem będzie wiodąca postać spacji [\u20] .

VisualPlugin Rōblox
źródło
Witamy na stronie! Ponieważ Lua może pobierać dane za pomocą standardowych metod , wymóg sposiadania danych wejściowych jest niezgodny z regułami . Poza tym masz dobry pierwszy post! Polecam zamieścić link do strony testowej online, np. Tio.run/#lua , aby inni mogli przetestować Twoje rozwiązanie
Cairney Coheringingahah
Cześć. Wariant Lua, na którym testowałem (Rbx.Lua) nie zawiera metod wprowadzania, chociaż piaskownica ma metody drukowania, ostrzegania i błędów.
VisualPlugin Rōblox