Реалізація функцій, подібних до т9


10

Ваша задача сьогодні - реалізувати функціонал, подібний до т9 .

Ви реалізуєте функцію, яка матиме лише 2 параметри.
Ви отримаєте 1 номер телефону в рядку та вміст текстового файлу зі списком слів (не припускайте конкретного стилю нового рядка).
Ви можете скористатися посиланням https://raw.githubusercontent.com/eneko/data-repository/master/data/words.txt, щоб перевірити функціональність, або скористатися /usr/share/dict/words(див . Текстовий файл із переліком слів [закритий] для отримання додаткової інформації інформація).

Ви можете припустити, що ви завжди отримаєте принаймні 2 числа.

Вказавши число, ви прочитаєте зі списку слів і повернете слова, починаючи з відображення букв до цих слів. Це означає, що на вході повинні бути лише цифри від 2 до 9.
Ви можете робити все, що завгодно, якщо отримаєте недійсний ввід.

Якщо збіг не знайдено, ви можете повернути порожній список, null/ nilабо 0.

Пам’ятайте, що клавіші мобільних телефонів відображені у відповідні символи:

  • 0 і 1 є недійсними
  • 2 відповіді [abc]
  • 3 відповідність [def]
  • 4 сірники [ghi]
  • 5 матчів [jkl]
  • 6 матчів [mno]
  • 7 матчів [pqrs]
  • 8 матчів [tuv]
  • і 9 матчів [wxyz]

Приклади:

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

Після запуску функції ви можете роздрукувати її будь-яким способом.

Правила:

  • Стандартні лазівки INVALID
  • Ви повинні щось повернути, навіть якщо це null/ nil
    Javascript повернеться, undefinedякщо ви щось не повернете, тому це правило.
  • Ви не можете використовувати чи повторно реалізовувати відповіді інших або копіювати мою реалізацію.
  • Ви можете припустити, що для Javascript, що браузер буде вже відкритий і що innerText/ textContentавтоматичного елемента буде передано як 2-й параметр
  • Для компільованих мов ви не можете передавати спеціальні аргументи компілятору
  • Ви можете отримати ім'я файлу через аргументи компілятора
  • Змінні, макроси, глобальні змінні, константи, нестандартні класи та всі види, що передають інші значення всередині функції, вважатимуться недійсними.
  • У Javascript змінні без ключового слова varроблять ваш код недійсним
  • Ваша функція буде названа f
  • Ви можете мати і мати лише 2 аргументи щодо вашої функції
  • Намагайтеся тримати код менше 500 секунд для запуску.
  • Не потрібно турбуватися про пробіли
  • Ви повинні використовувати лише символи для друку ASCII .
    Виняток становлять мови, які використовують лише символи, що не друкуються (APL та пробіли - 2 приклади).

Оцінка:

  • Найменша кількість байтів виграє
  • Якщо у вашій відповіді недійсні символи для друку ASCII , вважатиметься, що відповідь кодується в UTF-32
    . Виняток із кодування змусить вашу відповідь рахувати символами .
  • Вважається лише тіло функції, не рахуйте нічого іншого, що ви робите поза ним
  • Бонус -30%, якщо ви робите систему прогнозування на основі сусідства або найпоширеніших слів
  • Бонус розміром -20%, якщо ви повернете лише перші 5 збігів за кожну букву, що відповідає першому номеру (наприклад: 245 поверне 5 слів, починаючи з "a", 5 починаючи з "b" і 5 починаючи з "c" ).

Ось приклад реалізації за допомогою 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);
}

Щоб запустити його, відкрийте посилання зі списку та запустіть, наприклад:

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

Цей приклад був протестований і працює в операційній системі Opera 12.17 64bit на ОС Windows 7 Home Edition 64bit.


Чи є другим аргументом програми ім'я файлу, що містить слова або список самих слів?
Оптимізатор

@ MartinBüttner UTF-8 не є несправедливим (він як і раніше вважає символи ASCII 1 байтом), але я змінив правило.
Ісмаїл Мігель

@Optimizer Другий аргумент - це список слів. Ви можете передати ім'я файлу через аргумент компілятора і прочитати файл, якщо хочете. Але єдине, що враховує, - це функціональний орган.
Ісмаїл Мігель

@ MartinBüttner Якщо вважати ASCII, він рахується як байти. Ви хочете сказати, що в коді APL буде 1 байт розміром 8 біт?
Ісмаїл Мігель

2
-1 за невідповідні обмеження
AJMansfield

Відповіді:


3

CJam, 28 байт

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

Вводиться у вигляді "<number>" [<list of words>]

Приклад:

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

Вихід:

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

Наразі жодного бонусу не збирається.

Спробуйте код онлайн тут, але для фактичних вимірювань часу запустіть його на компіляторі Java

Зауважте, що CJam представляє порожні списки на кшталт ""

Для перетворення необробленого списку слів у список CJam використовуйте наступний код із списком слів у якості введення:

qN/p

"Ви отримаєте 1 номер телефону в рядку та вміст текстового файлу із переліком слів" -> Чи можете ви реалізувати в іншому блоці потрібний код для читання файлу у списку корисних даних?
Ісмаель Мігель

@IsmaelMiguel Ви маєте на увазі не частину цього коду, а просто допоміжний код для перетворення списку у правильний формат?
Оптимізатор

Саме так. Якого коду недостатньо для підтвердження, він може використовувати список слів як наведені приклади. Але я все-таки відмовився, просто хотів, щоб той помічник був.
Ісмаїл Мігель

Чи можете ви додати його до відповіді? Як редакція, в іншій частині
Ісмаель Мігель

Саме так. Це саме те, про що я кажу! Давайте подивимось, чи зможете ви оптимізувати її ще більше
Ісмаель Мігель

2

Ява: 395

Це формує схему регулярного вираження на основі літер, дозволених для кожного числа, а потім в кінці наклеюється на. *, Щоб відповідати будь-яким наступним символам.

Ось версія для гольфу:

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

А ось і версія для читання

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

Ваш код суперечить правилу № 7: "Змінні, макроси, глобальні змінні, константи, нестандартні класи та всі види, що передають інші значення всередині функції, вважатимуться недійсними." і це якось суперечить правилу № 3: "Ви не можете використовувати чи повторно реалізовувати відповіді інших чи копіювати мою реалізацію.", але у вашому коді це щось спірне. І це також суперечить правилу 9: "Ваша функція буде названа f".
Ісмаїл Мігель

@IsmaelMiguel На жаль Правило 7 можна легко зафіксувати, перемістивши константу всередині функції. Я просто витягував це за межі функції для кращого стилю програмування. Правило 9 - це також легке виправлення. Зізнаюся, я не прочитав вашої відповіді, тому навмисно не намагався її скопіювати. Я можу видалити свою відповідь, якщо ви вважаєте, що це занадто близько до конкурсу.
Брайан J

Ваша відповідь гаразд. У вас є помилка у вашому коді. На останній постійній ( ([W-Zw-z)]) вона повинна бути ([W-Zw-z]). А в Code-golf вам не доведеться турбуватися про стилі програмування та добрі практики: ваш код повинен просто робити це з необхідними параметрами. Якщо ви відзначите моя відповідь, ви побачите наступний рядок: $s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];. Це жахливий "злочин" в PHP. В основному я змушую PHP конвертувати неіснуючі константи в рядки. Це цілком прийнятно. Ви також побачите, що я навіть не встановлюю змінну $tдо масиву, перш ніж використовувати її як таку
Ісмаель Мігель

@IsmaelMiguel Хороший замах на помилку регулярного виразу. Дякуємо, що вказали на це. Я спробую завтра насправді гольфу; можливо, знайдіть на цьому сайті кілька прикладів Java.
Брайан Дж.

Я не Java-програміст, але я вам розповідаю деякі речі. Ви можете перевірити codegolf.stackexchange.com/questions/6671/…, щоб отримати кілька порад. Загальні поради включають видалення непотрібних пробілів (нові рядки, пробіли, вкладки), назви змінних, що містять одну букву, і зробити все, що ви можете, щоб максимально зменшити розмір коду.
Ісмаїл Мігель

1

C # .NET 4,5 235

Це має працювати:

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

Ласкаво просимо до PPCG. Ваш код буде працювати, але вам все одно потрібно зменшити його набагато більше. Видаливши всі непотрібні пробіли (пробіли, вкладки, нові рядки), мені вдалося зменшити ваш код до 167 байт. Цей код можна зменшити набагато більше, я впевнений у цьому. Я рекомендую прочитати codegolf.stackexchange.com/questions/173/…, щоб ще більше скоротити код. Щоб вам трохи допомогти, список слів - це рядок, розділений новими рядками, і ви, здається, припускаєте, що в ньому вже можна використовувати foreach. Якщо ви очікуєте, що це вже буде IEnumerable, включіть код, який використовується зовні
Ісмаель Мігель

@IsmaelMiguel TY Я на це подивлюсь. Список є IE Чимало немає коду поза тим, що я розмістив.
Chaossie

Якщо ви подивитеся на специфікацію функції, ви побачите, що другий параметр також є рядком. (Цитуючи: "Ви отримаєте 1 номер телефону в рядку та вміст текстового файлу зі списком слів (не передбачайте конкретного стилю нового рядка).") І у вас на aвар. Є 1 марний пробіл .
Ісмаїл Мігель

Я помітив вдосконалення у вашому питанні, і я дав вам підсумок. Але ви все одно можете зберегти байт на aвар. Але я дійсно бачу помітні поліпшення! Продовжуй гарно працювати.
Ісмаель Мігель

1

Python 2 (155 байт)

Також слід працювати в Python 3 з відповідними замінами ( string-> bytes, bпрефіксом на рядках тощо).

Я не був впевнений, чи maketransвважають дзвінок поза функцією «чесним»; якщо ні, то функція становить 134 байти, при цьому вона переміщується всередину.

EDIT: Упустив один байт від дурного нагляду.

З підготовленими maketrans, 67 байт:

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)]

З maketransтілом, 134 байти:

from string import maketrans

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

З importта maketransв тілі, 155 байт:

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

Тестовий дзвінок:

print f('9999',open('words.txt','rt').read())

Це maketransчастина органу функції. Ви повинні перемістити його. Я не знаю, чи це можливо, але ви можете спробувати безпосередньо скористатися import. Я думаю, я це десь бачив ... Але ваш код справді приємний!
Ісмаїл Мігель

Ви маєте на увазі переміщення імпорту та дзвінка в тіло? Так, я думаю, що це теж можна зробити.
Кріптих стоїть з Монікою

Я думав про те t=(from stirng import maketrans)([...]). Я поняття не маю, чи це навіть можливо. Але, можливо, ви можете використати те, from string import as x t=x([...])що я не впевнений, чи можливо це теж: /
Ісмаель Мігель

Правильна версія - остання. Але відповідь як є є прийнятною на мою думку. +1 для __import__('string').maketran.
Ісмаїл Мігель

Добре, дякую. Я видалив недійсні відповіді.
Кріптих стоїть з Монікою

0

PHP 5.4+ (171 186-20% = 148,8 байт):

Ну, це досить величезна відповідь, але добре.

Я сподіваюся, що це принесе більше людей відповісти.

Ця функція очікує, що неочищений вміст буде прочитаний.

Ось код:

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

Це працює, перевіривши, що лист є у списку дозволених літер.

Приклад: вхід 36зробить, щоб перевірити, чи 1abcє перша буква слова і чи 1defє друга літера.

Я додаю, 1щоб він не перевіряв, чи є лист на 1-му положенні (який би повернувся 0і який би оцінили false). if(!strpos(1..$s[$c],$v[$i]))або if(!strpos($c.$s[$c],$v[$i]))матиме такий же ефект, але 1-й плутає більше, і мені це подобається.

Якщо цього не зробити, слово буде видалено.

Не залишивши жодних слів, він повертає порожній масив.

Щоб перевірити це в Інтернеті, перейдіть на сторінку http://writecodeonline.com/php/ і створіть просту змінну зі словом для рядка.

Тестовий приклад:

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));

Це має вивести:

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

Для роботи над старими версіями php замініть $s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];на$s=array(2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz);


Для 20% бонусу:

Для зменшення коду я просто додав ||$t[$v[0]]++>4, який перевіряє, скільки разів було використано першу букву.

У php $tне потрібно визначати, що допомагає зменшити великий шматок до 37,2 байт.

Щоб побачити цей ефект, використовуйте таку змінну як другий аргумент:

$lines=<<<WORDS
one
two
three
four
five
six
seven
eight
nine
ten
twelve
time
tutor
test
truth
WORDS;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.