말로 된 전화 번호


33

숫자로 된 전화 번호를 말하기 쉬운 텍스트로 변환하는 프로그램이나 기능을 작성하십시오. 숫자가 반복되면 "double n"또는 "triple n"으로 읽어야합니다.

요구 사항

입력

자릿수입니다.

  • 모든 문자가 0에서 9까지의 숫자라고 가정하십시오.
  • 문자열에 하나 이상의 문자가 있다고 가정하십시오.

산출

이 숫자를 크게 읽을 수있는 방법에 대한 공백으로 구분 된 단어.

  • 숫자를 단어로 번역 :

    0 "oh"
    1 "one"
    2 "two"
    3 "three"
    4 "four"
    5 "five"
    6 "6"
    7 "7"
    8 "eight"
    9 "9"

  • 같은 숫자가 한 번에 두 번 반복되면 "double number "를 쓰십시오 .

  • 같은 숫자가 한 번에 세 번 반복되면 "트리플 번호 "를 쓰십시오 .
  • 같은 숫자가 네 번 이상 반복 되면 처음 두 자리에 "double number "를 쓰고 나머지 문자열을 평가하십시오.
  • 각 단어 사이에는 정확히 하나의 공백 문자가 있습니다. 단일 선행 또는 후행 공간이 허용됩니다.
  • 출력은 대소 문자를 구분하지 않습니다.

채점

바이트가 가장 적은 소스 코드.

테스트 사례

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
"음성 골프"에 관심이있는 사람은 "더블 식스"가 "식스 식스"보다 말하는 데 시간이 오래 걸린다는 점에 유의해야합니다. 여기서 모든 수치 적 가능성 중에서 "삼중 일곱"만이 음절을 절약합니다.
자주색 P

13
@Purple P : 그리고 당신도 알다시피, 'double-u double-u double-u'> 'world wide web'..
Chas Brown

11
나는 그 편지를 "dub"로 바꾸겠다고 투표했다.
손 전자 음식

8
나는 이것이 지적 운동 일 뿐이라는 것을 알고 있지만, 0800 048 1000 번호의 가스 요금 청구서를 가지고 있는데 이것을 "오 팔 백 오 사 팔 천"이라고 읽습니다. 자릿수 그룹화는 인간 독자에게 중요하며 "0800"과 같은 일부 패턴은 특별히 처리됩니다.
마이클 케이

3
@PurpleP 그러나 명확하게 말하기를 원하는 사람, 특히 전화로 말할 때는 "더블 6"을 사용하는 것이 좋습니다. 왜냐하면 스피커가 2/6을 의미하고 실수로 6을 반복하지 않았기 때문입니다. 사람들은 로봇이 아닙니다 : P
Monica

답변:


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스택의 최대 정수를 결정할 때 목록 내부를 살펴보십시오. 몰랐어요 기억해야 할 것 같습니다. :)
Kevin Cruijssen

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 스택 으로 푸시되어 표시 순서 반전을 단순화하고 숫자 이름 앞에 "double"및 "triple"단어를 쉽게 다시 정렬 할 수 있습니다.

다음 숫자가 마지막 숫자와 다른 경우 이름이 단어 목록에서 조회되어 스택으로 푸시됩니다. 기계 코드에는 "가변 길이 문자열의 색인 배열"에 대한 공식적인 개념이 없기 때문에, 단어 목록 i(문자 색인)이 문자열 분리 문자 ( $)에 해당하는 단어를 찾기 위해 스캔됩니다 (단어 색인) . 유용하게도 x86에는 C REPNZ SCASB와 비슷한 간단한 명령어 쌍이있어서 memchr()이를 단순화합니다 ( CISC 덕분에 ).

숫자가 이전 숫자와 동일하면 "실행"길이의 카운터가 증가하고 입력에서 왼쪽으로 계속 반복됩니다. 실행이 끝나면 각 그룹의 "더블"또는 "트리플"뒤에 배치해야하므로 숫자 이름이 스택에서 가져옵니다. 런의 길이가 홀수이고 런 길이가 > 1이면 문자열 "triple"뒤에 오는 숫자 이름이 스택으로 푸시되고 런 길이는 3만큼 줄어 듭니다. 실행 길이가 0이 될 때까지 "double"에 대해 반복됩니다.

입력 문자열이 끝에 도달하면 스택에 저장된 각 문자열이 역순으로 화면에 기록됩니다.

I / O :

명령 행 출력에서 ​​콘솔로 입력되는 독립형 PC DOS 실행 파일.

enter image description here

PHONE.COM을 다운로드하여 테스트 하십시오 .


repne scasb한다 memchr(또는 strchr하지 당신이 알고있는 경우 타격이있을거야) strstr.
Peter Cordes

프로세스 엔트리의 CH = 0이 표준에 의해 보장됩니까, 아니면 일부 DOS 버전이하는 일입니까? 나는 당신이 그것 mov cl, byte[si] 과 같다고 가정합니다 movzx cx, byte [si]. 같은 다른 등록 번호를 사용하는 경우 궁금 AH와 함께 카운트, dec ah / jnz대신 loop밀어하지 않아도 아무것도 절약 할 수 / CX 팝. 아마도 그렇지 않으며 1 바이트를 허용하는 16 비트 레지스터가 남아 있지 않습니다 dec.
Peter Cordes

1
@PeterCordes의에 CH=0의한 I의 이동 fysnet.net/yourhelp.htm DOS의 합리적인 방출을 위해 항상와 같은, zero'd된다 BX. mov기술적으로 필자는 movzx808x에서 사용할 수 없다고 생각하지만 zero-extend에 대해 잘 생각 합니다 (대상 플랫폼을 IBM PC 5150 등으로 유지). 바이트를 저장하기 위해 최선을 다해 모든 레지스터를 살펴 보았지만 놓친 부분이 있으면 알려주십시오.
640KB

1
memchrIMO 라고하는 것이 더 정확합니다 . "문자열 명령"이름 지정은 사람들이 암시 적 길이 C 문자열에서 작업한다고 생각하도록 오도하지만 실제로는 std::string버퍼 와 같은 명시 적 길이 문자열에서 작동합니다 . 마찬가지로 memcpy, memset(MOVS / stos) memchr/ memrchr및 (DF = 0 또는 1의 REPNE SCAS) memcmp(REPE의 CMPS). 유일한 C 상당 repe scas이다 strspn나는 생각하지 않기 때문에 mem함수가 그것을 위해. 당신은 설명 할 수 stosw또는 stosd같은 wmemset예를 들어.
Peter Cordes

1
movzx추가 opcode 바이트가 필요합니다. 그렇습니다. 386에만 도입되었습니다. 낮은 바이트 병합을 수행하고 정확하게 0으로 확장되었다고 가정하면 입력하기가 더 쉬웠습니다. CX 또는 최소한 CH = 0을 알고 있다면 골프에 대한 예는 항상 movCL 로 이동하십시오 . 그러나 골프 이외의 x86의 go-to byte-load 명령어는 다음 movzxmovsx같습니다. 잘못된 의존성 또는 다른 부분 레지스터 shenanigan을 피합니다. dword 대상이있는 최신 CPU에서는 dword mov 로드 만큼 빠릅니다 .
Peter Cordes

9

05AB1E , 61 56 53 52 51 바이트

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

@Grimy 덕분에 -9 바이트 .

온라인으로 시도 하거나 모든 테스트 사례를 확인하십시오 .

설명:

γ               # 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 Ah, 물론 .. if(length>=4)나머지를 추가하기 전에를 추가했지만 물론 문자열을 그대로 유지 1,2,3하기 때문에 size의 정수에는 필요하지 않습니다 ;Å2¨3ª£(단순히지도 뒤에 평평한 목록에 싸서 있기 때문에 ). 알아 주셔서 감사합니다! 님의 답변을 기다리겠습니다 Åγ. 나는 실제로 첫 번째 부분이 어떻게 든 더 짧아 질 수 있다고 생각했습니다.
케빈 크루이 센

1
Dg;LàäR여전히 바이트보다 짧으며 āɨšJõK원래 가지고 있던 것과 훨씬 비슷합니다.
그리미

1
@ 그림 아, 그것은 실제로 내가 처음에했던 것에 폐쇄되었습니다, 나는 그것을 좋아합니다. :) 다시 감사합니다!
케빈 크루이 센

1
@Grimy 나는 약 .. 잊고있는 또 하나 개의 골프 나 자신을 발견 할 수 있었다 á대신의 õK말에. :)
Kevin Cruijssen

1
좋은 찾기 á! 여기 에 51다른 것이 있습니다. 50 느낌이 가능합니다.
그리미

7

QuadR , 137 바이트 SBCS

선행 공백이있는 제목 사례.

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

온라인으로 사용해보십시오!

ε NLIST (펼치기)
¯2↑¨ 각 문자의 마지막 두 문자를 가지고 (공간 왼쪽에 패딩)
@ 위치에
(∊∘⎕A) 문자가 대문자의 구성원 인 경우 → lphabet
 PCRE 아래 교체 작업의 결과에 ...

(.) 그
\1 뒤에
* 0 번 이상 나오는 문자 는 다음의 결과로 대체됩니다.

{…}⍵M "dfn"; 위 패턴 M atch입니다.

('OhOneTwoThreeFourFiveSixSevenEightNine'()⎕A) 긴 문자열과 대문자 A lbet를 왼쪽 인수로 사용 하여 다음 익명의 암묵적 함수를 적용하십시오 .

 멤버십 (대문자의 긴 문자열 문자)

 파티션 (회원 일 때마다 새 파티션이 시작됨)

 왼쪽 인수 (즉, 긴 문자열)

(... )⎕R PCRE R eplace 그 단어 다음과 같은 패턴

⎕D 0에서 9까지의 숫자

 각각을 별도의 패턴으로 취급

⍺← 이 여분의 기능을 할당 (대 lphabetise)를

그때,

⊃⍵ 경기의 첫 문자

, 끈으로

그것에  적용

w← 이것을 w( 단어 )에 할당하십시오.

' '∊: 공간이 그 구성원 인 경우 (즉, 경기가 비어있는 경우) :

 아무것도 반환하지 않습니다 (빈 문자열이 됨)

 그밖에,

1=≢⍵: 하나가 일치하는 문자의 집계와 같은 경우 (예 : 길이) :

⍺⍵ 그 숫자를 알파벳순으로

 그밖에,

3=≢⍵: 3이 일치하는 문자의 집계와 같은 경우 (예 : 길이) :

'Triple',w 받는 사람 앞에 추가 "트리플" w ORD

 그밖에,

2↓⍵ 경기에서 숫자로 드롭

 그것에 재귀

w, 단어 앞에 붙이다

'Double', 접두사 "Double"


6

자바 스크립트 (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:]

온라인으로 사용해보십시오!

Jitse 덕분에 -1 바이트


다시 이길! 저장 1 바이트처럼 그렇게
Jitse

@Jitse, 그것은 작동하지 않습니다 1312;)
TFeld

아 맞아!
Jitse

어떻게 이런 일에 대해 다음 : ['','double ','triple '][n]' eellpbiurotd'[-n:0:-2]168 바이트 : 온라인으로보십시오!
Jitse


3

펄 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
몇 바이트를
줄였습니다

3

스칼라 , 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)}})

온라인으로 사용해보십시오!
편집 : DrY Wit 덕분에 -8b!

스칼라 , 215 바이트

그리고 여기에 어떤 이유로 든 2 바이트 더 긴 (공백 리팩토링에서도) 주요 공백 ​​버전이 제공됩니다.

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)+"").toInto(0)-48.
Dr Y Wit

잘 했어요 @DrYWit 감사합니다!
V. Courtois

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

온라인으로 사용해보십시오!

$i0부터 시작하는 인덱스의 각 숫자에 대해 :

  • 의 위치에서 시작하는 동일한 숫자의 범위가 $i3과 같으면 'triple '2를 인쇄 하고$i 하여 다음 반복에서 2 자리 숫자를 건너 뜁니다.
  • 의 위치에서 시작하는 동일한 숫자의 범위 $i가 2 이상이지만 3이 아닌 경우 'double '1을 인쇄 하여 다음에 추가합니다.$i 하므로 다음 반복에서는 1 자리 숫자가 건너 뜁니다.
  • 숫자와 공백에 대한 단어를 인쇄합니다.
  • $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 자리와 자동으로 일치하는 정규 표현식을 시도했지만 @Arnauld의 접근 방식은 골퍼로 밝혀졌습니다. 설명:

+`(.)\1
=$1

동일한 숫자 쌍을 일치시키고 첫 번째 숫자를 = . 그런 다음 홀수의 경우 두 번째 마지막 숫자도로 바뀌도록 반복하십시오 =.

.
 $&

자릿수 간격 (및 = s .

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

온라인으로 사용해보십시오!

숫자 문자열을 인수로 사용하고 공백으로 구분 된 단어의 젤리 문자열을 반환하는 모나드 링크입니다. 전체 프로그램으로 호출되면 암시 적으로 출력됩니다.


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::입니다.
Peter Cordes


2

펄 6 , 96 93 바이트

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

온라인으로 사용해보십시오!

이것은 숫자를 취해 숫자가 대문자 인 문자열을 반환하는 익명 코드 블록입니다. 0123 => oh ONE TWO THREE 단일 후행 공백).

미리보기에서 캡처를 사용하는 방법을 찾을 때까지 잠시 동안 삭제되었지만 지금 수정해야합니다.



1

스칼라 , 253 바이트

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

온라인으로 사용해보십시오!


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

주요 트릭은 숫자가 하드 코딩 된 리터럴 "1"... "9"대신 Oracle 형식 모델을 사용하여 단어로 변환되는 것입니다.


골프를 치게 될 가능성이 있습니까? 많은 공간을 제거 할 수있는 것 같습니다. 또한 WHERE가 null이 아닌 WHERE에 다시 쓸 수 있다고 생각합니다.> ''
t-clausen.dk

1
당신은 이후에 무엇을 대체하여 몇 개의 문자를 저장할 수 있습니다 union allselect regexp_replace(s,case when length(regexp_substr(s, '(.)(\1)+')) = 3 then '^...' else '^(.)\1|^.' end) from r.
Steve Kass


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 그래서 다른 사람들이 당신의 솔루션을 테스트 할 수 있음
케어 드 coinheringaahing

안녕. 샌드 박스에 인쇄, 경고 및 오류 출력 방법이 있지만 테스트 한 Lua I의 변형 (Rbx.Lua)에는 입력 방법이 포함되어 있지 않습니다.
VisualPlugin Rōblox
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.