语音电话号码


33

目标

编写程序或函数,将数字电话号码转换为易于说出的文本。重复数字时,应将它们读为“双n”或“三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
任何对“语音高尔夫”感兴趣的人都应该注意,“双六”比“六六”花费的时间更长。在这里所有的数值可能性中,只有“三分之七”节省了音节。
紫色P

13
@Purple P:我确定你知道,'double-u double-u double-u'>'World Wide Web'..
Chas Brown

11
我投票将该字母更改为“ dub”。
Hand-E-Food

8
我知道这只是一种理智的练习,但是我面前有一张天然气法案,编号为0800 048 1000,我会读为“哦八百哦四八千一千”。数字的分组对人类读者很重要,并且某些模式(例如“ 0800”)会被特别对待。
Michael Kay

3
@PurpleP 但是,对语音清晰度感兴趣的任何人,尤其是在电话中讲话时,可能都希望使用“双6”,因为更清楚的是说话者的意思是两个6,并且不会偶然重复6。人不是机器人:P
道歉并恢复莫妮卡

Answers:


10

05AB1E53 52 51 50 49字节

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

在线尝试!

说明:

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

1
哦,M确定堆栈上的最大整数时还会查看列表内部吗?不知道 听起来像是要记住的东西。:)
凯文·克鲁伊森

16

8088组装件,IBM PC DOS, 164 159 156 155字节

二进制:

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

xxd -r从上面构建并测试可执行文件,或下载PHONE.COM

未组装的清单:

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

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

TL; DR:

输入字符串从右到左读取,以便更轻松地查找三元组。输出被推入x86堆栈以简化显示顺序的反转,也便于重新排列“ double”和“ triple”两个单词,使其位于数字的名称之前。

如果下一位数字与最后一位数字不同,则在单词列表中查找该名称并将其压入堆栈。由于在机器代码中没有“变长字符串的索引数组”的正式概念,因此对单词列表进行扫描i(单词的索引)次数,$以查找字符串定界符()以找到相应的单词。有用的是,x86确实有一对简短的指令(REPNZ SCASB类似于memchr()C语言),从而简化了这一过程(感谢CISC!)。

如果数字与前一个数字相同,则“行程”长度的计数器增加,并继续在输入上向左循环。运行结束后,将从堆栈中获取数字名称,因为每个分组都需要将其放置在“双精度”或“三重”之后。如果游程长度为奇数(游程长度为> 1),则将数字名称和字符串“ triple”(三串)压入堆栈,并将游程长度减少3。由于游程长度现在为偶数,因此该步骤重复“双”,直到游程长度为0。

当输入字符串到达​​末尾时,堆栈将转储,每个保存的字符串都以相反的顺序写入屏幕。

输入/输出:

一个独立的PC DOS可执行文件,从命令行输出输入到控制台。

enter image description here

下载并测试PHONE.COM


repne scasbmemchr(或者,strchr如果您知道会受到打击),则不是strstr
彼得·科德斯

是通过标准保证CH = 0进入进程还是通过某种DOS版本实现的?我注意到您以为mov cl, byte[si] 等于movzx cx, byte [si]。我不知道如果使用不同的REG,如AH,为计数用dec ah / jnz的,而不是loop将节省从没有推什么/ POP CX。可能不是,您还没有剩下允许1个字节的16位reg dec
彼得·科德斯

1
@PeterCordes,因为CH=0我按fysnet.net/yourhelp.htm进行操作,对于任何合理的DOS版本,该值始终为零,与相同BXmov尽管从技术上讲我不认为movzx808x可用(将目标平台保持为IBM PC 5150等),但对零扩展进行了很好的考虑。我尽我所能地保存所有字节,以节省字节,但是如果您发现我可能会错过的内容,请告诉我!
640KB

1
称其为memchrIMO 更准确。“字符串指令”的命名会误导人们以为他们在隐式长度的C字符串上工作,但实际上他们在显式长度的字符串(如std::string或缓冲区)上工作。像memcpymemset(移动/存储),memchr/ memrchr(具有DF = 0或1的memcmp重复cas)和(重复cmps)。唯一的C等效项repe scasstrspn因为我认为没有mem功能。你甚至可以描述stoswstosd作为wmemset例如。
Peter Cordes

1
movzx花费了一个额外的操作码字节,是的,它仅在386中引入。键入来描述您正在执行低字节合并并假设正确地将其扩展为零的事实更加容易。如果您确实知道CX或至少CH = 0,那么高尔夫总是选择movCL。但是在打高尔夫球之外,x86的转到字节加载指令为movzxmovsx:它们避免任何错误的依赖关系或其他部分寄存器的恶作剧。在带有双字目标的现代CPU上,它们的速度与双字mov 加载一样快。
彼得·科德斯

9

05AB1E61 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)在添加其余部分之前添加了,但是对于size的整数,这不是必需的1,2,3,因为;Å2¨3ª£会保留字符串的完整性(只是包装在我们在映射后平展的列表中)。感谢您的关注!期待与您的回答Åγ。我确实有一种感觉,第一部分可以以某种方式缩短很多时间。
凯文·克鲁伊森

1
Dg;LàäR仍然比短一个字节āɨšJõK,并且与您最初拥有的字节非常相似。
Grimmy

1
@Grimy啊,这确实接近我最初的想法,我喜欢它。:) 再次感谢!
凯文·克鲁伊森

1
@Grimy我自己也能找到另外一个高尔夫,我忘了.. á而不是õK最后。:)
凯文·克鲁伊森

1
很高兴找到á!这是51另一个。50种感觉。
Grimmy

7

QuadR,137 字节SBCS

带前导空格的标题盒。

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

在线尝试!

ε NLIST(压平)
¯2↑¨ 采取的最后两个字符的每个的字符(填充上留下了一个空间)
@ 在其中的位置
(∊∘⎕A) 的字符是大写的成员 lphabet
 在下面PCRE替换操作的结果...

(.)
\1 后面跟随
* 零或多次的 任何字符,将被以下结果替换...

{…}⍵M “ dfn”;中号上面的图案的ATCH

('OhOneTwoThreeFourFiveSixSevenEightNine'()⎕A) 应用以下匿名默认函数,将长字符串和大写A lphabet作为左参数:

 成员资格(大写字母中长字符串中的字母)

 分区(只要是一个成员,就会开始一个新分区

 左参数(即长字符串)

()⎕R PCRE R用这些词替换以下模式:

⎕D 数字0到9

 将每个都视为单独的模式

⍺← 分配这个替换功能(对于一个 lphabetise)

然后,

⊃⍵ 比赛的第一个字符

, 作为一个字符串

 适用于它

w← 将此分配给w(用于word

' '∊: 如果space是其中的一员(即,如果匹配为空):

 不返回任何内容(成为空字符串)

 其他,

1=≢⍵: 如果一个等于比赛中字符的总和(即其长度):

⍺⍵ 字母数字

 其他,

3=≢⍵: 如果三个等于比赛中字符的总和(即其长度):

'Triple',w 前面加上“三联”的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


再打我一次!像这样
Jitse

@Jitse,不适用于1312;)
TF在

啊,你是对的!
吉特

那么如何处理:['','double ','triple '][n]' eellpbiurotd'[-n:0:-2]168字节:在线尝试!
吉斯

另外,也可以是168个字节
Jitse,

3

Perl -p 5,111个字节

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

在线尝试!

说明:

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

1
节省了几个字节:106
Xcali

3

Scala,213字节

得到它了。不知何故,我尝试构建的递归版本比该版本更为冗长(尽管仍然是递归的,但仅在一种情况下)。函数f将电话号码作为输入字符串,并以尾随空格输出其语音。

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

在线尝试!
编辑:-8b多亏了DrY Wit!

斯卡拉,215字节

随之而来的是领先的空白版本,出于某种原因(即使进行大规模重构),长度也要增加两个字节。

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

在线尝试!


2
替换(o(0)+"").toInt为可以节省8个字节o(0)-48
Y Wit博士

Oof做得好@DrYWit谢谢!
V. Courtois

3

PHP174个 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字节

+`(.)\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

在线尝试!

单字链接,将一串数字字符作为参数,并返回一个Jelly字符串,以空格分隔。当作为完整程序调用时,将隐式输出。


2

T-SQL 2017,238字节

添加了一些换行符以使其可读

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

在线尝试


2

C ++,382字节

它不是超级智能者,但需要编写C ++版本。递归函数R遍历输入字符串并计算重复值。如果重复次数超过3次,它会假装有2次重复,然后倒带并重试。

Major可能会挤出更多的源字符#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

Perl 6的96 93个字节

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

在线尝试!

这是一个匿名代码块,该代码块接受一个数字并返回带有大写数字的字符串,例如 0123 => oh ONE TWO THREE带有一个尾随空格。

在我发现如何在超前使用捕获功能之前,将其删除了一段时间,但现在应该对其进行修复。



1

Scala,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

主要技巧是使用Oracle格式模型将数字转换为单词,而不是使用硬编码的文字“ one” ...“ nine”。


这有打高尔夫球的机会吗?看来您可以删除一堆空格。我也想像您可以将WHERE s重写为WHERE s>''不为null
t-clausen.dk,

1
您可以通过更换后有什么保存一些字符union allselect regexp_replace(s,case when length(regexp_substr(s, '(.)(\1)+')) = 3 then '^...' else '^(.)\1|^.' end) from r
史蒂夫·卡斯

1

JavaScript,142个字节

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

在线尝试!


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

你好 我在(Rbx.Lua)上测试过的Lua的变体不包含输入方法,尽管沙盒具有打印,警告和错误输出方法。
VisualPluginRōblox,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.