Телефон Multi-Tap Правописание


21

Вдохновленный вызовом Google Code :

Латинский алфавит содержит 26 символов, а телефоны имеют только десять цифр на клавиатуре. Мы хотели бы упростить написание сообщения вашему другу, используя последовательность нажатий клавиш для обозначения нужных символов. Буквы отображаются на цифры, как показано ниже. Например, чтобы вставить символ B, программа нажимает 22. Чтобы последовательно вставить два символа с одной и той же клавиши, пользователь должен сделать паузу, прежде чем нажать клавишу еще раз. Пробел '' должен быть напечатан для обозначения паузы. Например, 2 2 обозначает AA, а 22 обозначает B.

Каждое сообщение будет состоять только из строчных букв az и пробелов ''. Нажатие ноль испускает пробел.

введите описание изображения здесь

Ваша задача состоит в том, чтобы написать наименьшую функцию, которая принимает входную строку и возвращает последовательность нажатий клавиш, необходимую для создания ввода в виде строки или вывода его на стандартный вывод. Функция, которая является наименьшим количеством байтов, побеждает.

Пример ввода / вывода

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

Другие уточнения

  • Паузы должны добавляться только при необходимости и должны быть пробелом ''.
  • Каждое сообщение будет состоять только из строчных букв az и пробелов ''. Печать 0для обозначения пробелов.
  • Нет внешних библиотек.
  • Только входная строка может быть передана вашей функции.
  • Чтобы сделать другие языки конкурентоспособными, объявление основной функции не учитывается, равно как и импорт других стандартных библиотек. #includeS, importS и usingS не в счет. Все остальное делает. Это включает в себя #defines и вспомогательные функции. См. Правило 2 в этом вопросе, если вы не уверены.
  • Несколько пробелов могут быть обозначены как 00или 0 0так как вам действительно не нужно делать паузу между пробелами


Можем ли мы предположить, что ввод вводится в нижнем / верхнем регистре?
Фил Х

@PhilH " строчные буквы az и пробелы"
Дэнни

Считаете ли вы скобки {}частью сигнатуры функции? Например, если мой код function f(){alert('hi');}, я должен считать символы alert('hi');или {alert('hi');}?
ProgramFOX

2
Насколько я помню, t9работает по-разному: вы должны нажать каждую клавишу один раз, чтобы получить слово.
VisioN

Ответы:


8

Рубин, 129 122 115 111 108 107 105

Сделано с гольфом ...

Ой, совсем забыл удалить ненужные пробелы - исправлено ...

Сохранено 2 символа благодаря Питеру Тейлору.

Онлайн версия

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

выражение регулярного выражения тогда соответствует первой группе равных цифр

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

массив объединен

*' ')

все пробелы в вхождениях "цифр пробела Different_digit" удаляются

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

1
Не выглядит на 100% правильно. Я вижу, 66666 не нужно нажимать 4 раза подряд.
Дэнни

Должно быть исправлено, спасибо;)
Дэвид Херрманн

1
Какой смысл \2в этом последнем регулярном выражении? Конечно, вторая группа является утверждением нулевой ширины?
Питер Тейлор

Вы абсолютно правы!
Дэвид Херрманн

6

REBEL - 154 110 103

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

Эта «функция» принимает входные данные от стандартного ввода и отправляет результаты в стандартный вывод.

Тестовые прогоны (так что вам не нужно устанавливать переводчик):

hi
44 444

hello world
4433555 555666096667775553

yes
999337777

kthxbai
558449922 2444

Я никогда не могу получить ваши ссылки для загрузки! :(
luser droog

4

JavaScript (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 (спасибо, Дэнни), в котором добавлено много символов.

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

yesдолжно быть 999337777. Я 10338использую твою функцию.
Дэнни

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

С ++ - 170 168 160

Golfed:

#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

Ява - 243

Довольно наивное решение Java. Спасибо комментаторам за предложения.

Исправлена ​​ошибка, которая иногда вставляла ненужные пробелы, например, для ввода «hello worlds 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
Один гольф: заменить t.lengthна10
Джастин

Кроме того, учитывая, что iон используется только для итерации String, удалите его и выполните цикл foreach:for(char c:s.toCharArray())
Джастин

Кроме того , изменения if(c==' '){o+='0';continue;}в if(c==' ')o+='0';else{и добавить соответствующее условие }.
Джастин

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или, не разглаживая, 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;
  • { ... }/( ... )[ ... ] принимает последний результат, индекс для каждого входного символа, чтобы преобразовать каждый символ в соответствующую строку цифр, затем объединяет строки, используя функцию в фигурных скобках;
  • {⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}или {(⍺,(=/↑¨⍺,⍵)↑''),⍵}добавляет каждую новую строку ⍺ к аккумулятору ⍵, вставляя один пробел, только если оба аргумента начинаются с одного и того же символа.

Примеры

      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('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='')
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.