Zaimplementuj funkcjonalność podobną do t9

10

Twoim dzisiejszym wyzwaniem jest wdrożenie funkcjonalności podobnej do T9 .

Zaimplementujesz funkcję, która będzie miała tylko 2 parametry.
Otrzymasz 1 numer telefonu w ciągu i zawartość pliku tekstowego z listą słów (nie zakładaj określonego stylu nowej linii).
Możesz użyć linku https://raw.githubusercontent.com/eneko/data-repository/master/data/words.txt, aby przetestować funkcjonalność, lub użyj /usr/share/dict/words(zaznacz plik tekstowy z listą słów [zamknięty], aby uzyskać więcej Informacja).

Możesz założyć, że zawsze otrzymasz co najmniej 2 numery.

Biorąc pod uwagę liczbę, przeczytasz z listy słów i zwrócisz słowa zaczynające się od odwzorowania liter na te słowa. Oznacza to, że dane wejściowe powinny składać się tylko z liczb od 2 do 9.
Możesz zrobić co chcesz, jeśli otrzymasz nieprawidłowe dane wejściowe.

Jeśli nie zostanie znaleziony, można powrócić pustą listę, null/ nilalbo 0.

Pamiętaj, że klawisze telefonu są mapowane na odpowiadające im znaki:

  • 0 i 1 są nieprawidłowe
  • 2 mecze [abc]
  • 3 dopasowane [def]
  • 4 mecze [ghi]
  • 5 dopasowania [jkl]
  • 6 dopasowania [mno]
  • 7 dopasowania [pqrs]
  • 8 meczów [tuv]
  • i 9 dopasowań [wxyz]

Przykłady:

f('52726')
//returns ["Japan","japan","Japanee","Japanese","Japanesque"...,"larbowlines"]

f('552')
//returns ["Kjeldahl","kjeldahlization","kjeldahlize"...,"Lleu","Llew"]

f('1234')
//makes demons fly out your nose or divide by 0

f('9999')
//returns ["Zyzzogeton"]

f('999999')
//returns [] or null/nil or 0

Po uruchomieniu funkcji możesz wydrukować ją w dowolny sposób.

Zasady:

  • Standardowe luki są NIEPRAWIDŁOWE
  • Musisz coś zwrócić, nawet jeśli to null/ nil
    JavaScript zwróci, undefinedjeśli czegoś nie zwrócisz, dlatego ta reguła.
  • Nie możesz użyć lub ponownie zaimplementować odpowiedzi innych osób ani skopiować mojej implementacji.
  • W przypadku Javascript można założyć, że przeglądarka zostanie już otwarta i że element innerText/ textContentelementu automatycznego zostanie przekazany jako drugi parametr
  • W przypadku języków skompilowanych nie można przekazywać kompilatorowi specjalnych argumentów
  • Możesz otrzymać nazwę pliku zamiast argumentów kompilatora
  • Zmienne, makra, zmienne globalne, stałe, niestandardowe klasy i wszystkie inne przekazywanie innych wartości wewnątrz funkcji zostaną uznane za nieprawidłowe.
  • W JavaScript zmienne bez słowa kluczowego varpowodują, że kod jest nieprawidłowy
  • Twoja funkcja zostanie nazwana f
  • Możesz mieć tylko i tylko 2 argumenty na swojej funkcji
  • Staraj się, aby kod działał krócej niż 500 sekund.
  • Nie musisz się martwić o białe znaki
  • Musisz używać tylko znaków drukowalnych ASCII .
    Wyjątkiem są języki, które używają tylko znaków niedrukowalnych (APL i białe znaki to 2 przykłady).

Punktacja:

  • Najniższa liczba bajtów wygrywa
  • Niepoprawne znaki drukowalne ASCII w odpowiedzi będą liczone jako odpowiedź kodowana w UTF-32
    . Wyjątek od kodowania spowoduje, że odpowiedź będzie liczona według znaków .
  • Liczy się tylko ciało funkcji, nie licz niczego, co robisz poza nim
  • Premia w wysokości -30%, jeśli stworzysz system przewidywania oparty na sąsiedztwie lub najczęściej używanych słowach
  • Premia wielkości -20%, jeśli zwrócisz tylko 5 pierwszych dopasowań dla każdej litery odpowiadającej pierwszej cyfrze (np .: 245 zwróci 5 słów zaczynających się na „a”, 5 zaczynających się na „b” i 5 zaczynających się na „c” ).

Oto przykład implementacji przy użyciu Javascript:

function f(phone, words)
{
    var keypad=['','','abc','def','ghi','jkl','mno','pqrs','tuv','wxyz'];
    var regex='';

    for(var i=0,l=phone.length;i<l;i++)
    {
        regex+='['+keypad[phone[i]]+']';
    }

    var regexp=new RegExp('\\s('+regex+'[a-z]*)\\s','gi');

    return words.match(regexp);
}

Aby go uruchomić, otwórz link do listy i uruchom, na przykład:

f('9999',document.getElementsByTagName('pre')[0].innerText);
//returns [" Zyzzogeton "]

Ten przykład został przetestowany i działa pod kontrolą Opery 12.17 64bits w systemie Windows 7 Home Edition 64bits.

Ismael Miguel
źródło
Czy drugim argumentem programu jest nazwa pliku zawierającego słowa lub sama lista słów?
Optymalizator
@ MartinBüttner UTF-8 nie jest niesprawiedliwy (nadal liczy znaki ASCII jako 1 bajt), ale zmieniłem regułę.
Ismael Miguel,
@Optimizer Drugi argument to lista słów. Możesz przekazać nazwę pliku nad argumentem kompilatora i odczytać plik, jeśli chcesz. Ale jedyne, co się liczy, to ciało funkcyjne.
Ismael Miguel,
@ MartinBüttner Licząc jako ASCII, jest liczony jako bajty. Chcesz, żebym powiedział, że kod APL będzie miał 1 bajt o wielkości 8 bitów?
Ismael Miguel
2
-1 za nieodpowiednie ograniczenia
AJMansfield

Odpowiedzi:

3

CJam, 28 bajtów

q~{el{'h-_9/-D+3/}%s1$#!},p;

Pobiera dane wejściowe w postaci "<number>" [<list of words>]

Przykład:

"52726" ["Japan" "japan" "Japanee" "Japanese" "Japanesque" "larbowlines" "ablution" "ablutionary" "abluvion" "ably" "abmho" "Abnaki" "abnegate"]

Wynik:

["Japan" "japan" "Japanee" "Japanese" "Japanesque" "larbowlines"]

Na razie nie będzie żadnego bonusu.

Wypróbuj kod online tutaj, ale aby zmierzyć rzeczywisty czas, uruchom go na kompilatorze Java

Zauważ, że CJam reprezentuje puste listy, takie jak ""

Aby przekonwertować surową listę słów na listę CJam, użyj następującego kodu z listą słów jako danymi wejściowymi:

qN/p
Optymalizator
źródło
„Otrzymasz 1 numer telefonu w ciągu i zawartość pliku tekstowego z listą słów” -> czy możesz zaimplementować w innym bloku potrzebny kod do odczytania pliku na użytecznej liście?
Ismael Miguel
@ IsmaelMiguel Masz na myśli nie część tego kodu, ale tylko kod pomocniczy do konwersji listy do prawidłowego formatu?
Optymalizator
Dokładnie. Który kod nie wystarczy, aby udowodnić, że może użyć listy słów jako podanych przykładów. Ale i tak głosowałem, chciałem tylko ten kod pomocnika.
Ismael Miguel
Czy możesz to dodać do odpowiedzi? Jako zmianę, w innej części
Ismael Miguel,
Dokładnie. O tym właśnie mówię! Zobaczmy, czy można jeszcze go zoptymalizować
Ismael Miguel,
2

Java: 395

Tworzy to wzór wyrażenia regularnego na podstawie liter, które są dozwolone dla każdej liczby, a następnie wstawia znak „*” na końcu, aby dopasować dowolne następujące znaki.

Oto wersja golfowa:

static ArrayList<String> f(String n,ArrayList<String> d){String[] k={"","","([A-Ca-c])","([D-Fd-f])","([G-Ig-i])","([J-Lj-l])","([M-Om-o])","([P-Sp-s])","([T-Vt-v])","([W-Zw-z])"};String r="";for(int i=0;i<n.length();++i)r+=k[n.charAt(i)-'0'];r += ".*";Pattern p=Pattern.compile(r);ArrayList<String> a=new ArrayList<String>();for(String w:dictionary)if(p.matcher(w).matches())a.add(w);return a;}

A oto wersja dla golfistów bez umiejętności czytania

public static ArrayList<String> f(String phoneNumber, ArrayList<String> dictionary) {

    String[] KEY_VALUES = {"", "", "([A-Ca-c])", "([D-Fd-f])", "([G-Ig-i])",
                                            "([J-Lj-l])", "([M-Om-o])", "([P-Sp-s])",
                                            "([T-Vt-v])", "([W-Zw-z])"};

    String regex = "";
    for (int i = 0; i < phoneNumber.length(); ++i) {
        regex += KEY_VALUES[phoneNumber.charAt(i) - '0'];
    }
    regex += ".*";
    Pattern p = Pattern.compile(regex);
    ArrayList<String> answers = new ArrayList<String>();
    for (String word : dictionary) {
        if (p.matcher(word).matches()) {
            answers.add(word);
        }
    }
    return answers;
}
Brian J.
źródło
Twój kod jest niezgodny z regułą numer 7: „Zmienne, makra, zmienne globalne, stałe, niestandardowe klasy i wszystkie inne przekazywanie innych wartości wewnątrz funkcji zostaną uznane za nieprawidłowe”. i jest to trochę sprzeczne z regułą nr 3: „Nie możesz użyć lub ponownie zaimplementować odpowiedzi innych ani skopiować mojej implementacji.”, ale w twoim kodzie jest to trochę dyskusyjne. Jest to również sprzeczne z zasadą 9: „Twoja funkcja zostanie nazwana f”.
Ismael Miguel
@IsmaelMiguel Oops. Regułę 7 można łatwo naprawić, przesuwając stałą wewnątrz funkcji. Właśnie wyciągałem go poza funkcję, aby uzyskać lepszy styl programowania. Zasada 9 jest również łatwa do rozwiązania. Przyznaję, że nie przeczytałem twojej odpowiedzi, więc nie próbowałem jej celowo kopiować. Mogę usunąć moją odpowiedź, jeśli uważasz, że jest ona zbyt blisko do konkursu.
Brian J
Twoja odpowiedź jest w porządku. Masz błąd w kodzie. Na ostatniej stałej ( ([W-Zw-z)]) powinno być ([W-Zw-z]). A w Code-golf nie musisz się martwić stylami programowania i dobrymi praktykami: twój kod musi po prostu robić to z wymaganymi parametrami. Jeśli zaznaczysz moją odpowiedź, widać ten wiersz: $s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];. To jest okropne „przestępstwo” w PHP. Zasadniczo zmuszam PHP do konwersji nieistniejących stałych na ciągi. Jest to całkowicie do przyjęcia. Zobaczysz również, że nawet nie ustawiam zmiennej $tna tablicę przed użyciem jej jako takiej
Ismael Miguel
@ IsmaelMiguel Dobry chwyt na błąd wyrażenia regularnego. Dzięki za zwrócenie na to uwagi. Spróbuję jutro zagrać w golfa; może znajdź kilka przykładów Java na tej stronie.
Brian J,
Nie jestem programistą Java, ale mówię ci kilka rzeczy. Możesz sprawdzić codegolf.stackexchange.com/questions/6671/..., aby uzyskać wskazówki. Ogólne wskazówki obejmują usuwanie bezużytecznych białych znaków (znaki nowej linii, spacje, tabulatory), nazwy zmiennych o długości jednej litery i czynią wszystko, co możliwe, aby maksymalnie zmniejszyć rozmiar kodu.
Ismael Miguel,
1

C # .NET 4.5 235

To powinno działać:

IEnumerable<string>F(string n,string d){IEnumerable<string>w=d.Split(null).ToList();string[]a={"","","abc","def","ghi", "jkl","mno","pqrs","tuv","wxyz"};foreach(var i in n){w=w.Where(x=>x.IndexOfAny(a[i-'0'].ToArray())>0);}return w;}
Chaossie
źródło
Witamy w PPCG. Twój kod będzie działał, ale nadal musisz go znacznie zmniejszyć. Usuwając wszystkie bezużyteczne białe znaki (spacje, tabulatory, znaki nowej linii) udało mi się zredukować kod do 167 bajtów. Ten kod można znacznie zmniejszyć, jestem tego pewien. Polecam przeczytać codegolf.stackexchange.com/questions/173/..., aby jeszcze bardziej skrócić swój kod. Aby ci trochę pomóc, lista słów jest ciągiem oddzielonym znakami nowej linii i wydaje się, że zakładasz, że można już foreachw niej użyć znaku. Jeśli spodziewasz się, że tak już jest IEnumerable, dołącz kod użyty na zewnątrz
Ismael Miguel
@IsmaelMiguel TY Spojrzę na to. Lista jest IEnumerable, nie ma kodu poza tym, co opublikowałem.
Chaossie,
Jeśli spojrzysz na specyfikację funkcji, zobaczysz, że drugi parametr jest również łańcuchem. (Cytując: „Otrzymasz 1 numer telefonu w ciągu i zawartość pliku tekstowego z listą słów (nie zakładaj określonego stylu nowej linii).”) I masz 1 bezużyteczną spację na swoim avar.
Ismael Miguel,
Zauważyłem poprawę twojego pytania i wyraziłem zgodę. Ale nadal możesz zapisać bajt na swoim avar. Ale naprawdę widzę zauważalną poprawę! Tak trzymaj.
Ismael Miguel,
1

Python 2 (155 bajtów)

Powinien także działać w Pythonie 3 z odpowiednimi zamiennikami ( string-> bytes, bprzedrostek na ciągach znaków itp.).

Nie byłem pewien, czy maketranswywołanie poza funkcją jest uważane za „prawidłowe”; jeśli nie, funkcja ma 134 bajty i jest przeniesiona do środka.

EDYCJA: Usunięto jeden bajt z głupiego niedopatrzenia.

Z przygotowanymi maketrans67 bajtami:

from string import maketrans
t=maketrans('abcdefghijklmnopqrstuvwxyz','22233344455566677778889999')

def f(n,w):
    return[x for x in w.split()if x.lower().translate(t).startswith(n)]

W maketransciele 134 bajty:

from string import maketrans

def f(n,w):
    return[x for x in w.split()if x.lower().translate(maketrans('abcdefghijklmnopqrstuvwxyz','22233344455566677778889999')).startswith(n)]

Z importi maketransw ciele, 155 bajtów:

def f(n,w):
    return[x for x in w.split()if x.lower().translate(__import__('string').maketrans('abcdefghijklmnopqrstuvwxyz','22233344455566677778889999')).startswith(n)]

Połączenie testowe:

print f('9999',open('words.txt','rt').read())
cryptych stoi z Moniką
źródło
maketransJest częścią ciała funkcji. Powinieneś to przenieść. Nie wiem, czy to w ogóle możliwe, ale możesz spróbować bezpośrednio użyć import. Myślę, że gdzieś to widziałem ... Ale twój kod jest naprawdę fajny!
Ismael Miguel,
Czy chcesz przenieść import i zadzwonić do treści? Tak, myślę, że to też można zrobić.
cryptych stoi z Monicą
Myślałem o tym t=(from stirng import maketrans)([...]). Nie mam pojęcia, czy to w ogóle możliwe. Ale może możesz użyć, from string import as x t=x([...])którego nie jestem pewien, czy jest to również możliwe: /
Ismael Miguel
Prawidłowa wersja to ostatnia. Moim zdaniem odpowiedź „tak jak jest” jest do zaakceptowania. +1 dla __import__('string').maketran.
Ismael Miguel,
Ok dzięki. Usunąłem nieprawidłowe odpowiedzi.
cryptych stoi z Monicą
0

PHP 5.4+ (171 186-20% = 148,8 bajtów):

Cóż, to dość duża odpowiedź, ale dobrze.

Mam nadzieję, że dzięki temu więcej osób odpowie.

Ta funkcja oczekuje na odczytanie surowej zawartości.

Oto kod:

function f($_,$a){$s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];$a=preg_split('@\r\n|\r|\n@',$a);for($i=0;$c=$_[$i];++$i)foreach($a as$k=>$v)if(!strpos(1..$s[$c],$v[$i])||$t[$v[0]]++>4)unset($a[$k]);return$a;}

Działa to poprzez sprawdzenie, czy litera znajduje się na liście dozwolonych liter.

Przykład: dane wejściowe 36sprawdziłyby, czy 1abcma pierwszą literę słowa, a która 1defma drugą literę.

Dołączam, 1aby nie sprawdzało, czy list znajduje się na 1. pozycji (która wróciłaby 0i to by się zmieniło false). if(!strpos(1..$s[$c],$v[$i]))lub if(!strpos($c.$s[$c],$v[$i]))będzie miał ten sam efekt, ale 1. myli bardziej i podoba mi się to.

W przeciwnym razie słowo zostanie usunięte.

Bez pozostawionych słów zwraca pustą tablicę.

Aby przetestować to online, przejdź na stronę http://writecodeonline.com/php/ i utwórz prostą zmienną ze słowem linia.

Testowalny przykład:

function f($_,$a)
{
    $s=array(2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz);
    $a=preg_split('@\r\n|\r|\n@',$a);

    for($i=0;$c=$_[$i];++$i)
        foreach($a as$k=>$v)
            if(!strpos(1..$s[$c],$v[$i]) || $t[$v[0]]++>4)
                unset($a[$k]);
    return$a;
}

$lines=<<<WORDS
one
two
three
four
five
six
seven
eight
nine
ten
WORDS;

var_dump(f('36',$lines));

To powinno wygenerować:

array(1) {
    [3]=>
      string(4) "four"
}

Aby pracować na starszych wersjach php, zamień $s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];na$s=array(2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz);


W przypadku premii 20%:

Aby zmniejszyć kod, po prostu dodałem ||$t[$v[0]]++>4, który sprawdza, ile razy pierwsza litera została użyta.

W php $tnie trzeba definiować, co pomaga zmniejszyć dużą porcję 37,2 bajtów.

Aby zobaczyć ten efekt, użyj następującej zmiennej jako drugiego argumentu:

$lines=<<<WORDS
one
two
three
four
five
six
seven
eight
nine
ten
twelve
time
tutor
test
truth
WORDS;
Ismael Miguel
źródło