Письма в телефонные номера


23

Проблема:

Например, вы создаете новый телефон, в котором люди могут вводить специальные телефонные номера, 1-800-programи они будут автоматически преобразованы в используемый телефонный номер, например 1-800-7764726(в предыдущем примере).

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

Вот клавиатура, для справки:

клавиатура

Правила:

  • Ваша программа получит строку
  • Это обработает это и возвратит / напечатает другую строку
  • Любой язык принят
  • Поскольку это , выигрывает самый короткий код

Должна ли программа обрабатывать как строчные, так и прописные буквы на входе?
mattnewport

3
@mattnewport - нет, предположим, что переменная уже преобразована в нижний регистр
TheDoctor

Ответы:


8

GolfScript, 24 символа

{.96>{,91,'qx'+-,3/`}*}%

Тестовый ввод:

0123456789-abcdefghijklmnopqrstuvwxyz

Тестовый вывод:

0123456789-22233344455566677778889999

Объяснение:

  • { }% применяет код в фигурных скобках к каждому символу ввода.

  • .96>{ }* выполняет код между внутренними фигурными скобками, если и только если ASCII-код символа больше 96 (т. е. это строчная буква).

  • Первый ,превращает символ в список всех символов с более низкими кодами ASCII и 91,'qx'+-отфильтровывает все символы с кодами ASCII менее 91, а также буквы qи xиз списка. Так, например, персонаж aпревращается в список из 6 символов [\]^_`, а персонаж - в список zиз 29 символов [\]^_`abcdefghijklmnoprstuvwy.

  • Вторая ,подсчитывает количество элементов, оставшихся в списке, и 3/делит это число на три (округление вниз). Наконец, `превращает полученное число (в диапазоне 2 - 9) в строку.

Таким образом, согласно спецификации, дефисы и цифры остаются без изменений, а строчные буквы отображаются в числа в соответствии со схемой клавиатуры. Код будет фактически проходить через все печатаемые символы ASCII, за исключением строчных букв (которые отображаются так, как описано) и символов {, |и }(которые отображаются в двухсимвольную строку 10). Не-ASCII 8-битный ввод будет производить всевозможные странные числовые результаты.

После всего этого немного разочаровывает, что это тривиальное решение bash превосходит всего шесть символов.


50

Баш, 30

Изменить: Спасибо Doorknob за устранение 3 символов

tr a-z 22233344455566677778889

Пример:


10
Вы не можете удалить последние 3 9с?
Ручка двери

16

С 83 78 77 65 63 62

main(c){for(;~(c=getchar());putchar(c>96?20-c/122+5*c/16:c));}

http://ideone.com/qMsIFQ


3
Хорошая математика. Просто хочу сказать, что вы можете уменьшить 1 символ, предполагая, что EOF равно -1, и сделайте~(c=getchar())
user12205

Не могли бы вы использовать getch()вместо getchar()?
starsplusplus

Строго говоря, getch()это не стандартный C, в результате я думаю, что он не связывается в ideone. Тем не менее, в любом случае я протестировал его в MSVC, и он, к сожалению, не работает - поскольку он напрямую потребляет ввод с клавиатуры, нет выхода из программы, хотя он переводит то, что вы печатаете на лету, что довольно аккуратно.
mattnewport

4

Javascript - 103 символа

alert(prompt().replace(/[a-z]/g,function(y){y=y.charCodeAt(0)-91;return y>27?9:y>24?8:y>20?7:~~(y/3)}))

1
Я не знал, что ты можешь сделать это с .replace. Голосуй за тебя!
SuperJedi224

Вы можете заменить charCodeAt(0)на, charCodeAt()и вы можете использовать функцию стрелки для function(y)...сохранения нескольких байтов, и ~~(y/3)вы можете использоватьy/3|0
chau giang

3

Рубин, 75 символов

gets.chars{|c|$><<"22233344455566677778889999#{c}"[[*?a..?z].index(c)||-1]}

Использует устаревший charsс блоком, и печатает каждую букву индивидуально с $><<. Мне тоже нравится [[*?a..?z].index(c)||-1]; он захватывает символ, соответствующий этой букве алфавита, если это буква, и последний символ (который оказывается тестовым символом без изменений), если нет.

Рубин, 43 (или 35) символов

Откровенно воровал у @ace;)

puts gets.tr'a-z','22233344455566677778889'

Побрей 8 символов, если я смогу работать в IRB с переменной sв качестве строки:

s.tr'a-z','22233344455566677778889'

3

C ++ - 222 символа

Самое длинное решение на данный момент:

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

1
Lol, я не думаю, что самое длинное решение - цель здесь ...
Дэнни

@Danny C ++ плохо подходит для игры в гольф . Я и C # - единственные языки, которые хуже, которые я знаю (все классы, создание объектов и длинные имена для вывода ...).
Hosch250

Я знаю, я просто подумал, что это было забавно, что вы упомянули «Самое длинное решение».
Дэнни

3

Фринк, 92

Я знаю довольно многословный язык. Это проверяет 8 значений вместо 26 без необходимости вводить сравнения. Может ли какое-либо из приведенных выше решений "222333444 .." быть сокращено аналогичным образом?

Используя встроенные конструкции, 107

co=new OrderedList
co.insertAll[charList["cfilosv{"]]
println[input[""]=~%s/([a-z])/co.binarySearch[$1]+2/eg]

Используя пользовательскую рекурсивную функцию, 92

fn[x,a]:=x<=(charList["cfilosv{"])@a?a+2:fn[x,a+1]
println[input[""]=~%s/([a-z])/fn[$1,0]/eg]

+1 за сокращение метода перевода строки до 8-символьного поиска. Приятное прикосновение.
Джонатан Ван Матр

2

Smalltalk, 79 70

ввод s:

s collect:[:c|' 22233344455566677778889999'at:1put:c;at:(($ato:$z)indexOf:c)+1]

вероятно, не является кандидатом на то, чтобы быть самым коротким - но может представлять интерес для старого трюка, чтобы избежать проверки для условия not-found (indexOf: возвращает 0 в этом случае). Таким образом, специальный тест для писем не требуется. Однако некоторые Smalltalks имеют неизменяемые строки, и нам нужно еще 4 символа («copy»).

О, лучшая версия, которая даже имеет дело с неизменяемыми строками в 70 символов:

s collect:[:c|c,'22233344455566677778889999'at:(($ato:$z)indexOf:c)+1]

2

Mathematica 90

Это следует логике решения @ ace:

StringReplace[#,Thread[CharacterRange["A","Z"]->Characters@"22233344455566677778889999"]]&

пример

StringReplace[#1,Thread[CharacterRange["A","Z"]-> 
Characters@"22233344455566677778889999"]]&["VI37889"]

8437889


Ваше изображение стрелы не принимается Mma при копировании / вставке
Dr. belisarius

Кроме того, вам не нужно 1в #1:)
Доктор Belisarius

Велисарий, я изменил стрелу назад и удалил 1. Тем не менее 90 символов, но вырезать и вставить будет работать. Вы, конечно, понимаете мотивацию использовать одну стрелку символа.
DavidC

Был там, сделал это :)
Доктор Белизарий

2

Perl, 50

Еще одна очевидная копия ответа Эйса

($_)=@ARGV;y/a-z/22233344455566677778889999/;print

1
Этот код работает правильно, но есть возможности для улучшения. Давайте избавимся от $ ARGV [0] и -pвместо этого воспользуемся параметром switch, который позволяет вам хорошо проходить каждую строку stdin. Пока мы на этом, диапазон в y /// не должен быть заключен в квадратные скобки. Мы также можем избавиться от трех 9, оставив только одну, и удалить последнюю точку с запятой: вот -p y/a-z/22233344455566677778889/ и все, 30 + 1 за -p. Благодарим Вас за использование сервисов по поиску и оптимизации корпоративного китайского языка Perl и хорошего дня.
китайский Perl Goth

2

R, очень долго, но весело

foo <- '1-800-splurghazquieaobuer57'
oof <- unlist(strsplit(foo,''))
#don't count that part - it's input formatting :-) 
digout <- unlist(strsplit('22233344455566677778889999','')) 
oof[oof%in%letters[1:26]] <- unlist(sapply(oof[oof%in%letters[1:26]], function(j) digout[which(letters[1:26]==j)] ))

2

к [32 символа]

{(.Q.a!|,/(4 3 4,5#3)#'|$2+!8)x}

использование

{(.Q.a!|,/(4 3 4,5#3)#'|$2+!8)x}"stack exchange"
"78225 39242643"

2

JavaScript, 85

JavaScript никогда не победит в гольф-войнах, но мне это нравится, и я хотел сделать что-то другое, чем прыгнуть на фургон @ace.

alert(prompt().replace(/[a-z]/g,function(a){for(i=7;a<"dgjmptw{"[i--];);return i+4}))

2

PHP, 141

Не самое короткое, но веселее

<?php foreach(str_split($argv[1])as$c){$v=ord($c);if($v>114){$v--;}if($v==121){$v--;}if($v<123&$v>96){echo chr(ceil($v/3+17));}else{echo$c;}}

Более читабельно:

<?php 
foreach (str_split($argv[1]) as $c) {
  $v=ord($c);
  if ($v>114) {$v--;}
  if ($v==121){$v--;}
  if ($v<123 & $v>96){
    echo chr(ceil($v/3+17));
    } else {echo $c;}
}

ОП сказал, что ввод уже в нижнем регистре, поэтому вы можете удалитьstrtolower
Einacio

2

Python 2.7, 80

for c in raw_input():print'\b'+(`(ord(c)-97)/3+2-(c in('svyz'))`if c>'`'else c),

Я новичок в Python, так что я уверен, что должен быть способ играть в гольф еще дальше , это другой подход, надеюсь, вам, ребята, нравится, мой бог, Python довольно!

Пример запуска:

  • вход: 01-800-abcdefghijklmnopqrstuvwxyz
  • выход: 01-800-22233344455566677778889999

2

T-SQL, 216 байт

За последние пару ночей я потратил довольно много времени на тщательное создание математической функции последовательности, которая бы правильно округлялась, чтобы генерировать правильные коды ASCII для чисел из алфавитных кодов ASCII. У него было смешное количество десятичных разрядов в коэффициентах, но это работало.

Тем не менее, рациональный подход mattnewport работает и в SQL, при гораздо меньших затратах в байтах, поэтому я бесстыдно отказываюсь от собственной математики в пользу его. Пойди проголосуй за него, это элегантное решение!

Вот мой:

DECLARE @p VARCHAR(MAX)='';WITH t AS(SELECT ASCII(LEFT(@s,1))c,2 i UNION ALL SELECT ASCII(SUBSTRING(@s,i,1)),i+1FROM t WHERE i<=LEN(@s))SELECT @p=@p+CHAR(CASE WHEN c>96THEN 20-c/122+5*c/16 ELSE c END)FROM t;SELECT @p

При этом используется рекурсивный CTE для создания импровизированной стопки символов в телефонном номере и преобразования букв на лету, а затем немного хитрости SQL (SELECT @ p = @ p ​​+ columnValue) для перекомпоновки строки из CTE без необходимости другая рекурсивная конструкция.

Выход:

DECLARE @s VARCHAR(MAX)='1-800-abcdefghijklmnopqrstuvwxyz'
--above code runs here
1-800-22233344455566677778889999

2

Python 2.7, 66 65


Оригинал Анакаты

for c in raw_input():print'\b'+(`(ord(c)-97)/3+2-(c in('svyz'))`if c>'`'else c),


Дальше в гольф

for c in input():print(ord(c)-91)/3-(c in('svyz'))if c>'`'else c,


У меня недостаточно репутации, чтобы комментировать ответ @ anakata, поэтому я сделал здесь отдельный пост. У меня была та же идея (принимая модуль 3 постановления), но я не мог понять, как напечатать правильные числа для s - z .

В любом случае, улучшения в гольф я сделал:

  • изменился raw_inputнаinput

  • удалены посторонние '\b'и скобки и одинарные кавычки

  • убрал +2смещение и поместил его в исходное вычитание (97 - (3 * 2) = 91)

Протестировано с интерпретатором Python 2.7.6. Предполагается, согласно правилам, ввод строки.


Вы также можете удалить пространство между) и если
Виллем

Вы правы. хороший улов Виллем
Жешишей


1

q [38 символов]

{(.Q.a!"22233344455566677778889999")x}

Вдохновленный решением @ ace

пример

{(.Q.a!"22233344455566677778889999")x}"stack exchange"
"78225 39242643"

1

XQuery, 71

BaseX использовался в качестве процессора XQuery. $iэто вход.

translate($i,"abcdefghijklmnopqrstuvwxyz","22233344455566677778889999")

Не самый короткий ответ, но довольно короткий и очень читаемый.


1

Питон, очень безликий

Поскольку все копируют туз, я решил опубликовать код, который я придумал, прежде чем задавать вопрос:

def phonekeypad(text):
    c = ['','','abc','def','ghi','jkl','mno','pqrs','tuv','wxyz']
    st = ""
    for i in list(text):
        a = False
        for t in range(len(c)):
            if i in c[t]:
                st += str(t)
                a=True
        if a == False:
            st += str(i)
    return st

1

EcmaScript 6 (103 байта):

i.replace(/[a-z]/g,x=>keys(a='00abc0def0ghi0jkl0mno0pqrs0tuv0wxyz'.split(0)).find(X=>a[X].contains(x)))

Ожидается, iчтобы содержать строку.

Попробуйте это в любой последней версии Firefox. Я не пробовал Google Chrome.


1

Питон 3, 121

print("".join((lambda x:"22233344455566677778889999"[ord(x)-97] if ord(x)>96 and ord(x)<123 else x)(i) for i in input()))

1

Haskell, 93C

t[]_ a=a
t(b:c)(d:e)a
 |a==b=d
 |True=t c e a
y=map(t['a'..'z']"22233344455566677778889999")

использование

y "1-800-program"

1

C # 140

using System.Linq;class P{static void Main(string[]a){System.Console.Write(string.Concat(a[0].Select(d=>(char)(d>96?20-d/122+5*d/16:d))));}}

0

питон

import string          
trans = str.maketrans(string.ascii_lowercase,
                      '22233344455566677778889999')                                                                                         
print("1-800-ask-usps".translate(trans))

0

ECMASCRIPT, 101 (с входом)

"1-800-PROGRAM".replace(/./g,function(c){
return "22233344455566677778889999"[c.charCodeAt(0)-65]||c})

Новая строка добавлена ​​для ясности. 85 символов, если вход находится в переменной.


0

Perl, 54

print map{/[a-y]/?int(5/16*ord)-28:/z/?9:$_}<>=~/./gs

Стреляй, @RobHoare все еще бьет меня на 4 символа. :)


0

QBasic, 155

Ах, воспоминания ...

INPUT n$
FOR i=1 TO LEN(n$)
c$=MID$(n$,i,1)
a=ASC(c$)
IF 97>a THEN
PRINT c$;
ELSE IF 122>a THEN
PRINT STR$(a\3.2-28);
ELSE
PRINT 9;
END IF
NEXT i

Это должно было быть короче, но я тестировал с repl.it , который не допускает однострочных IFоператоров и ведет себя странно, если вы оставляете переменную выключенной NEXT i. Он также не распознает ASCфункцию, поэтому для запуска кода необходимо добавить этот обходной путь в начале:

DECLARE FUNCTION ASC(s$)
FUNCTION ASC(s$)
FOR j=1 TO 255
IF CHR$(j)=LEFT$(s$,1) THEN
ASC=j
END IF
NEXT j
END FUNCTION

(Во второй раз, когда вы запустите его, переводчик будет жаловаться, если вы не удалите DECLARE FUNCTIONстроку, иди к рисунку.)


0

R 110

s=strsplit(scan(,""),"")[[1]];i=grep("[a-z]",s);s[i]=sort(c(1:24%%8+2,7,9))[match(s[i],letters)];cat(s,sep="")

Пример:

> s=strsplit(scan(,""),"")[[1]];i=grep("[a-z]",s);s[i]=sort(c(1:24%%8+2,7,9))[match(s[i],letters)];cat(s,sep="")
1: 1-800-program
2: 
Read 1 item
1-800-7764726
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.