Litery w numerach telefonów


23

Problem:

Tworzysz nowy telefon, na którym ludzie mogą na przykład wpisywać wyspecjalizowane numery telefonów 1-800-program, i zostaną one automatycznie przekonwertowane na użyteczny numer telefonu, taki jak 1-800-7764726(w poprzednim przykładzie).

Twój program otrzyma ciąg znaków, jeśli ma dowolną długość z cyframi, literami i myślnikami, i przekonwertuje wszystkie litery na odpowiadające im liczby.

Oto klawiatura w celach informacyjnych:

klawiatura

Zasady:

  • Twój program otrzyma ciąg
  • Przetworzy go i zwróci / wydrukuje kolejny ciąg
  • Każdy język jest akceptowany
  • Ponieważ jest to , wygrywa najkrótszy kod

Czy program powinien obsługiwać zarówno duże, jak i małe litery na wejściu?
mattnewport

3
@mattnewport - nie, zakładamy, że zmienna została już zamieniona na małe litery
TheDoctor

Odpowiedzi:


8

GolfScript, 24 znaki

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

Wejście testowe:

0123456789-abcdefghijklmnopqrstuvwxyz

Wyjście testowe:

0123456789-22233344455566677778889999

Wyjaśnienie:

  • { }% stosuje kod między nawiasami klamrowymi do każdego znaku wejścia.

  • .96>{ }* wykonuje kod między wewnętrznymi nawiasami klamrowymi tylko wtedy, gdy kod ASCII znaku jest większy niż 96 (tzn. jest to mała litera).

  • Pierwszy ,zamienia znak w listę wszystkich znaków o niższych kodach ASCII i 91,'qx'+-odfiltrowuje wszystkie znaki o kodach ASCII mniejszych niż 91, a także litery qi xz listy. W ten sposób na przykład postać azostaje zamieniona na listę 6-znakową [\]^_`, a zzostaje zamieniona na listę 29-znakową[\]^_`abcdefghijklmnoprstuvwy .

  • Drugi ,zlicza elementy pozostałe na liście i 3/dzieli tę liczbę przez trzy (zaokrąglając w dół). Na koniec `zamienia wynikową liczbę (w zakresie 2–9) na ciąg.

Tak więc, zgodnie ze specyfikacją, myślniki i liczby pozostają niezmienione, podczas gdy małe litery są mapowane na liczby zgodnie ze schematem klawiatury referencyjnej. Kod faktycznie przejdzie czysto przez wszystkie drukowalne znaki ASCII, z wyjątkiem małych liter (które są odwzorowane zgodnie z opisem) i znaków {, |oraz} (które są mapowane do ciągu dwóch znaków 10). 8-bitowe wejście inne niż ASCII spowoduje powstanie różnego rodzaju dziwnych danych liczbowych.

Po tym wszystkim trochę rozczarowujące jest to, że pokonuje to trywialne rozwiązanie bash tylko o sześć znaków.


50

Bash, 30

Edycja: Dziękuję Klamce za wyeliminowanie 3 znaków

tr a-z 22233344455566677778889

Przykład:


10
Nie możesz usunąć ostatnich 3 9sekund?
Klamka

16

C, 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
Niezła matematyka. Chcę tylko powiedzieć, że możesz zmniejszyć 1 znak, zakładając, że EOF wynosi -1 i zrób~(c=getchar())
użytkownik12205

Nie możesz użyć getch()zamiast getchar()?
starsplusplus

Ściśle mówiąc, getch()nie jest standardem C, dlatego wydaje mi się, że nie łączy się w ideone. Mimo to przetestowałem go w MSVC i tak naprawdę nie działa to smutno - ponieważ bezpośrednio zużywa klawiaturę, nie ma możliwości wyjścia z programu, chociaż tłumaczy to, co piszesz w locie, co jest całkiem fajne.
mattnewport

4

JavaScript - 103 znaki

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
Nie wiedziałem, że możesz to zrobić za pomocą .replace. Do góry głosuj na Ciebie!
SuperJedi224,

Można wymienić charCodeAt(0)ze charCodeAt()można użyć funkcji strzałki dla function(y)...zaoszczędzić kilka bajtów i ~~(y/3)można użyćy/3|0
Chau Giang

3

Ruby, 75 znaków

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

Używa przestarzałego charsbloku i drukuje każdą literę indywidualnie za pomocą $><<. Ja też lubię [[*?a..?z].index(c)||-1]; pobiera znak odpowiadający tej literze alfabetu, jeśli jest to litera, a ostatni znak (który jest niezmienionym znakiem testowym), jeśli nie.

Rubinowy, 43 (lub 35) znaków

Rażąco kradnie z @ace;)

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

Ogol 8 znaków, jeśli mogę uruchomić w IRB ze zmienną sjako ciągiem:

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

3

C ++ - 222 znaków

Najdłuższe jak dotąd rozwiązanie:

#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, nie sądzę, żeby celem było tutaj najdłuższe rozwiązanie ...
Danny

@Danny C ++ nie nadaje się dobrze do gry w golfa . Java i C # to jedyne gorsze języki, które znam (wszystkie klasy, tworzenie obiektów i długie nazwy danych wyjściowych ...).
Hosch250,

Wiem, pomyślałem, że to zabawne, że wspomniałeś o „Najdłuższym rozwiązaniu”.
Danny

3

Frink, 92

Wiem dość gadatliwy język. Sprawdza to 8 wartości zamiast 26 bez konieczności wpisywania porównań. Czy którekolwiek z powyższych rozwiązań „222333444 ..” można zmniejszyć w podobny sposób?

Korzystanie z wbudowanych struktur, 107

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

Korzystanie z niestandardowej funkcji rekurencyjnej 92

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

+1 za zredukowanie metody tłumaczenia ciągów do wyszukiwania 8-znakowego. Miły dotyk.
Jonathan Van Matre

2

Smalltalk, 79 70

dane wejściowe to s:

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

prawdopodobnie nie jest kandydatem na bycie najkrótszym - ale może zainteresować starą sztuczką, aby uniknąć testu na nie znaleziony warunek (indexOf: w tym przypadku zwraca 0). Dlatego nie jest wymagany specjalny test na litery. Niektóre Smalltalks mają jednak niezmienne ciągi i potrzebujemy 4 dodatkowych znaków („kopiuj”).

Och, lepsza wersja, która nawet zajmuje niezmienne ciągi znaków w 70 znakach:

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

2

Mathematica 90

Jest to zgodne z logiką rozwiązania @ ace:

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

Przykład

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

8437889


Reprezentacja twojej strzałki nie jest akceptowana przez Mma w kopiowaniu / wklejaniu
Dr. belisarius

Ponadto, nie trzeba 1się #1:)
Dr. Belizariusz

Belizariusz, zmieniłem strzałę do tyłu i usunąłem 1. Nadal 90 znaków, ale wycinanie i wklejanie będzie działać. Rozumiesz oczywiście motywację do korzystania ze strzały jednoznakowej.
DavidC

Byłem tam, zrobiłem to :)
Dr Belisarius

2

Perl, 50

Kolejna oczywista kopia odpowiedzi Ace na bash

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

1
Ten kod działa poprawnie, ale można go ulepszyć. Pozbądźmy się $ ARGV [0] i użyj -pzamiast tego przełącznika, który pozwala ładnie przejść przez każdą linię standardowego wejścia. W tym momencie zakresy w / y nie muszą być umieszczane w nawiasach kwadratowych. Możemy również pozbyć się trzech 9 pozostawiając tylko jeden i usunąć ostatni średnik: Proszę -p y/a-z/22233344455566677778889/ , 30 + 1 za -p. Dziękujemy za skorzystanie z usług golfowych i optymalizacyjnych Enterprise Chinese Perl i życzę miłego dnia.
chiński perl goth

2

R, bardzo długie, ale zabawne

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

k [32 znaki]

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

Stosowanie

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

2

JavaScript, 85

JavaScript nigdy nie wygra wojen golfowych, ale lubię to i chciałem zrobić coś innego niż wskoczyć na modę @ace.

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

2

PHP, 141

Nie najkrótszy, ale bardziej zabawny:

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

Bardziej czytelny:

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

OP powiedział, że dane wejściowe są już strtolower
pisane

2

Python 2.7, 80

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

Jestem nowy w Pythonie, więc jestem pewien, że musi istnieć sposób na grę w golfa jeszcze bardziej , to inne podejście, mam nadzieję, że wam się podoba, mój Boże, ładna jest Python!

Uruchom przykład:

  • dane wejściowe: 01-800-abcdefghijklmnopqrstuvwxyz
  • wyjście: 01-800-22233344455566677778889999

2

T-SQL, 216 bajtów

Spędziłem sporo czasu w ciągu ostatnich kilku nocy, starannie opracowując matematyczną funkcję sekwencji, która zaokrąglałaby poprawnie, aby wygenerować odpowiednie kody ASCII dla liczb z alfabetycznych kodów ASCII. Miał śmieszną liczbę miejsc po przecinku we współczynnikach, ale działał.

Jednak racjonalne podejście Mattnewport działa również w języku SQL, przy znacznie niższym koszcie bajtów, więc bezwstydnie pozbywam się własnej matematyki na jego korzyść. Głosuj w górę, to eleganckie rozwiązanie!

To moje:

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

Wykorzystuje rekurencyjne CTE, aby zaimprowizowany stos znaków w numerze telefonu i tłumaczyć litery w locie, a następnie trochę sztuczek SQL (SELECT @ p = @ p ​​+ columnValue), aby ponownie skomponować ciąg z CTE bez konieczności kolejny konstrukt rekurencyjny.

Wydajność:

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

2

Python 2.7, 66 65


Anakata's Original

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


Dalsza gra w golfa

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


Nie mam wystarczającej reputacji, aby skomentować odpowiedź @ anakata, dlatego napisałem tutaj osobny post. Miałem ten sam pomysł (biorąc moduł zarządzający 3), ale nie mogłem wymyślić, jak wydrukować odpowiednie liczby dla s - z .

W każdym razie ulepszenia wprowadzone przez golfa:

  • zmieniony raw_inputnainput

  • usunięto obce '\b'i nawiasy oraz pojedyncze cudzysłowy

  • usunięto +2przesunięcie i umieściłem je w pierwotnym odjęciu (97 - (3 * 2) = 91)

Przetestowano przy użyciu interpretera języka Python 2.7.6. Zakłada, zgodnie z regułami, ciąg znaków.


możesz również usunąć spację między) a if
Willem

Masz rację. dobry połów willem
zheshishei

1

PHP, 87

echo str_ireplace(range('a','z'),str_split('22233344455566677778889999'),fgets(STDIN));

1

q [38 znaków]

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

Zainspirowany rozwiązaniem @ ace

Przykład

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

1

XQuery, 71

BaseX został użyty jako procesor XQuery. $ijest wejściem.

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

Nie najkrótsza odpowiedź, ale dość krótka i bardzo czytelna.


1

Python, bardzo nie golfowy

Ponieważ wszyscy kopiują asa, przed wysłaniem pytania postanowiłem opublikować kod, który przygotowałem:

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 bajty):

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

Oczekuje izawierać ciąg.

Wypróbuj w dowolnej najnowszej wersji Firefoksa. Nie próbowałem Google Chrome.


1

Python 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, 93 ° C

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

Stosowanie

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

Pyton

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

0

ECMASCRIPT, 101 (z wejściem)

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

Dodano nową linię dla przejrzystości. 85 znaków, jeśli wejście jest w zmiennej.


0

Perl, 54

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

Strzelaj, @RobHoare wciąż bije mnie o 4 znaki. :)


0

QBasic, 155

Ach, wspomnienia ...

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

Powinno to być krótsze, ale testowałem przy użyciu repl.it , który nie zezwala na IFinstrukcje jednowierszowe i zachowuje się dziwnie, jeśli pominiesz zmienną NEXT i. Nie rozpoznaje również ASCfunkcji, więc aby uruchomić kod, musisz dodać to obejście na początku:

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

(Za drugim razem, gdy go uruchomisz, tłumacz narzeka, chyba że usuniesz DECLARE FUNCTIONlinię, idź na rysunek.)


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

Przykład:

> 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.