หมายเลขโทรศัพท์เป็นคำพูด


33

เป้าหมาย

เขียนโปรแกรมหรือฟังก์ชั่นที่แปลหมายเลขโทรศัพท์ที่เป็นตัวเลขเป็นข้อความที่ทำให้พูดง่าย เมื่อตัวเลขซ้ำกันพวกเขาควรจะอ่านว่า "double n" หรือ "triple n"

ความต้องการ

อินพุต

สตริงของตัวเลข

  • สมมติว่าตัวละครทุกตัวเป็นตัวเลขตั้งแต่ 0 ถึง 9
  • สมมติว่าสตริงมีอักขระอย่างน้อยหนึ่งตัว

เอาท์พุต

คำที่คั่นด้วยช่องว่างทำให้สามารถอ่านตัวเลขเหล่านี้ได้อย่างชัดเจน

  • แปลตัวเลขเป็นคำ:

    0 "โอ้"
    1 "หนึ่ง"
    2 "สอง"
    3 "สาม"
    4 "สี่"
    5 "ห้า"
    6 "หก"
    7 "เจ็ด"
    8 "แปด"
    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
ใครก็ตามที่สนใจใน "speech golf" ควรทราบว่า "double six" ใช้เวลาในการพูดนานกว่า "six six" จากความเป็นไปได้เชิงตัวเลขทั้งหมดที่นี่มีเพียง "สามเจ็ด" เท่านั้นที่จะบันทึกพยางค์
Purple P

13
@Purple P: และอย่างที่ฉันแน่ใจว่าคุณรู้ 'double-u double-u double-u'> 'เวิลด์ไวด์เว็บ' ..
Chas Brown

11
ฉันลงคะแนนให้เปลี่ยนจดหมายนั้นเป็น "พากย์"
อาหารมือ

8
ฉันรู้ว่านี่เป็นเพียงการออกกำลังกายทางปัญญา แต่ฉันมีตั๋วจ่ายก๊าซที่อยู่ด้านหน้าหมายเลข 0800 048 1,000 และฉันจะอ่านว่า "โอ้แปดแสนสี่สี่แปดหนึ่งพัน" การจัดกลุ่มตัวเลขมีความสำคัญต่อผู้อ่านของมนุษย์และบางรูปแบบเช่น "0800" ได้รับการปฏิบัติเป็นพิเศษ
Michael Kay

3
@PurpleP ทุกคนที่สนใจในความชัดเจนของคำพูดอย่างไรก็ตามโดยเฉพาะอย่างยิ่งเมื่อพูดทางโทรศัพท์อาจต้องการใช้ "double 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ดูรายการข้างในเมื่อพิจารณาจำนวนเต็มที่สูงสุดในกองหรือไม่ ไม่ทราบว่า เสียงเหมือนสิ่งที่ต้องจำ :)
Kevin Cruijssen

16

8088 Assembly, 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 มีคำแนะนำสั้น ๆ ( REPNZ SCASBซึ่งคล้ายกับmemchr()ใน C) ซึ่งทำให้คำสั่งนี้ง่ายขึ้น (ขอบคุณCISC !)

หากตัวเลขนั้นเหมือนกันกับตัวก่อนหน้าตัวนับสำหรับความยาวของ "การทำงาน" จะเพิ่มขึ้นและยังคงวนซ้ำไปทางซ้ายบนอินพุต เมื่อจบการทำงานแล้วชื่อของตัวเลขจะถูกนำมาจากสแต็กเพราะจะต้องวางหลังจาก "double" หรือ "triple" สำหรับการจัดกลุ่มแต่ละครั้ง หากความยาวของการวิ่งเป็นเลขคี่ (และความยาวของการวิ่งคือ> 1) ชื่อของหลักตามด้วยสตริง "สาม" จะถูกผลักไปที่สแต็กและความยาวของการวิ่งจะลดลง 3 เนื่องจากความยาวของการวิ่งจะเท่ากัน ซ้ำสำหรับ "double" จนกระทั่งความยาวรันเท่ากับ 0

เมื่ออินพุตสตริงถึงจุดสิ้นสุดสแต็กจะถูกดัมพ์กับแต่ละสตริงที่บันทึกไว้ที่เขียนไปยังหน้าจอตามลำดับย้อนกลับ

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]ฉันสงสัยว่าการใช้ reg อื่นเช่นAHสำหรับการนับด้วยdec ah / jnzแทนที่จะloopช่วยอะไรจากการไม่ต้องกด / pop CX อาจจะไม่ได้และคุณไม่ได้มี Regs 16 บิตที่เหลือที่จะช่วยให้ dec1
Peter Cordes

1
@PeterCordes สำหรับCH=0ฉันไปโดยfysnet.net/yourhelp.htmซึ่งสำหรับการเปิดตัวที่เหมาะสมใด ๆ ของ DOS จะ zero'd BXเสมอเช่นเดียวกันกับ ดีที่คิดเกี่ยวกับการขยายศูนย์movแต่ในทางเทคนิคแล้วฉันไม่คิดว่าmovzxมีอยู่ใน 808x (ทำให้แพลตฟอร์มเป้าหมายเป็นพีซี IBM 5150 และทั้งหมด) ฉันเล่นกับทุกแห่งที่ดีที่สุดที่ฉันสามารถบันทึกไบต์ แต่ถ้าคุณเห็นสิ่งที่ฉันอาจพลาดโปรดแจ้งให้เราทราบ!
640KB

1
แม่นยำกว่าที่จะเรียกว่าmemchrIMO การตั้งชื่อ "คำสั่งสตริง" ทำให้คนเข้าใจผิดว่าพวกเขาทำงานกับสตริง C ที่มีความยาวโดยนัย แต่จริงๆแล้วพวกเขาทำงานกับสตริงที่มีความยาวอย่างชัดเจนเช่นstd::stringหรือบัฟเฟอร์ ชอบmemcpy, memset(MOVs / stos) memchr/ memrchr(SCAs repne กับ DF = 0 หรือ 1) และmemcmp(CMPS repe) สิ่งเดียวที่เทียบเท่ากับ C repe scasคือstrspnเพราะฉันไม่คิดว่าจะมีmemฟังก์ชั่นสำหรับสิ่งนั้น คุณสามารถอธิบายstoswหรือstosdเป็นwmemsetตัวอย่างได้
Peter Cordes

1
movzxค่าใช้จ่าย opcode พิเศษและใช่มันถูกนำมาใช้กับ 386 มันเป็นเรื่องง่ายที่จะพิมพ์เพื่ออธิบายความจริงที่ว่าคุณกำลังทำไบต์ต่ำผสานและสมมติว่ามันเป็นศูนย์ขยายอย่างถูกต้อง หากคุณรู้จัก CX หรืออย่างน้อย CH = 0 แสดงว่าใช่สำหรับการเล่นกอล์ฟไปmovที่ CL เสมอ แต่ด้านนอกของกอล์ฟ x86 ของไปสู่คำแนะนำไบต์โหลดmovzxและmovsxพวกเขาหลีกเลี่ยงการอ้างอิงเท็จใด ๆ หรืออื่น ๆ แง่บางส่วนลงทะเบียน บนซีพียูรุ่นใหม่ที่มีปลายทาง dword จะเร็วเท่ากับmov โหลดdword
Peter Cordes

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 Ah แน่นอน .. ฉันเพิ่มif(length>=4)ส่วนที่เหลือก่อนหน้านี้ แต่แน่นอนว่ามันไม่จำเป็นสำหรับจำนวนเต็ม1,2,3เพราะ;Å2¨3ª£จะทำให้สตริงคงสภาพเหมือนเดิม ขอบคุณที่สังเกต! Åγและมองไปข้างหน้าเห็นคำตอบของคุณด้วย ฉันมีความรู้สึกแน่นอนว่าส่วนแรกสามารถทำได้สั้นกว่านี้มาก
Kevin Cruijssen

1
Dg;LàäRยังคงเป็นไบต์ที่สั้นกว่าāɨšJõKและคล้ายกับสิ่งที่คุณมีในตอนแรก
Grimmy

1
@Grimy Ah มันใกล้เคียงกับสิ่งที่ฉันมีในตอนแรกฉันชอบมัน :) ขอบคุณอีกครั้ง!
Kevin Cruijssen

1
@Grimy รับสามารถหาอีกหนึ่งกอล์ฟตัวเองซึ่งฉันลืมเกี่ยวกับ .. áแทนที่จะõKจบ :)
Kevin Cruijssen

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) ตัวละครที่เป็นสมาชิกของตัวพิมพ์ใหญ่ lphabet
 ในผลของการดำเนินการดังต่อไปนี้ PCRE แทนที่ ...

(.) ตัวละครใด ๆ
\1  ตามมาด้วยตัวเอง
* เป็นศูนย์หรือมากกว่านั้นจะถูกแทนที่ด้วยผลลัพธ์ต่อไปนี้

{…}⍵M "DFN"; คือ M atch ของรูปแบบด้านบน

('OhOneTwoThreeFourFiveSixSevenEightNine'()⎕A) ใช้ฟังก์ชั่นเงียบโดยไม่ระบุชื่อต่อไปนี้กับสตริงยาวและตัวพิมพ์ใหญ่ A lphabet เป็นอาร์กิวเมนต์ซ้าย:

 สมาชิก (ของตัวอักษรในสตริงยาวในตัวอักษรตัวพิมพ์ใหญ่)

 พาร์ติชัน (ด้วยพาร์ติชันใหม่ที่เริ่มต้นเมื่อใดก็ตามที่เป็นสมาชิก

 อาร์กิวเมนต์ซ้าย (เช่นสตริงยาว)

()⎕R PCRE Rแทนที่รูปแบบต่อไปนี้ด้วยคำเหล่านั้น:

⎕D ตัวเลข 0 ถึง 9

 ถือว่าแต่ละแบบแยก

⍺← กำหนดฟังก์ชั่นนี้เพื่อทดแทน(สำหรับ lphabetise)

แล้ว

⊃⍵ อักขระตัวแรกของการแข่งขัน

, เป็นสตริง

 ใช้ ไปกับมัน

w← กำหนดสิ่งนี้ให้กับw(สำหรับคำ )

' '∊...:  ถ้าช่องว่างเป็นสมาชิกของมัน (เช่นถ้าการแข่งขันว่างเปล่า):

 คืนค่าอะไร (กลายเป็นสตริงว่าง)

 อื่น,

1=≢⍵: หากหนึ่งเท่ากับจำนวนตัวละครในการแข่งขัน (เช่นความยาวของมัน):

⍺⍵ ตัวอักษรหลักที่

 อื่น,

3=≢⍵: ถ้าสามเท่ากับจำนวนตัวละครในการแข่งขัน (เช่นความยาว):

'Triple',w เติม "Triple" เป็นw ord

 อื่น,

2↓⍵ วางตัวเลขจากการแข่งขัน

 ชดเชยสิ่งนั้น

w, เสริมคำ

'Double', เติม "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

Python 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 ไบต์ขอบคุณ Jitse


เอาชนะฉันอีกครั้ง! บันทึก 1 ไบต์เช่นดังนั้น
Jitse

@Jitse ที่ใช้งานไม่ได้1312;)
TFeld

อ่าคุณพูดถูก!
Jitse

วิธีการเกี่ยวกับเรื่องนี้แล้ว: ['','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

สกาลา 213 ไบต์

เข้าใจแล้ว อย่างใดรุ่น recursive ฉันพยายามที่จะสร้างเป็น verbose-y ยิ่งกว่านี้อย่างใดอย่างหนึ่ง (ยังคงเรียกซ้ำ แต่ แต่ในกรณีเดียว) ฟังก์ชั่น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
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].' ');

ลองออนไลน์!

สำหรับแต่ละหลักที่ดัชนีของ $iเริ่มต้นจาก 0:

  • หากช่วงของตัวเลขเดียวกันเริ่มต้นจากตำแหน่งของ$iเท่ากับ 3 ให้พิมพ์'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

ลองออนไลน์! ส่งออกพื้นที่ชั้นนำ คำอธิบาย: ตอนแรกฉันลองใช้ regex ที่จับคู่ตัวเลข 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

ลองออนไลน์!

ลิงก์ monadic ที่รับสายอักขระตัวเลขเป็นอาร์กิวเมนต์และส่งคืนสตริง 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 ไบต์

ไม่ใช่ superclever แต่มีคนต้องการเขียนเวอร์ชัน 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>หรือไม่? หรือคุณจะเลื่อนมันลงหลังจากส่วน golfed สำหรับฟังก์ชั่นการทดสอบได้หรือไม่? ผมคิดว่าการพิมพ์std::ostream&sจะใช้พื้นที่น้อยกว่าusing namespace std;เว้นแต่มีสถานที่อื่น ๆ std::ที่คุณต้องการต้อง
Peter Cordes


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มีช่องว่างท้ายเดียว

สิ่งนี้ถูกลบไประยะหนึ่งแล้วจนกระทั่งฉันพบวิธีใช้งานการดักจับใน lookahead แต่ควรได้รับการแก้ไขแล้ว




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> ''
t-clausen.dk

1
คุณสามารถบันทึกตัวอักษรไม่กี่โดยการเปลี่ยนสิ่งที่อยู่หลังด้วยunion all select 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เพื่อให้ผู้อื่นสามารถทดสอบวิธีการแก้ปัญหาของคุณ
caird coinheringaahing

สวัสดี ตัวแปรของ Lua I กำลังทดสอบ (Rbx.Lua) ไม่มีวิธีการป้อนข้อมูลแม้ว่า sandbox จะมีวิธีการพิมพ์การเตือนและการแสดงข้อผิดพลาด
VisualPlugin Rōblox
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.