Telefonnummer in gesprochenen Worten


33

Tor

Schreiben Sie ein Programm oder eine Funktion, die eine numerische Telefonnummer in einen Text übersetzt, der das Sprechen erleichtert. Wenn Ziffern wiederholt werden, sollten sie als "double n" oder "triple n" gelesen werden.

Bedarf

Eingang

Eine Folge von Ziffern.

  • Angenommen, alle Zeichen sind Ziffern von 0 bis 9.
  • Angenommen, die Zeichenfolge enthält mindestens ein Zeichen.

Ausgabe

Durch Leerzeichen getrennte Wörter, wie diese Ziffern laut vorgelesen werden können.

  • Ziffern in Wörter übersetzen:

    0 "oh"
    1 "eins"
    2 "zwei"
    3 "drei"
    4 "vier"
    5 "fünf"
    6 "sechs"
    7 "sieben"
    8 "acht"
    9 "neun"

  • Wenn dieselbe Ziffer zweimal hintereinander wiederholt wird, geben Sie "double number " ein.

  • Wenn die gleiche Ziffer dreimal hintereinander wiederholt wird, schreiben Sie "dreifache Zahl ".
  • Wenn die gleiche Ziffer vier oder mehr Mal wiederholt wird, schreiben Sie für die ersten beiden Ziffern "double number " und werten Sie den Rest der Zeichenfolge aus.
  • Zwischen jedem Wort befindet sich genau ein Leerzeichen. Ein einzelnes vorangestelltes oder nachfolgendes Leerzeichen ist zulässig.
  • Bei der Ausgabe wird nicht zwischen Groß- und Kleinschreibung unterschieden.

Wertung

Quellcode mit den wenigsten Bytes.

Testfälle

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
Wer sich für "Redegolf" interessiert, sollte beachten, dass "Double Six" länger dauert als "Six Six". Von allen numerischen Möglichkeiten speichert hier nur "Triple Seven" Silben.
Lila P

13
@ Purpur P: Und wie Sie sicher wissen, 'double-u double-u double-u'> 'world wide web' ..
Chas Brown

11
Ich stimme dafür, diesen Brief in "Dub" zu ändern.
Hand-E-Food

8
Ich weiß, dass dies nur eine intellektuelle Übung ist, aber ich habe eine Gasrechnung mit der Nummer 0800 048 1000 vor mir, und ich würde das als "oh achthundert oh vier acht eintausend" lesen. Die Gruppierung von Ziffern ist für den menschlichen Leser von Bedeutung, und einige Muster wie "0800" werden speziell behandelt.
Michael Kay

3
@PurpleP Jeder, der an der Klarheit der Sprache interessiert ist , möchte möglicherweise "double 6" verwenden, da es klarer ist, dass der Sprecher zwei Sechser bedeutet und die Zahl 6 nicht versehentlich wiederholt. Leute sind keine Roboter: P
Entschuldige

Antworten:


10

05AB1E , 53 52 51 50 49 Bytes

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

Probieren Sie es online!

Erläuterung:

γ                      # 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
Oh, Msieht man auch in Listen nach, wenn man die maximale Ganzzahl auf dem Stapel ermittelt? Wusste das nicht. Klingt nach etwas, an das man sich erinnert. :)
Kevin Cruijssen

16

8088 Assembly, IBM PC DOS, 164 159 156 155 Bytes

Binär:

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$

Erstellen und testen Sie die ausführbare Datei xxd -rvon oben oder laden Sie PHONE.COM herunter .

Zerlegte Auflistung:

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:

Die Eingabezeichenfolge wird von rechts nach links gelesen, um das Auffinden eines Tripels zu erleichtern. Die Ausgabe wird auf den x86-Stapel geschoben , um das Umkehren der Anzeigereihenfolge und das Neuanordnen der Wörter "double" und "triple" vor dem Ziffernnamen zu vereinfachen.

Wenn sich die nächste Ziffer von der letzten unterscheidet, wird der Name in der Wortliste nachgeschlagen und auf den Stapel verschoben. Da es kein formales Konzept für ein "indiziertes Array von Zeichenfolgen variabler Länge" im Maschinencode gibt, wird die Liste der Wörter i(der Wortindex) so oft gescannt, bis der Zeichenfolgenbegrenzer ( $) das entsprechende Wort gefunden hat. Hilfreich ist, dass x86 ein paar kurze Anweisungen hat ( REPNZ SCASBähnlich wie memchr()in C), die dies vereinfachen (danke CISC !).

Wenn die Ziffer mit der vorherigen identisch ist, wird der Zähler für die Länge eines "Laufs" inkrementiert und die Schleife am Eingang nach links fortgesetzt. Sobald der Lauf beendet ist, wird der Name der Ziffer vom Stapel genommen, da er für jede Gruppierung nach dem "Doppel" oder "Dreifach" gesetzt werden muss. Wenn die Lauflänge ungerade ist (und die Lauflänge ungerade ist > 1), wird der Name der Ziffer, gefolgt von der Zeichenfolge "Triple", in den Stapel verschoben und die Lauflänge um 3 verringert. Da die Lauflänge jetzt gerade ist, ist der Schritt wird für "double" wiederholt, bis die Lauflänge 0 ist.

Wenn die Eingabezeichenfolge das Ende erreicht hat, wird der Stapel ausgegeben, wobei jede gespeicherte Zeichenfolge in umgekehrter Reihenfolge auf den Bildschirm geschrieben wird.

I / O:

Eine eigenständige ausführbare PC-DOS-Datei, die über die Befehlszeilenausgabe an die Konsole eingegeben wird.

Bildbeschreibung hier eingeben

Laden Sie PHONE.COM herunter und testen Sie es .


repne scasbist memchr(oder strchrwenn Sie wissen, dass es einen Treffer geben wird), nicht strstr.
Peter Cordes

Ist CH = 0 bei Prozesseintritt durch einen Standard garantiert, oder ist das genau das, was eine DOS-Version tut? Ich stelle fest, dass Sie davon ausgehen, dass dies mov cl, byte[si] äquivalent zu ist movzx cx, byte [si]. Ich frage mich, ob die Verwendung eines anderen Registers AHfür die Zählung mit dec ah / jnzstatt loopetwas davon abhalten würde, CX nicht zu pushen / popen. Wahrscheinlich nicht, und Sie haben keine 16-Bit-Register mehr, die 1 Byte zulassen würden dec.
Peter Cordes

1
@PeterCordes, für die CH=0gehe ich von fysnet.net/yourhelp.htm aus , die für jede vernünftige DOS-Version immer gleich null ist, also mit BX. Gute Gedanken über die Null-Ausdehnung mov, obwohl ich technisch nicht denke, dass movzxsie auf dem 808x verfügbar ist (die Zielplattform bleibt ein IBM PC 5150 und alle). Ich habe mit allen Registern herumgespielt, so gut ich konnte, um die Bytes zu retten, aber wenn Sie etwas sehen, das ich wahrscheinlich verpasst habe, lassen Sie es mich bitte wissen!
640 KB,

1
Es ist genauer, es memchrIMO zu nennen . Die Bezeichnung "Zeichenfolgenanweisung" täuscht die Leute in die Irre, dass sie an implizit langen C-Zeichenfolgen arbeiten, aber tatsächlich arbeiten sie an explizit langen Zeichenfolgen wie std::stringoder Puffern. Wie memcpy, memset(MOVs / stos) memchr/ memrchr(REPNE SCAS mit DF = 0 oder 1), und memcmp(repe CMPS). Das einzige C-Äquivalent für repe scasist, strspnweil ich nicht glaube, dass es dafür eine memFunktion gibt . Sie können sogar beschreiben stoswoder stosdals wmemsetzum Beispiel.
Peter Cordes

1
movzxkostet ein zusätzliches Opcode-Byte, und ja, es wurde erst mit 386 eingeführt. Es war nur einfacher zu tippen, um die Tatsache zu beschreiben, dass Sie eine Low-Byte-Zusammenführung durchführen und davon ausgehen, dass sie korrekt null erweitert ist. Wenn Sie CX oder mindestens CH = 0 kennen, dann gehen Sie ja zum Golfen immer movzu CL. Aber außerhalb des Golfsports sind x86s Anweisungen zum Laden von Bytes movzxund movsx: Sie vermeiden falsche Abhängigkeiten oder andere Partial-Register-Spielereien. Auf modernen CPUs mit einem Dword-Ziel sind sie so schnell, wie Dword geladen mov wird.
Peter Cordes

9

05AB1E , 61 56 53 52 51 Bytes

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

-9 Bytes dank @Grimy .

Probieren Sie es online aus oder überprüfen Sie alle Testfälle .

Erläuterung:

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

Sehen Sie sich meinen Tipp 05AB1E (Abschnitt Wie verwende ich das Wörterbuch? ) An, um zu verstehen, warum es … ‹¶½¿ist " double triple"und “Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“ist "oh two three four five six seven eight nine".


1
@Grimy Ah, natürlich .. Ich habe das hinzugefügt, if(length>=4)bevor ich den Rest hinzufügte, aber natürlich ist es nicht notwendig für ganze Zahlen der Größe 1,2,3, da ;Å2¨3ª£die Zeichenketten intakt bleiben (nur umhüllt von einer Liste, die wir ohnehin nach der Karte abflachen). Danke fürs bemerken! Und freue mich auf Ihre Antwort mit Åγ. Ich hatte in der Tat das Gefühl, dass der erste Teil irgendwie viel kürzer gemacht werden könnte.
Kevin Cruijssen

1
Dg;LàäRist immer noch ein Byte kürzer als āɨšJõKund viel ähnlicher als das, was Sie ursprünglich hatten.
Grimmy

1
@Grimy Ah, das ist in der Tat nicht das, was ich anfangs hatte, ich mag es. :) Danke noch einmal!
Kevin Cruijssen

1
@Grimy Habe selbst noch einen Golf gefunden, den ich vergessen habe .. ástatt õKam Ende. :)
Kevin Cruijssen

1
Schöner Fund mit á! Hier ist eine 51 und eine andere . 50 fühlt sich möglich.
Grimmy

7

QuadR , 137 Byte SBCS

Titeletui mit einem führenden Leerzeichen.

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

Probieren Sie es online!

ϵ nlist (flatten)
¯2↑¨ nimm die letzten zwei Zeichen (links mit einem Leerzeichen aufgefüllt ) von jedem Zeichen
@ an Positionen, an denen
(∊∘⎕A) Zeichen Mitglieder des Großbuchstaben A lphabet sind,
 als Ergebnis der folgenden PCRE-Ersetzungsoperation…

(.) Jedes Zeichen,
\1 dem
* null oder mehrmals ein Zeichen folgt , wird durch das folgende Ergebnis ersetzt:

{…}⍵M "dfn"; ist der M atch des obigen Musters

('OhOneTwoThreeFourFiveSixSevenEightNine'(... )⎕A) die folgende anonyme stillschweigende Funktion mit der langen Schnur und die Groß gelten A lphabet als linke Argumente:

 Mitgliedschaft (von Buchstaben in der langen Zeichenkette in Großbuchstaben)

 Partitionen (mit einer neuen Partition, die beginnt, wenn sie Mitglied ist

 das linke Argument (dh die lange Zeichenkette)

(... )⎕R PCRE R eplace folgende Muster mit diesen Worten:

⎕D die Ziffern 0 bis 9

 Behandle jedes als ein separates Muster

⍺←Weisen Sie  diese Ersatzfunktion zu (für ein Lphabetise)

dann,

⊃⍵ das erste Zeichen des Spiels

, als Zeichenfolge

 anwenden , um es

w← ordne dies zu w(für Wort )

' '∊: Wenn Space Mitglied ist (dh wenn das Match leer war):

 nichts zurückgeben (wird zur leeren Zeichenkette)

 sonst,

1=≢⍵: Wenn man der Anzahl der Zeichen in der Übereinstimmung entspricht (dh der Länge):

⍺⍵ Alphabetisieren Sie diese Ziffer

 sonst,

3=≢⍵: wenn drei gleich der Anzahl der Zeichen in der Übereinstimmung ist (dh ihre Länge):

'Triple',w prepend "Triple" , um die w ord

 sonst,

2↓⍵ fallen auf Ziffern aus dem Match

 darauf zurückgreifen

w, das Wort voranstellen

'Double', "Double" voranstellen


6

JavaScript (ES6),  161 160 152  144 Byte

Die Ausgabe enthält ein einzelnes führendes Leerzeichen.

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

Probieren Sie es online!

oder Siehe den formatierten Quellcode

Wie?

Die Konvertierung erfolgt in drei Schritten:

  1. Ersetzen Sie jede Ziffer durch das entsprechende englische Wort, dem ein Leerzeichen vorausgeht
  2. Ersetzen Sie jedes Muster "X X"durch"double X"
  3. Ersetzen Sie jedes Muster "double X X"durch"triple X"

Um Bytes zu sparen, verwenden wir für alle Schritte den gleichen regulären Ausdruck:

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

was wie folgt funktioniert:

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

In Schritt 1 verwenden wir eine Rückruffunktion, die das richtige Wort aus einer Nachschlagetabelle auswählt:

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

In Schritt 2 ersetzen wir durch "$1 double$2":

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

In Schritt 3 ersetzen wir durch "triple$2":

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



3

Python 2 , 171 169 168 Bytes

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

Probieren Sie es online!

-1 Byte, danke an Jitse


Schlagt mich noch einmal! Speicher 1 Byte wie so
Jitse

@Jitse, das funktioniert nicht für 1312;)
TFeld

Ah, du hast recht!
Jitse

Wie wäre es dann mit diesem: ['','double ','triple '][n]bis ' eellpbiurotd'[-n:0:-2]für 168 Bytes: Probieren Sie es online!
Jitse

Alternativ auch 168 Bytes
Jitse

3

Perl 5 -p , 111 Bytes

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

Probieren Sie es online!

Erläuterung:

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
Ein paar Bytes weniger rasiert: 106
Xcali

3

Scala , 213 Bytes

Ich habs. Irgendwie war die rekursive Version, die ich zu erstellen versuchte, viel ausführlicher als diese (immer noch rekursiv, aber nur in einem Fall). Die Funktion fnimmt die Telefonnummer als Eingabezeichenfolge und gibt ihre Phonetik mit einem nachgestellten Leerzeichen aus.

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

Probieren Sie es online!
Edit : -8b dank DrY Wit!

Scala , 215 Bytes

Und hier kommt die führende Whitespace-Version, die aus irgendeinem Grund zwei Bytes länger ist (auch bei massivem Refactoring).

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

Probieren Sie es online!


2
Sie können 8 Bytes speichern durch Ersetzen (o(0)+"").toIntmit o(0)-48.
Dr Y Wit

Oof gut gemacht @DrYWit danke!
V. Courtois

3

PHP , 174 169 166 159 Bytes

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

Probieren Sie es online!

Für jede Ziffer bei Index $iab 0:

  • Wenn die Spanne der gleichen Ziffer ab Position von $igleich 3 ist, wird gedruckt 'triple 'und zu 2 addiert, $isodass bei der nächsten Iteration 2 Stellen übersprungen werden.
  • Wenn die Spanne der gleichen Ziffer ab Position von $imindestens 2, aber nicht 3 beträgt, wird 1 gedruckt 'double 'und zur $inächsten Iteration hinzugefügt, sodass 1 Ziffer übersprungen wird.
  • Gibt ein Wort für die Ziffer und ein Leerzeichen aus.
  • $i++.

2

Retina 0,8,2 , 105 Bytes

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

Probieren Sie es online! Gibt ein führendes Leerzeichen aus. Erklärung: Ich habe ursprünglich versucht, eine Regex zu verwenden, die automatisch mit 2 oder 3 Ziffern übereinstimmt, aber der Ansatz von @ Arnauld erwies sich als golferisch. Erläuterung:

+`(.)\1
=$1

Ordnen Sie identische Ziffernpaare zu und ersetzen Sie die erste durch a =. Dann wiederholen, so dass bei einer ungeraden Zahl auch die vorletzte Ziffer durch a ersetzt wird =.

.
 $&

Leert die Ziffern (und =s) aus.

= =
triple

Behandeln Sie den Fall von drei identischen Ziffern.

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

Ersetzen Sie alle verbleibenden Zeichen durch Wörter.


2

Jelly , 59 Bytes

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

Probieren Sie es online!

Eine monadische Verknüpfung, die eine Zeichenfolge aus Ziffern als Argument verwendet und eine Jelly-Zeichenfolge aus durch Leerzeichen getrennten Wörtern zurückgibt. Beim Aufruf als Vollprogramm erfolgt die Ausgabe implizit.


2

T-SQL 2017, 238 Byte

Einige Zeilenumbrüche hinzugefügt, um die Lesbarkeit zu verbessern

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 @

Probieren Sie es online aus


2

C ++, 382 Bytes

Es ist kein Superclever, aber jemand musste eine C ++ - Version schreiben. Die rekursive Funktion R durchläuft die Eingabezeichenfolge und zählt die wiederholten Werte. Wenn es mehr als 3 Wiederholungen gibt, wird so getan, als ob es 2 Wiederholungen gäbe, dann wird zurückgespult und es wird erneut versucht.

Ein paar weitere Quell-Zeichen könnten wahrscheinlich mit #defineMajor herausgedrückt werden, aber ich bin sicher, dass ein besserer Algo mehr herausdrücken könnte.

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

und Verifikation von Testfällen:

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
Braucht der Golf-Teil eigentlich #include <sstream>? Oder können Sie das nach dem Golfspiel für die Testfunktion nach unten verschieben? Ich denke, das Tippen std::ostream&swürde weniger Platz beanspruchen als using namespace std;, es sei denn, es gibt andere Stellen, an denen Sie eine benötigen würden std::.
Peter Cordes


2

Perl 6 , 96 93 Bytes

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

Probieren Sie es online!

Dies ist ein anonymer Codeblock, der eine Zahl akzeptiert und eine Zeichenfolge mit den Zahlen in Großbuchstaben zurückgibt, z. B. 0123 => oh ONE TWO THREEmit einem einzelnen nachgestellten Leerzeichen.

Dies wurde für eine Weile gelöscht, bis ich herausfand, wie man Captures in einem Lookahead verwendet, aber es sollte jetzt behoben werden.


1

rot , 242 Bytes

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

Probieren Sie es online!


1

Scala , 253 Bytes

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

Probieren Sie es online!


1

Oracle SQL, 578 Bytes (in formatierter Form)

Die Lösung ist in keiner Weise präzise, ​​so dass sie in formatierter Form veröffentlicht wird.

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

Testen Sie in 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

Der Haupttrick besteht darin, dass Ziffern, die mithilfe von Oracle-Formatmodellen in Wörter umgewandelt wurden, anstelle von hartcodierten Literalen "eins" ... "neun".


Gibt es eine Chance dafür, dass Golf gespielt wird? es scheint, dass Sie eine Reihe von Leerzeichen entfernen können. Ich stelle mir auch vor, Sie können WHERE s nicht auf WHERE s> ''
umschreiben

1
Sie können ein paar Zeichen speichern , indem ersetzt , was nach union allmit select regexp_replace(s,case when length(regexp_substr(s, '(.)(\1)+')) = 3 then '^...' else '^(.)\1|^.' end) from r.
Steve Kass

1

JavaScript, 142 Bytes

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

Probieren Sie es online!


1

(Roblox) Lua 5.1 , 166 Bytes

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

Stellen Sie sicher, dass ses sich um einen vordefinierten Zeichenfolgenwert handelt, der nur mit Ziffern gefüllt ist. Das ist die Variable, die geändert werden soll. Das Ergebnis enthält ein führendes Leerzeichen [\u20] .


Willkommen auf der Seite! Da Lua Eingaben über Standardmethoden entgegennehmen kann, verstößt es gegen die Regeln s, bereits Eingaben zu verlangen . Abgesehen davon hast du einen guten ersten Beitrag! Ich würde empfehlen, dass Sie einen Link zu einer Online-Test-Site hinzufügen , z. B. tio.run/#lua, damit andere Ihre Lösung testen können
caird coinheringaahing

Hallo. Die Variante von Lua, auf der ich getestet habe (Rbx.Lua), enthält keine Eingabemethoden, obwohl die Sandbox über Druck-, Warn- und Fehlerausgabemethoden verfügt.
VisualPlugin Rōblox
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.