โทรศัพท์การสะกดคำแบบหลายแทป


21

แรงบันดาลใจจากGoogle Code Challenge :

ตัวอักษรละตินมี 26 ตัวอักษรและโทรศัพท์มีเพียงสิบหลักบนปุ่มกด เราต้องการทำให้การเขียนข้อความถึงเพื่อนของคุณง่ายขึ้นโดยใช้ปุ่มกดลำดับเพื่อระบุอักขระที่ต้องการ ตัวอักษรจะถูกแมปไปยังตัวเลขที่แสดงด้านล่าง ในการแทรกตัวอักษร B เช่นโปรแกรมจะกด 22 เพื่อที่จะแทรกอักขระสองตัวตามลำดับจากคีย์เดียวกันผู้ใช้จะต้องหยุดก่อนที่จะกดปุ่มครั้งที่สอง ควรพิมพ์อักขระเว้นวรรค '' เพื่อระบุการหยุดชั่วคราว ตัวอย่างเช่น 2 2 หมายถึง AA ในขณะที่ 22 หมายถึง B

แต่ละข้อความจะประกอบด้วยอักขระตัวพิมพ์เล็กเท่านั้น az และอักขระเว้นวรรค '' การกดศูนย์จะปล่อยช่องว่าง

ป้อนคำอธิบายรูปภาพที่นี่

ความท้าทายของคุณคือการเขียนฟังก์ชั่นที่เล็กที่สุดซึ่งรับสตริงป้อนเข้าและส่งกลับลำดับของการกดปุ่มที่จำเป็นในการสร้างอินพุตเป็นสตริงหรือส่งออกไปยัง stdout ฟังก์ชั่นซึ่งเป็นจำนวนน้อยที่สุดของไบต์ชนะ

ตัวอย่างอินพุต / เอาท์พุต

phone("hi")
44 444
phone("hello world")
4433555 555666096667775553

คำชี้แจงอื่น ๆ

  • ต้องเพิ่มหยุดชั่วคราวเมื่อจำเป็นเท่านั้นและต้องเว้นวรรค ''
  • แต่ละข้อความจะประกอบด้วยอักขระตัวพิมพ์เล็กเท่านั้นaz และอักขระเว้นวรรค '' พิมพ์0เพื่อบ่งบอกถึงช่องว่าง
  • ไม่มีห้องสมุดภายนอก
  • เฉพาะอินพุตสตริงเท่านั้นที่สามารถส่งผ่านไปยังฟังก์ชันของคุณ
  • เพื่อให้ภาษาอื่นแข่งขันได้การประกาศฟังก์ชั่นหลักจะไม่ถูกนับและจะไม่นำเข้าไลบรารีมาตรฐานอื่น ๆ #includes, imports และusings จะไม่นับ ทุกอย่างอื่นทำ ซึ่งรวมถึง#defineฟังก์ชั่น s และผู้ช่วย ดูกฎที่ 2ในคำถามนี้หากคุณสับสน
  • ช่องว่างหลายช่องสามารถแสดงเป็น00หรือ0 0เนื่องจากคุณไม่ต้องหยุดระหว่างช่องว่างจริงๆ

1
เกี่ยวข้องกับสิ่งนี้: codegolf.stackexchange.com/questions/21327/…
Victor Stafusa

เราสามารถสมมติว่าอินพุตเป็นตัวพิมพ์เล็ก / ใหญ่ได้หรือไม่?
Phil H

@PhilH " อักขระตัวพิมพ์เล็ก az และอักขระเว้นวรรค ''"
Danny

คุณพิจารณาวงเล็บ{}เป็นส่วนหนึ่งของลายเซ็นฟังก์ชั่นหรือไม่? ตัวอย่างเช่นหากรหัสของฉันคือfunction f(){alert('hi');}ฉันควรนับตัวอักษรของalert('hi');หรือ{alert('hi');}?
ProgramFOX

2
เท่าที่ฉันจำได้t9ทำงานแตกต่างกัน: คุณต้องคลิกแต่ละคีย์หนึ่งครั้งเพื่อรับคำ
VisioN

คำตอบ:


8

ทับทิม, 129 122 115 111 108 107 105

เสร็จแล้วกับการเล่นกอล์ฟ ...

โอ๊ะลืมลบช่องว่างที่ไม่จำเป็นออกทั้งหมด - แก้ไขแล้ว ...

บันทึก 2 ตัวขอบคุณ Peter Taylor

เวอร์ชั่นออนไลน์

def t9(t)
(t.tr(" ",?`).bytes.map{|c|"09998887777666555444333222"[96-c..-1][/(.)\1*/]}*' ').gsub /(\d) (?!\1)/,'\1'
end

คำอธิบาย:

พื้นที่ถูกแปลเป็นถ่านด้วยลำดับ 96

(t.tr(" ",?`).bytes

อักขระถูกแมปแรกกับชุดของตัวเลข: - a ถึง 2 - b ถึง 22 - d ถึง 3222 - h ถึง 444333222

นิพจน์ regex จะตรงกับกลุ่มแรกของตัวเลขที่เท่ากัน

map{|c|"09998887777666555444333222"[96-c..-1][/(.)\1*/]}

อาร์เรย์เข้าร่วม

*' ')

ช่องว่างทั้งหมดในการเกิดขึ้นของ "หลักพื้นที่แตกต่างกัน_digit" จะถูกลบออก

gsub /(\d) (?!\1)/,'\1'

1
ดูเหมือนจะทำงานไม่ถูกต้อง 100% ฉันเห็นว่า66666 ไม่จำเป็นต้องกด 4 ครั้งติดต่อกัน
Danny

ควรได้รับการแก้ไขขอบคุณ;)
David Herrmann

1
อะไรคือจุดเริ่มต้นของ\2regex สุดท้าย? แน่นอนกลุ่มที่สองคือการยืนยันความกว้างเป็นศูนย์?
Peter Taylor

คุณพูดถูก!
David Herrmann

6

REBEL - 154 110 103

;0 2abc3def4ghi5jkl6mno7pqrs8tuv9wxyz/^;/$<;/([^\d-])(?=\D.*(\d)(\w)*\1)/$2$3-/(\d)-+\1/$1 $1/-//;/$>$`

ฟังก์ชั่นนี้รับอินพุตจาก stdin และส่งผลลัพธ์ไปยัง stdout

ทดสอบการทำงาน (ดังนั้นคุณไม่ต้องติดตั้งล่าม):

hi
44 444

hello world
4433555 555666096667775553

yes
999337777

kthxbai
558449922 2444

ฉันไม่สามารถโหลดลิงค์ของคุณได้เลย! :(
luser droog

4

จาวาสคริปต์ (124)

ทำงานใน Firefox

t9=s=>s.replace(/./g,c=>'099998887777666555444333222'.slice(36-parseInt(c,36)).match(/(.)\1*/)[0]+' ').replace(/(.) (?!\1)/g,'$1')

4

GolfScript, 46 ตัวอักษร

{).," adgjmptw"&.,.1>*`@@)\;-*}/]{.2$^!" "*\}*

ตามปกติอ่านอินพุตจาก stdin พิมพ์ไปที่ stdout ดูการสาธิตออนไลน์ (พร้อมการป้อนข้อมูลกระป๋อง)

โปรดทราบว่ารหัสนี้ขึ้นอยู่กับการตีความที่เข้มงวดมากของข้อมูลจำเพาะอินพุต (เฉพาะตัวอักษรตัวพิมพ์เล็กและช่องว่าง): โดยเฉพาะบรรทัดใหม่ใด ๆ ในอินพุตจะทำให้เกิดปัญหา! ปัญหานี้สามารถแก้ไขได้ด้วยค่าใช้จ่ายพิเศษสองตัวอักษรโดยn-การเตรียมโค้ดเพื่อกรองบรรทัดใหม่ใด ๆ


3

C ++ - 365 ตัวอักษรที่ไม่มี int main(){}

#include<iostream>
#include<string>
#include<cmath>
#define o std::cout<<
int main(){std::string s;getline(std::cin,s);for(int i=0;i<s.size();i++){if(s[i]==32)o 0;int j=s[i]-97;if(i>0&&j/3==(s[i-1]-97)/3)o ' ';if(-1<j&j<15){for(int k=j-j%3-1;k<j;k++)o 2+j/3;}if(14<j&j<19){for(int k=14;k<j;k++)o 7;}if(18<j&j<22){for(int k=18;k<j;k++)o 8;}if(21<j&j<26){for(int k=21;k<j;k++)o 9;}}}

ใช้เหตุผลเดียวกับคำตอบของฉันที่นี่เพียงใช้forลูปเพื่อเอาท์พุทแต่ละตัวอักษรตามจำนวนครั้งที่เหมาะสม


คุณสามารถใช้แทนs[i]==32 s[i]==' 'ค่า ASCII ของช่องว่างคือ 32
user12205

@ace สิ่งที่แน่นอน
Hosch250

3

Perl - 107 110

$_=<>;y/ /0/;$z='a';$==2;for$l((3)x5,4,3,4){for$q(1..$l){s/$z/$=x$q.$"/ge,$z++}$=++}s/(.) (?!\1)/\1/g;print

นี่คือโซลูชันก่อนหน้าของฉันใน 120 128 130 155 :

$_=<>;s//_/g;y/sz/79/;for$x(cfilorvy,behknqux,adgjmptw){s/(\d)_/\1\1_/g,eval"y/$x/2-9/"}y/ _/0 /;s/(.) (?!\1)/\1/g;print

แบบทดสอบ:

hi
 44 444

hello world
 4433555 555666096667775553

jackdaws loves my big sphinx
 52 222553297777055566688833777706999022444 407777 744 4446699

3

VBA 220 253/258/219

ไม่นับFunctionบรรทัดที่นี่:

ด้วยString, 253 :

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>""Then If c=" "Then t=t & 0 Else b=Asc(c)-91:n=String(IIf(b>27,(b-4)Mod 4+1,IIf(b>23,(b-1)Mod 4+1,b Mod 3+1)),Trim(Str(Int(b/3)-IIf(b=24Or b=27Or b>29,1,0)))):t=t &IIf(Right(t,1)=Left(n,1)," " &n,n)
Next
End Function

ด้วยForห่วง258 :

เพิ่มการแก้ไขสำหรับคีย์ 7/9 (ขอบคุณ Danny) ซึ่งเพิ่มตัวอักษรจำนวนมาก

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>""Then
n=""
b=Asc(c)-91
For i=1To IIf(b>27,(b-4)Mod 4+1,IIf(b>23,(b-1)Mod 4+1,b Mod 3+1))
n=n &Int(b/3)-IIf(b=24Or b=27Or b>29,1,0)
Next
t=t &IIf(c=" ",0,IIf(Right(t,1)=Left(n,1)," " &n,n))
End If
Next
End Function

ใช้Choose 219 :

ฉันไม่ต้องการที่จะทำงานกับอันนี้เนื่องจากมันเป็นพื้นฐานในการทำงาน แต่มันเป็นรหัสที่สั้นกว่า ...

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>"" Then:b=Asc(c)-96:n=Choose(b,2,22,222,3,33,333,4,44,444,5,55,555,6,66,666,7,77,777,7777,8,88,888,9,99,999,9999):t=t &IIf(c=" ",0,IIf(Right(t,1)=Left(n,1)," " &n,n))
Next
End Function

yes999337777ควรจะเป็น ฉัน10338ใช้ฟังก์ชั่นของคุณ
Danny

3

C, 165 163 153 149 138 ตัวอักษร

k(char*s){char*m="`cfilosvz",l=0,i,c;while(*s^0){for(i=0;*s>m[i];i++);c=*s-m[i-1];i==0?i=-1,c=1:i==l?putchar(32):1;while(c--)putchar(i+49);l=i;s++;}}

ความพยายามครั้งแรกของฉันในการตีกอล์ฟข้อเสนอแนะใด ๆ ได้รับการชื่นชม


2

C ++ - 170 168 160

แข็งแรงเล่นกอล์ฟ:

#define t std::cout<< 
void g(char*s){char v,p,b,l=1;while(*s){v=*s++-97;p=(v==18)+(v==25)+(v-=v/18+v/25)%3;b=v<0?48:v/3+50;if(l==b)t' ';while(p--+1){t(l=b);}}}

Ungolfed

void numpresses(char* s)
{
char lastbutton = 1;
const char asciiOffset = 97;

while(*s)
{
    char val = *s++ - asciiOffset;

    char presses = 
        (val == 18) + (val == 25)           //Z and S are special cases. Check for their ascii codes.
        + (val -= val / 18 + val / 25) % 3; //Simple mod 3 for number of presses. Also apply offset for characters above s and z.

    char button =
        val < 0                             //If the character is a space...
        ? '0'                               //The button character needs to be 0
        : val / 3 + '2';                    //Buttons are offset by the ascii code for the number 2


    if (lastbutton == button)               //Add a space if we need to pause
    {
        std::cout << ' ';
    }

    while (presses-- + 1)                   //Print the button once for each press required
    {
        std::cout << button;
        lastbutton = button;            
    }
}
}

2

C: 136 ตัวอักษร

p(char*s){int i,c,l=1;while(c=*s%32,*s++)for(i=l!=(l=(c+149-c/18-c/25)/3-!c);i++<(c-!!c-c/18-c/25)%3+(c==19)+c/26+2;putchar(i^1?l:32));}

และไม่ได้รับการอวดเล็กน้อย (ใช่นั่นคือวิธีที่เขียนไว้):

p(char*s){
        int i,c,l=1;
        while(c=*s%32,*s++)for(
                i=l!=(l=(c+149-c/18-c/25)/3-!c);
                i++<(c-!!c-c/18-c/25)%3+(c==19)+c/26+2;
                putchar(i^1?l:32)
        );
}

ฉันอาจจะตัดมันลงเล็กน้อยโดยใช้การเรียกซ้ำ, มนต์ดำและพริกป่น


2

Java - 243

โซลูชัน java ที่ไร้เดียงสา ขอบคุณที่แสดงความคิดเห็นสำหรับข้อเสนอแนะ

แก้ไขข้อผิดพลาดที่บางครั้งแทรกช่องว่างที่ไม่จำเป็นเช่นสำหรับอินพุต "hello world sup"

    private static void t9(String s) {
        String[]t=",,abc,def,ghi,jkl,mno,pqrs,tuv,wxyz".split(",");String o="";int i,j,k,l=0;for(char c:s.toCharArray()){if(c==32){o+='0';l=0;}else for(j=0;j<10;j++){int n=t[j].indexOf(c);if(n>=0){if(j==l)o+=' ';for(k=0;k<n+1;k++)o+=j;l=j;}}}return o;
    }

4
ค่อนข้างดี แต่คุณต้องตีกอล์ฟและให้คะแนน
Hosch250

1
javaผมถือว่านี่เป็น คุณช่วยพูดเรื่องนี้ในหัวเหมือนคำตอบอื่น ๆ
บาดเจ็บทางดิจิทัล

1
One golf: แทนที่t.lengthด้วย10
Justin

นอกจากนี้การพิจารณาว่าiใช้สำหรับการวนซ้ำเท่านั้นให้Stringลบออกและทำลูป foreach:for(char c:s.toCharArray())
Justin

นอกจากนี้การเปลี่ยนแปลงif(c==' '){o+='0';continue;}ไปและเพิ่มที่เหมาะสมif(c==' ')o+='0';else{ }
Justin

1

CoffeeScript - 202 (210 - 8)

t9=(s)->
    t=[3,3,3,3,3,4,3,4];l=-1;r=""
    for c in s
        n="";d=c.charCodeAt(0)-96
        if c is ' '
            n=0
        else((n+=k+2 for x in[0...d];break)if d<=v;d-=v)for v,k in t
        r+=if n[0]is l[0] then " "+n else n
        l=n
    r

1

APL, 77 ตัวอักษร

{{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]}

คำอธิบาย

  • 2+⌊y←7.99,⍨.315×⍳25หรือ, ungolfed, y←(0.315×⍳25),7.99 ◇ 2+⌊yตัวอย่างเส้นเอียงที่เหมาะสม (y = 0.315 x) บนจุดตั้งแต่ 1 ถึง 25; เส้นเอียงในลักษณะที่พื้นของค่า y เหล่านี้เป็นไปตามรูปแบบการทำซ้ำ 000111 ... 777 ยกเว้นกลุ่มที่หกของตัวเลข 5555; จำนวนจะถูกต่อท้ายที่จะได้รับ 7 ที่สี่เพื่อให้อาร์เรย์สุดท้ายบวก 2 เป็น 22233344455566677778889999;
  • ⌈3.1×y-⌊y ขยายความแตกต่างระหว่างค่า y และพื้นเพื่อให้เพดานของความแตกต่างให้รูปแบบ 123123 ... กับ 4 บนหลักสุดท้ายของสองกลุ่ม 4 หลัก;
  • '0',⍨( ... )/¨⍕¨ ...หรือ(( ... ) /¨ ⍕¨ ...),'0' ใช้ผลลัพธ์หลังเพื่อทำซ้ำตัวเลขจากอดีตเพื่อให้ผลลัพธ์เป็นอาร์เรย์ของสตริง "2" "22" "222" "3" "33" "333" ... ด้วย "7777" และ "ที่ถูกต้อง" 9999 "ในสถานที่และ" 0 "ต่อท้าย;
  • ⍵⍳⍨⎕UCS 96+⍳26หรือ(⎕UCS 96+⍳26)⍳⍵คำนวณดัชนีของถ่านอินพุตแต่ละอันโดยที่ "a" คือ 1, "z" คือ 26 และพื้นที่ (และถ่านอื่น ๆ ) เท่ากับ 27;
  • { ... }/( ... )[ ... ] รับผลลัพธ์หลังดัชนีสำหรับแต่ละอักขระอินพุตเพื่อแปลอักขระแต่ละตัวเป็นสตริงตัวเลขตามลำดับจากนั้นเชื่อมสตริงโดยใช้ฟังก์ชันในวงเล็บปีกกา
  • {⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}หรือ{(⍺,(=/↑¨⍺,⍵)↑''),⍵}ผนวกแต่ละสตริงใหม่⍺ต่อแอคคิวมูเลเตอร์ inter เพื่อแทรกช่องว่างเดียวหากอาร์กิวเมนต์ทั้งสองเริ่มต้นด้วยอักขระเดียวกัน

ตัวอย่าง

      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]} 'hello world'
 4433555 555666096667775553 
      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]} 'the quick brown fox jumped over the lazy dog'
 84433077884442225502277766696603336669905886733 3066688833777084433055529999 999036664 

1

Python 155 150

ฉันหวังว่าฉันจะดีกว่าใน XD นี้ ไม่นับความหมายฟังก์ชัน ระดับการเยื้องครั้งแรกคือช่องว่างที่สองคือแท็บและแท็บที่สอง 2

def p(s,l=None):
 for c in s:
    for i,g in enumerate(" ,,abc,def,ghi,jkl,mno,pqrs,tuv,wxyz".split(",")):
        if c in g:print"\b"+[""," "][l==i]+str(i)*(g.index(c)+1),;l=i

0

JavaScript 234

for(l=-1,r="",I=0,y=(s=prompt()).length;I<y;I++){c=s[I];n="";d=c.charCodeAt(0)-96;if(0>d)n=0;else for(k=J=0;J<8;k=++J){v="33333434"[k];if(d<=v){for(x=K=0;0<=d?K<d:K>d;x=0<=d?++K:--K)n+=k+2;break}d-=v}r+=n[0]==l[0]?" "+n:n;l=n}alert(r)


0

R 224

ฉันแน่ใจว่ามีวิธีที่ดีกว่าในการทำเช่นนี้ดังนั้นฉันจะทำงานต่อไป

a=strtoi(charToRaw(scan(,'',sep='\n')),16L)-95;a[a<0]=1;b=c(0,2,22,222,3,33,333,4,44,444,5,55,555,6,66,666,7,77,777,7777,8,88,888,9,99,999,9999)[a];c=append(b[-1],0)%%10;d=b%%10;b[c==d]=paste(b[c==d],'');paste(b,collapse='')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.