Konuşulan kelimelerde telefon numarası


33

Hedef

Sayısal bir telefon numarasını, söylenmesini kolaylaştıran metne çeviren bir program veya işlev yazın. Rakamlar tekrarlandığında, "çift n" veya "üç n" olarak okunmaları gerekir.

Gereksinimler

Giriş

Bir rakam dizesi.

  • Tüm karakterlerin 0 ile 9 arasında rakamlar olduğunu varsayalım.
  • Dize en az bir karakter içerdiğini varsayalım.

Çıktı

Boşluklarla ayrılmış sözcükler, bu rakamların yüksek sesle nasıl okunabileceğini gösterir.

  • Rakamları kelimelere çevir:

    0 "oh"
    1 "bir"
    2 "iki"
    3 "üç"
    4 "dört"
    5 "beş"
    6 "altı"
    7 "yedi"
    8 "sekiz"
    9 "dokuz"

  • Aynı rakam üst üste iki kez tekrarlandığında, "çift sayı " yaz.

  • Aynı rakam üst üste üç kez tekrarlandığında, "üçlü sayı " yaz.
  • Aynı hane dört veya daha fazla kez tekrarlandığında , ilk iki hane için "çift sayı " yazın ve dizenin geri kalanını değerlendirin.
  • Her kelime arasında tam olarak bir boşluk karakteri vardır. Tek bir lider veya sondaki boşluk kabul edilebilir.
  • Çıktı büyük / küçük harfe duyarlı değildir.

puanlama

En az bayt olan kaynak kodu.

Test Kılıfları

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
Konuşma golfu ile ilgilenen herkes "altı altı" nın "altı altı" dan daha uzun sürdüğünü not etmelidir. Buradaki tüm sayısal olasılıklardan sadece "üçlü yedi", heceleri kurtarıyor.
Mor P

13
@Purple P: Ve bildiğiniz gibi, 'double-u double-u-u'> 'world wide web' ..
Chas Brown

11
Bu mektubu "dub" olarak değiştirmeye oy verdim.
El-E-Yemek

8
Bunun sadece entelektüel bir egzersiz olduğunu biliyorum, ama önümde 0800 048 1000 numaralı bir gaz faturası var ve bunu "ah sekiz yüz oh dört sekiz bin" olarak okurdum. Rakamların gruplanması insan okuyucular için önemlidir ve "0800" gibi bazı modeller özel olarak ele alınır.
Michael Kay,

3
@PurpleP Konuşmanın netliği ile ilgilenen herkes , özellikle de telefonda konuşurken, "double 6" kullanmak isteyebilir, çünkü konuşmacının iki altı kişi anlamına geldiği ve yanlışlıkla 6 sayısını tekrarlamadığı açıktır. İnsanlar robot değil: P
Özür dileriz Monica'da

Yanıtlar:


10

05AB1E , 53 52 51 50 49 bayt

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

Çevrimiçi deneyin!

Açıklama:

γ                      # 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, Mayrıca yığıntaki maksimum tamsayıyı belirlerken listelerin içine mi bakıyorsun? Bunu bilmiyordum. Hatırlanması gereken bir şey gibi geliyor. :)
Kevin Cruijssen

16

8088 Meclisi, IBM PC DOS, 164 159 156 155 bayt

İkili:

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 -rYukarıdakileri kullanarak çalıştırılabilir dosya oluşturun ve test edin veya PHONE.COM'u indirin .

Demonte listeleme:

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:

Giriş dizisi, üçlü bulmayı kolaylaştırmak için sağdan sola okunur. Çıktı, görüntü sırasını tersine çevirmeyi basitleştirmek ve ayrıca basamağın adından önce "çift" ve "üçlü" sözcükleri yeniden düzenlemeyi kolaylaştırmak için x86 yığınının üzerine itilir .

Eğer bir sonraki rakam bir öncekinden farklı ise, isim kelime listesinde aranır ve yığına basılır. Makine kodunda "indekslenmiş değişken uzunluklu dizgiler dizisi" kavramı olmadığı için, sözcük listesi i, dizgenin sınırlayıcıya ( $) karşılık gelen kelimeyi bulması için (kelimenin dizini) kaç kez taranır . Yardımcı bir şekilde, x86 , bunu basitleştiren ( CISC'ye teşekkürler) bir çift kısa yönergeye ( C'ye REPNZ SCASBbenzer ) sahiptir.memchr()

Rakam öncekiyle aynıysa, bir "koşmanın" uzunluğu için sayıcı artırılır ve girişte sola doğru dönmeye devam eder. Çalışma bittiğinde, her bir gruplama için "çift" veya "üçlü" den sonra yerleştirilmesi gerekeceğinden, basamağın adı yığından alınır. Eğer çalışmanın uzunluğu tek ise (ve çalışma uzunluğu ise > 1), "üçlü" dizgesini izleyen basamağın adı yığına itilir ve çalışma uzunluğu 3 ile azaltılır. çalışma uzunluğu 0 olana kadar "çift" için tekrarlanır.

Giriş dizesi sona erdiğinde, ekrana ters sırayla yazılan her kaydedilmiş dizeyle yığın boşaltılır.

I / O:

Bağımsız bir PC DOS çalıştırılabilir komut satırı çıktısından konsola girdi.

enter image description here

PHONE.COM'u indirin ve test edin .


repne scasbolduğu memchr(veya strchr, değil biliyorsan bir hit olacaksa oluyor) strstr.
Peter Cordes

Proses girişinde CH = 0 standart tarafından garanti ediliyor mu, yoksa sadece bazı DOS versiyonlarının yaptığı şey mi? Bunun mov cl, byte[si] eşdeğer olduğunu varsaydığını fark ettim movzx cx, byte [si]. Acaba AH, saymak dec ah / jnzyerine, loopCX'i zorlamak / zorlamak zorunda kalmamaktan başka bir şey yapmamak gibi , farklı bir reg kullanıp kullanmadığımı merak ediyorum . Muhtemelen hayır ve 1-byte'a izin verecek 16-bit kaydınız kalmadı dec.
Peter Cordes

1
@PeterCordes için CH=0I go fysnet.net/yourhelp.htm DOS herhangi makul serbest bırakılması için hep aynı, zero'd edilir BX. Sıfırın uzaması hakkında iyi düşünceler mov, teknik movzxolarak 808x'te mevcut olduğunu sanmıyorum (hedef platformu IBM PC 5150 ve diğerleri tutuyor). Baytları kurtarmak için elimden geldiğince bütün kayıtlara göz gezdirdim, ancak muhtemelen kaçırdığım bir şey görürseniz, lütfen bana bildirin!
640KB

1
memchrIMO olarak adlandırmak daha doğru . "Dizge dizisi", insanları örtük uzunluktaki C dizeleri üzerinde çalıştıklarını düşünmeleri konusunda yanıltıcı hale getirir, ancak gerçekten açık uzunluklu dizeler std::stringveya tamponlar üzerinde çalışırlar . Gibi memcpy, memset(movs / stos), memchr/ memrchr(DF = 0 veya 1 ile repne scas) ve memcmp(repe cmps). Tek C eşdeğer repe scasolduğunu strspnben orada olduğunu sanmıyorum çünkü memişlev bunun için. Hatta stoswya stosdda wmemsetörneğin tanımlayabilirsiniz .
Peter Cordes,

1
movzxfazladan bir opcode bayt maliyeti ve evet sadece 386 ile tanıtıldı. Düşük baytlı bir birleştirme yaptığınızı ve sıfırın doğru bir şekilde uzatıldığını varsaydığınızı açıklamak için yazı yazmak daha kolaydı. CX veya en az CH = 0 biliyorsanız, golf oynamak için evet, her zaman movCL ile gidin . Ancak golf dışında, x86'nın bayt yükleme yönergeleri şunlardır movzxve movsx: herhangi bir yanlış bağımlılıktan veya diğer kısmi sicil shenaniganlardan kaçınırlar. Bir dword hedefi bulunan modern CPU'larda, dword mov yükleri kadar hızlıdırlar .
Peter Cordes,

9

05AB1E , 61 56 53 52 51 bayt

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

@Grimy sayesinde -9 bayt .

Çevrimiçi deneyin veya tüm test durumlarını doğrulayın .

Açıklama:

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

Benim bu 05AB1E ucu bakın (bölüm nasıl sözlüğü kullanılır? ) Anlamak için … ‹¶½¿ise " double triple"ve “Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“olup "oh two three four five six seven eight nine".


1
Tabii ki @Grimy Ah, if(length>=4)geri kalanını eklemeden önce ekledim , fakat elbette büyüklük tamsayıları için gerekli değil 1,2,3, çünkü ;Å2¨3ª£ipler bozulmadan kalacaktır (sadece haritadan sonra düzleştirdiğimiz bir listeye sarılmış). Fark ettiğiniz için teşekkürler! Ve cevabınızı görmek için sabırsızlanıyorum Åγ. Gerçekten ilk bölümün bir şekilde daha kısa yapılabileceği hissine kapıldım.
Kevin Cruijssen

1
Dg;LàäRhala āɨšJõK, başlangıçta sahip olduğunuzdan daha kısa ve daha benzer bir bayttır .
Grimmy,

1
@Grimy Ah, bu gerçekten başlangıçta sahip olduğum şeye kapalıydı, hoşuma gitti. :) Tekrar teşekkürler!
Kevin Cruijssen

1
@Grimy Sonunda ádeğil, unutmuş olduğum bir golf daha bulabildim õK. :)
Kevin Cruijssen

1
Güzel bulmak á! İşte bir 51 ve diğeri . 50 mümkün hissediyor.
Grimmy,

7

QuadR , 137 bayt SBCS

Başında boşluk olan başlık.

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

Çevrimiçi deneyin!

ε nlist (düzleştirmek)
¯2↑¨ her karakter son iki karakter almak (boşluk ile soldaki dolgu)
@ pozisyonlarda
(∊∘⎕A) karakterleri büyük harf üyeleridir A lphabet
 PCRE'nin altında değiştirin operasyon sonucunda ...

(.) Sıfır veya daha fazla kez
\1 kendiliğinden takip eden  herhangi bir karakter
*, aşağıdakilerin sonucu ile değiştirilir…

{…}⍵M "DFN"; olduğu M yukarıda desenin atch

('OhOneTwoThreeFourFiveSixSevenEightNine'()⎕A) Uzun dize ve sol argümanlar olarak büyük A lphabet ile aşağıdaki isimsiz taciz işlevini uygulayın:

 üyelik (büyük harfle uzun dize harfleri)

 bölümler (üye olduktan sonra başlayan yeni bir bölümle

 sol argüman (yani uzun dize)

()⎕R PCRE R , aşağıdaki kalıpları bu sözcüklerle değiştirin:

⎕D 0 ile 9 arasındaki rakamlar

 her birini ayrı bir desen olarak ele al

⍺← bu değiştirme işlevini atama (için bir alfabe için)

sonra,

⊃⍵ maçın ilk karakteri

, dize olarak

 uygulamak ona

w← Bunu w( kelime için ata) )

' '∊: Eğer alan bunun bir üyesiyse (yani maç boşsa):

 hiçbir şey döndürmeyin (boş dize olur)

 Başka,

1=≢⍵: eğer biri maçtaki karakterlerin toplamına eşittir (yani uzunluğu):

⍺⍵ bu rakamı alfabetik olarak yaz

 Başka,

3=≢⍵: eğer üçü maçtaki karakterlerin toplamına eşittir (yani uzunluğu):

'Triple',ww  için "Triple" hazırlamak kelimesini

 Başka,

2↓⍵ maçtan rakamlara bırak

 buna güvenmek

w, kelimeyi hazırla

'Double', "Çifte" hazırla


6

JavaScript (ES6),  161 160 152  144 bayt

Çıktı, tek bir öncü alan içerir.

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

Çevrimiçi deneyin!

veya Biçimlendirilmiş kaynak kodunu görün

Nasıl?

Dönüşüm üç adımda işlenir:

  1. her basamağı, önce boşluk bırakarak karşılık gelen İngilizce sözcükle değiştirin
  2. Her desen yerine "X X"ile"double X"
  3. Her desen yerine "double X X"ile"triple X"

Bayt kaydetmek için, tüm adımlar için aynı normal ifadeyi kullanırız:

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

aşağıdaki gibi çalışır:

(\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. adımda, bir arama tablosundan doğru kelimeyi alan bir geri çağırma işlevi kullanıyoruz:

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

2. adımda, bununla değiştiririz "$1 double$2":

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

3. adımda, bununla değiştiririz "triple$2":

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



3

Python 2 , 171 169 168 bayt

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

Çevrimiçi deneyin!

-1 bayt, Jitse sayesinde


Beni tekrar döv! Böylece,
Jitse,

@Jitse, bu işe yaramazsa 1312;)
TFeld

Ah, haklısın!
Jitse

Buna ne dersiniz o zaman: ['','double ','triple '][n]için ' eellpbiurotd'[-n:0:-2]168 bayt için: Online deneyin!
Jitse,

Alternatif olarak, ayrıca 168 bayt
Jitse,

3

Perl 5 -p , 111 bayt

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

Çevrimiçi deneyin!

Açıklama:

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
Birkaç byte kapalı
tıraş

3

Scala , 213 bayt

Anladım. Her nasılsa inşa etmeye çalıştığım özyinelemeli sürüm, bundan çok daha ayrıntılıydı (hala özyinelemeli, ancak sadece bir durumda). İşlev f, telefon numarasını bir giriş dizesi olarak alır ve fonetik olarak izleyen bir boşluk ile çıktı verir.

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

Çevrimiçi deneyin!
Düzenle : -8b DrY Wit sayesinde!

Scala , 215 bayt

Ve işte önde gelen boşluk versiyonu, iki nedenden daha uzun (bir süredir yeniden yapılanma ile bile).

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

Çevrimiçi deneyin!


2
Sen değiştirerek 8 bayt kaydedebilirsiniz (o(0)+"").toIntile o(0)-48.
Dr Y Wit

Oof aferin @DrYWit teşekkürler!
V. Courtois

3

PHP , 174 169 166 159 bayt

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

Çevrimiçi deneyin!

$i0'dan başlayan dizindeki her hane için :

  • Konumundan başlayarak aynı rakamın aralığı $i3'e eşitse, 'triple '2'ye basar ve ekler.$i böylece bir sonraki yinelemenin üzerine atlanan 2 basamağa sahip olur.
  • Konumundan başlayan aynı hanenin yayılma alanı $i2'ye eşit veya 2’den büyükse, 3 değilse'double '$i sonraki yinelemenin üzerine atlanan 1 basamağa ve 1 ekler .
  • Rakam ve boşluk için sözcük yazdırır.
  • $i++.

2

Retina 0.8.2 , 105 bayt

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

Çevrimiçi deneyin! Önde gelen bir boşluk çıkarır. Açıklama: Başlangıçta otomatik olarak 2 veya 3 hane ile eşleşen bir regex denedim ama @ Arnauld'un yaklaşımı golfçü oldu. Açıklama:

+`(.)\1
=$1

Aynı basamak çiftlerini eşleştirin ve ilkini a ile değiştirin =. Sonra tekrarlayın, böylece tek bir sayı için ikinci son hane aynı zamanda a ile değiştirilir =.

.
 $&

Rakamları (ve noktaları =) dışarıda bırakın.

= =
triple

Üç tane aynı rakamı kullanın.

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

Kalan tüm karakterleri kelimelerle değiştir.


2

Jöle , 59 bayt

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

Çevrimiçi deneyin!

Argüman olarak bir rakam karakteri dizisi alan ve boşlukla ayrılmış kelimelerin bir Jelly dizesini döndüren monadik bir link. Tam program olarak adlandırıldığında örtük olarak çıktı verir.


2

T-SQL 2017, 238 bayt

Okunabilir hale getirmek için bazı satır çizgiler eklendi

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 @

Çevrimiçi deneyin


2

C ++, 382 bayt

Süper basit değil, ancak birinin C ++ sürümü yazması gerekiyordu. Özyinelemeli işlev R, giriş dizgisinden geçer ve tekrarlanan değerleri sayar. 3'ten fazla tekrar varsa, 2 tekrar varmış gibi yapar, sonra geri sarar ve tekrar dener.

Birkaç kaynak daha fazla büyük olasılıkla #definemajor ile sıkıştırılmış olabilir , ama eminim daha iyi bir algo daha fazla sıkabilir.

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

ve test durumlarının doğrulanması:

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
Golfe atılan kısmın gerçekten ihtiyacı var #include <sstream>mı? Ya da test işlevi için golf bölümünden sonra bunu aşağıya çekebilir misiniz? İhtiyacınız olan başka yerler olmadığı sürece, yazmaktan std::ostream&sdaha az yer alacağını düşünüyorum . using namespace std;std::
Peter Cordes,


2

Perl 6 , 96 93 bayt

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

Çevrimiçi deneyin!

Bu, bir sayı alan ve büyük harfle sayıları içeren bir dize döndüren adsız bir kod bloğudur, örn. 0123 => oh ONE TWO THREE . Tek bir boşluk ile.

Bu, bir çekimde yakalamaların nasıl kullanılacağını bulana kadar silindi, ancak şimdi düzeltilmesi gerekiyor.


1

Kırmızı , 242 bayt

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

Çevrimiçi deneyin!


1

Scala , 253 bayt

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

Çevrimiçi deneyin!


1

Oracle SQL, 578 bayt (biçimlendirilmiş biçimde)

Çözüm hiçbir şekilde özlü değildir, bu nedenle biçimlendirilmiş şekilde yayınlamak.

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'ta Test Edin

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

Asıl püf nokta, basamakların "" "", "dokuz" sabit kodlu kodlar yerine Oracle formatındaki modelleri kullanarak kelimelere dönüştürülmesidir.


Bunun golf oynama şansı var mı? Görünüşe göre bir sürü alanı kaldırabilirsin. Ayrıca
NEREDEYEN

1
Sen sonra ne değiştirerek birkaç karakter kaydedebilirsiniz union allile select regexp_replace(s,case when length(regexp_substr(s, '(.)(\1)+')) = 3 then '^...' else '^(.)\1|^.' end) from r.
Steve Kass

1

JavaScript, 142 bayt

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

Çevrimiçi deneyin!


1

(Roblox) Lua 5.1 , 166 bayt

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

Emin olun s, yalnızca rakamlarla doldurulmuş önceden tanımlanmış bir dize değeridir; Bu değiştirilecek değişken olacaktır. Sonuç, baştaki boşluk karakterini içerecektir [\u20] .


Siteye Hoşgeldiniz! Lua standart yöntemlerle girdi alabildiğinden , szaten girdi olması gereken kurallara aykırıdır . Bunun yanı sıra, iyi bir ilk yazı var! Tio.run/#lua gibi bir çevrimiçi test sitesine link eklemenizi tavsiye ederim, böylece diğerleri çözümünüzü test edebilir
caird coinheringaahing

Merhaba. Test edilen Lua varyantı (Rbx.Lua) üzerinde test edildi, ancak sanal alan yazdırma, uyarma ve hata çıkış yöntemlerine sahip olmasına rağmen giriş yöntemleri içermiyor.
VisualPlugin Rōblox
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.