Menerapkan fungsi seperti t9

10

Tantangan Anda hari ini adalah mengimplementasikan fungsionalitas mirip- t9 .

Anda akan mengimplementasikan fungsi yang hanya akan memiliki 2 parameter.
Anda akan menerima 1 nomor telepon dalam sebuah string dan konten file teks dengan daftar kata-kata (jangan menganggap gaya baris baru tertentu).
Anda dapat menggunakan tautan https://raw.githubusercontent.com/eneko/data-repository/master/data/words.txt untuk menguji fungsionalitas, atau menggunakan /usr/share/dict/words(periksa file teks dengan daftar kata [ditutup] untuk informasi lebih lanjut. informasi).

Anda dapat mengasumsikan bahwa Anda akan selalu menerima setidaknya 2 angka.

Dengan nomor tersebut, Anda akan membaca dari daftar kata-kata dan mengembalikan kata-kata yang dimulai dengan pemetaan huruf ke kata-kata itu. Ini berarti bahwa input harus hanya angka dari 2 hingga 9.
Anda dapat melakukan apa pun yang Anda inginkan jika Anda menerima input yang tidak valid.

Jika tidak ada yang cocok, Anda dapat mengembalikan daftar kosong, null/ nilatau 0.

Ingat bahwa tombol ponsel dipetakan ke karakternya yang setara:

  • 0 dan 1 tidak valid
  • 2 pertandingan [abc]
  • 3 cocok [def]
  • 4 pertandingan [ghi]
  • 5 pertandingan [jkl]
  • 6 pertandingan [mno]
  • 7 pertandingan [pqrs]
  • 8 pertandingan [tuv]
  • dan 9 pertandingan [wxyz]

Contoh:

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

Setelah Anda menjalankan fungsi Anda, Anda dapat mencetaknya dengan cara apa pun yang Anda inginkan.

Aturan:

  • Celah standar adalah INVALID
  • Anda harus mengembalikan sesuatu, meskipun itu null/ nil
    Javascript akan kembali undefinedjika Anda tidak mengembalikan sesuatu, oleh karena itu aturan ini.
  • Anda tidak dapat menggunakan atau mengimplementasikan kembali jawaban orang lain atau menyalin implementasi saya.
  • Anda dapat mengasumsikan, untuk Javascript, bahwa browser akan sudah dibuka dan bahwa innerText/ textContentdari elemen otomatis akan diteruskan sebagai parameter ke-2
  • Untuk bahasa yang dikompilasi, Anda tidak bisa meneruskan argumen khusus ke kompiler
  • Anda dapat menerima nama file melalui argumen kompiler
  • Variabel, makro, variabel global, konstanta, kelas non-standar, dan semua pengurutan yang melewati nilai lain di dalam fungsi akan dianggap tidak valid.
  • Dalam Javascript, variabel tanpa kata kunci varmembuat kode Anda tidak valid
  • Fungsi Anda akan dinamai f
  • Anda hanya dapat dan hanya memiliki 2 argumen pada fungsi Anda
  • Cobalah untuk menjaga kode Anda di bawah 500 detik untuk dijalankan.
  • Anda tidak perlu khawatir tentang spasi putih
  • Anda harus menggunakan hanya karakter yang dapat dicetak ASCII .
    Pengecualian adalah bahasa yang hanya menggunakan karakter yang tidak dapat dicetak (APL dan spasi putih adalah 2 contoh).

Mencetak:

  • Jumlah byte terendah menang
  • Memiliki karakter ASCII yang dapat dicetak yang dapat dicetak dalam jawaban Anda, akan dihitung sebagai jawaban yang dikodekan dalam UTF-32
    . Pengecualian untuk pengkodean akan membuat jawaban Anda dihitung berdasarkan karakter .
  • Hanya fungsi tubuh yang penting, jangan menghitung apa pun yang Anda lakukan di luarnya
  • Bonus -30% jika Anda membuat sistem prediksi berdasarkan lingkungan atau kata-kata yang paling umum
  • Bonus dalam ukuran -20% jika Anda hanya mengembalikan 5 pertandingan pertama untuk setiap huruf yang sesuai dengan angka pertama (mis .: 245 akan mengembalikan 5 kata dimulai dengan 'a', 5 dimulai dengan 'b' dan 5 dimulai dengan 'c' ).

Berikut adalah contoh implementasi, menggunakan 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);
}

Untuk menjalankannya, buka tautan daftar dan jalankan, misalnya:

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

Contoh ini diuji dan berfungsi di bawah Opera 12.17 64bits pada Windows 7 Home Edition 64bits.

Ismael Miguel
sumber
Apakah argumen kedua ke program nama file yang berisi kata-kata atau daftar kata-kata itu sendiri?
Pengoptimal
@ MartinBüttner UTF-8 tidak tidak adil (masih menganggap ASCII karakter sebagai 1 byte), tapi saya mengubah aturannya.
Ismael Miguel
@Optimizer Argumen ke-2 adalah daftar kata-kata. Anda dapat melewatkan nama file di atas argumen kompiler dan membaca file, jika Anda mau. Tetapi satu-satunya hal yang diperhitungkan adalah fungsi tubuh.
Ismael Miguel
@ MartinBüttner Dengan menghitung sebagai ASCII, itu dihitung sebagai byte. Anda ingin saya mengatakan bahwa kode APL akan memiliki 1 byte yang memiliki ukuran 8 bit?
Ismael Miguel
2
-1 untuk batasan yang tidak pantas
AJMansfield

Jawaban:

3

CJam, 28 byte

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

Mengambil input dalam bentuk "<number>" [<list of words>]

Contoh:

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

Keluaran:

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

Tidak ada bonus untuk saat ini.

Coba kode online di sini tetapi untuk pengukuran waktu aktual, jalankan di kompiler Java

Perhatikan bahwa CJam mewakili daftar kosong seperti ""

Untuk mengonversi daftar kata mentah menjadi daftar CJam, gunakan kode berikut dengan daftar kata sebagai masukan:

qN/p
Pengoptimal
sumber
"Anda akan menerima 1 nomor telepon dalam sebuah string dan konten file teks dengan daftar kata" -> dapatkah Anda menerapkan, pada blok yang berbeda, kode yang diperlukan untuk membaca file ke dalam daftar yang dapat digunakan?
Ismael Miguel
@ IsmaelMiguel Maksud Anda bukan bagian dari kode ini, tetapi hanya kode pembantu untuk mengkonversi daftar ke format yang benar?
Pengoptimal
Persis. Kode Anda yang tidak cukup untuk membuktikannya dapat menggunakan daftar kata-kata sebagai contoh yang diberikan. Tapi saya tetap memilih, saya hanya ingin kode pembantu itu.
Ismael Miguel
Bisakah Anda menambahkannya ke jawabannya? Sebagai suntingan, di bagian lain
Ismael Miguel
Persis. Itu yang saya bicarakan! Mari kita lihat apakah Anda dapat mengoptimalkannya lebih jauh
Ismael Miguel
2

Jawa: 395

Ini membentuk pola regex berdasarkan huruf-huruf yang diperbolehkan untuk setiap angka, dan kemudian menekan a. * Di akhir untuk mencocokkan karakter berikut.

Ini adalah versi golfnya:

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

Dan di sini adalah versi tanpa kemampuan untuk membaca-kemampuan

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
sumber
Kode Anda bertentangan dengan aturan nomor 7: "Variabel, makro, variabel global, konstanta, kelas non-standar, dan semua yang melewati nilai-nilai lain di dalam fungsi akan dianggap tidak valid." dan itu agak bertentangan dengan aturan nomor 3: "Anda tidak dapat menggunakan atau mengimplementasikan kembali jawaban orang lain atau menyalin implementasi saya.", tetapi pada kode Anda itu agak bisa diperdebatkan. Dan itu juga bertentangan dengan aturan 9: "Fungsi Anda akan dinamai f".
Ismael Miguel
@IsmaelMiguel Ups. Aturan 7 dapat dengan mudah diperbaiki dengan menggerakkan konstanta di dalam fungsi. Saya hanya menariknya di luar fungsi untuk gaya pemrograman yang lebih baik. Aturan 9 juga merupakan perbaikan yang mudah. Saya akui saya tidak membaca jawaban Anda, jadi saya tidak sengaja mencoba menyalinnya. Saya dapat menghapus jawaban saya jika menurut Anda terlalu dekat untuk kontes.
Brian J
Jawaban Anda baik-baik saja. Anda memiliki bug pada kode Anda. Pada konstanta terakhir ( ([W-Zw-z)]) seharusnya ([W-Zw-z]). Dan pada Code-golf Anda tidak perlu khawatir tentang gaya pemrograman dan praktik yang baik: kode Anda hanya harus melakukan hal itu dengan parameter yang diperlukan. Jika Anda memeriksa jawaban saya, Anda akan melihat baris ini: $s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];. Ini adalah 'kejahatan' yang mengerikan di PHP. Pada dasarnya saya memaksa PHP untuk mengubah konstanta yang tidak ada menjadi string. Ini bisa diterima. Anda juga akan melihat bahwa saya bahkan tidak mengatur variabel $tke array sebelum menggunakannya
Ismael Miguel
@ IsmaelMiguel Bagus menangkap kesalahan regex. Terima kasih telah menunjukkannya. Saya akan mencoba untuk benar-benar golf besok; mungkin menemukan beberapa contoh Java di situs ini.
Brian J
Saya bukan programmer java, tetapi saya memberi tahu Anda beberapa hal. Anda dapat memeriksa codegolf.stackexchange.com/questions/6671/… untuk mendapatkan beberapa tips. Kiat umum termasuk menghapus spasi kosong yang tidak berguna (baris baru, spasi, tab), nama variabel panjang satu huruf dan melakukan semua yang Anda bisa untuk mengurangi ukuran kode sebanyak mungkin.
Ismael Miguel
1

C # .NET 4.5 235

Ini seharusnya bekerja:

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
sumber
Selamat datang di PPCG. Kode Anda akan berfungsi, tetapi Anda masih perlu menguranginya lebih banyak. Dengan menghapus semua spasi kosong yang tidak berguna (spasi, tab, baris baru) saya berhasil mengurangi kode Anda menjadi 167 byte. Kode ini dapat dikurangi lebih banyak, saya yakin itu. Saya sarankan membaca codegolf.stackexchange.com/questions/173/… untuk lebih mempersingkat kode Anda. Untuk sedikit membantu Anda, daftar kata adalah string yang dipisahkan oleh baris baru, dan Anda tampaknya menganggap sudah mungkin untuk menggunakan a foreachdi dalamnya. Jika Anda berharap sudah IEnumerable, sertakan kode yang digunakan di luar
Ismael Miguel
@IsmaelMiguel TY Saya akan melihatnya. Daftar adalah nomor IEnumerable tidak ada kode di luar apa yang saya posting.
Chaossie
Jika Anda melihat spesifikasi fungsi, Anda akan melihat parameter ke-2 juga berupa string. (Mengutip: "Anda akan menerima 1 nomor telepon dalam sebuah string dan konten file teks dengan daftar kata-kata (jangan menganggap gaya baris baru tertentu).") Dan Anda memiliki 1 spasi kosong yang tidak berguna di avar Anda .
Ismael Miguel
Saya perhatikan perbaikan pada pertanyaan Anda, dan saya memberi Anda suara positif. Tapi Anda masih bisa menyimpan byte di avar Anda . Tapi saya benar-benar melihat peningkatan nyata! Terus bekerja dengan baik.
Ismael Miguel
1

Python 2 (155 byte)

Harus juga bekerja di Python 3 dengan penggantian yang sesuai ( string-> bytes, bawalan pada string, dll.).

Saya tidak yakin apakah memiliki maketranspanggilan di luar fungsi tersebut dianggap "adil"; jika tidak, fungsinya 134 byte dengan itu dipindahkan ke dalam.

EDIT: Turun satu byte dari pengawasan bodoh.

Dengan siap maketrans, 67 byte:

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

Dengan maketransisi, 134 byte:

from string import maketrans

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

Dengan importdan maketransdalam tubuh, 155 byte:

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

Panggilan uji:

print f('9999',open('words.txt','rt').read())
criptych berdiri bersama Monica
sumber
Ini maketransadalah bagian dari fungsi tubuh. Anda harus memindahkannya. Saya tidak tahu apakah itu mungkin, tetapi Anda dapat mencoba langsung menggunakan import. Saya rasa saya melihatnya di suatu tempat ... Tapi kode Anda sangat bagus!
Ismael Miguel
Apakah Anda bermaksud memindahkan impor dan menelepon ke badan? Ya, saya pikir itu bisa dilakukan juga.
Criptych berdiri dengan Monica
Saya sedang memikirkan t=(from stirng import maketrans)([...]). Saya tidak tahu apakah itu mungkin. Tapi mungkin Anda dapat menggunakan from string import as x t=x([...])yang saya tidak yakin apakah itu mungkin juga: /
Ismael Miguel
Versi yang benar adalah yang terakhir. Tapi jawabannya apa adanya bisa diterima menurut saya. +1 untuk __import__('string').maketran.
Ismael Miguel
Ok terima kasih. Saya telah menghapus jawaban yang tidak valid.
Criptych berdiri dengan Monica
0

PHP 5.4+ (171 186-20% = 148.8 byte):

Baiklah, ini jawaban yang sangat besar, tetapi baik.

Saya harap ini membawa lebih banyak orang untuk menjawab.

Fungsi ini mengharapkan konten mentah sedang dibaca.

Ini kodenya:

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

Ini berfungsi dengan memverifikasi bahwa surat itu ada dalam daftar surat yang diizinkan.

Contoh: input 36akan membuat untuk memeriksa apakah 1abcmemiliki huruf pertama dari kata dan yang 1defmemiliki huruf ke-2.

Saya menambahkan 1sehingga tidak memeriksa apakah surat itu di posisi 1 (yang akan kembali 0dan yang akan dievaluasi false). if(!strpos(1..$s[$c],$v[$i]))atau if(!strpos($c.$s[$c],$v[$i]))akan memiliki efek yang sama, tetapi yang pertama lebih membingungkan dan saya menyukainya.

Gagal melakukannya, akan menghapus kata.

Dengan tidak ada kata yang tersisa, itu mengembalikan array kosong.

Untuk menguji ini secara online, buka http://writecodeonline.com/php/ dan buat variabel sederhana dengan kata untuk baris.

Contoh yang dapat diuji:

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

Ini akan menghasilkan:

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

Untuk bekerja pada versi php yang lebih lama, ganti $s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];dengan$s=array(2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz);


Untuk bonus 20%:

Untuk mengurangi kode saya cukup menambahkan ||$t[$v[0]]++>4, yang memeriksa berapa kali huruf pertama digunakan.

Dalam php, $ttidak perlu didefinisikan, membantu mengurangi sebagian besar dari 37,2 byte.

Untuk melihat efek ini, gunakan variabel berikut sebagai argumen ke-2:

$lines=<<<WORDS
one
two
three
four
five
six
seven
eight
nine
ten
twelve
time
tutor
test
truth
WORDS;
Ismael Miguel
sumber