Satu Surat Swap

18

Forum terbesar di web, disebut postcount ++ memutuskan untuk membuat game forum baru. Dalam permainan ini, tujuannya adalah memposting kata, tetapi kata tersebut harus memiliki satu huruf yang ditambahkan, dihapus, atau diubah. Bos Anda ingin Anda menulis sebuah program yang mendapatkan kata, dan kamus UNIX, saat Anda bekerja untuk perusahaan yang memiliki forum yang lebih cerdas dengan lebih banyak permainan forum yang cerdas, dan ingin menghancurkan persaingan (hei, itu bos Anda, jangan diskusikan dengan dia, Anda mendapatkan banyak uang dari pekerjaan Anda).

Program Anda akan mendapatkan dua argumen, kata, dan kamus. Karena pengguna yang mengelola program (ya, pengguna, perusahaan Anda tidak memiliki sumber daya untuk menjalankan bot) tidak sempurna, Anda harus menormalkan kasus di keduanya. Kata-kata dalam kamus mungkin memiliki huruf ASCII (baik huruf besar dan kecil, tetapi harus diabaikan selama perbandingan), tanda hubung, apostrof, dan spasi non-berturut-turut di tengah. Tidak lebih dari 78 karakter. Anda harus menampilkan daftar kata-kata yang akan diterima dalam permainan, untuk menghentikan kesenangan orang-orang yang memikirkan kata-kata secara manual.

Ini adalah contoh dari program yang Anda harapkan, memeriksa kata-kata yang mirip dengan golf.

> ./similar golf /usr/share/dict/words
Goff
Wolf
gold
golfs
goof
gulf
wolf

Ini /usr/share/dict/wordsadalah daftar kata-kata, dengan jeda setelah masing-masing. Anda dapat dengan mudah membacanya dengan fgets (), misalnya.

Perusahaan tempat Anda bekerja tidak memiliki banyak kartu punch (ya, ini 2014, dan mereka masih menggunakan kartu punch), jadi jangan sia-siakan. Tulis program sesingkat mungkin. Oh, dan Anda diminta untuk tidak menggunakan implementasi internal atau jarak jauh Levenshtein atau algoritma serupa lainnya. Sesuatu tentang Tidak Diciptakan Di Sini atau di luar rumah yang tampaknya dimasukkan oleh vendor ke dalam bahasa (Anda tidak memiliki bukti tentang itu, tetapi jangan berdiskusi dengan bos Anda). Jadi, jika Anda ingin jarak, Anda harus menerapkannya sendiri.

Anda bebas menggunakan bahasa apa pun. Bahkan dengan kartu punch, perusahaan memiliki akses ke sebagian besar bahasa pemrograman modern, seperti Cobol Ruby atau Haskell atau apa pun yang Anda inginkan. Mereka bahkan memiliki GolfScript, jika Anda pikir itu bagus untuk manipulasi string (saya tidak tahu, mungkin ...).

Pemenang mendapat 15 poin reputasi dari saya, dan mungkin banyak poin lain dari komunitas. Jawaban bagus lainnya akan mendapat 10 poin, dan poin dari komunitas juga. Anda mendengar bahwa poin tidak ada nilainya, tetapi kemungkinan besar mereka akan mengganti dolar pada tahun 2050. Namun itu tidak dikonfirmasi, tapi tetap saja ide yang bagus untuk mendapatkan poin.

Konrad Borowski
sumber
6
Kita tidak boleh "menggunakan implementasi internal atau jarak jauh Levenshtein atau algoritma serupa"? Hilang solusi 30 karakter Mathematica.
Michael Stern
@MichaelStern dan python pendek yang sama menggunakan fuzzy matching dari perpustakaan regex ini
Martin Ender
2
Hampir sama dengan codegolf.stackexchange.com/questions/6939/… .
Howard
"seperti Ruby atau Haskell" - ok, saya mengerti, Anda ingin saya berpartisipasi.
John Dvorak
Harap berikan contoh yang lebih baik, sehingga semua jenis perubahan akan muncul atau orang-orang akan terus mengirimkan algoritma yang salah.
desir

Jawaban:

4

GolfScript, 59 karakter

{32|}%"*"%.|(:w;{:x,),{:^[x>.1>]{.[^w=]\+}%{^x<\+w=},},},n*

Tentu, GolfScript luar biasa untuk manipulasi string!

Apa GolfScript tidak begitu pandai menangani file I / O atau argumen baris perintah. Dengan demikian, program ini mengharapkan untuk menerima semua inputnya melalui stdin: baris pertama yang tidak kosong dianggap sebagai kata target, sedangkan baris yang tersisa harus berisi kamus. Pada sistem Unixish, Anda dapat menjalankan kode ini misalnya dengan:

(echo golf; cat /usr/share/dict/words) | ruby golfscript.rb similar.gs

Pada kotak Ubuntu Linux saya, output dari perintah di atas adalah:

goff
wolf
gold
golfs
goof
gulf

Perhatikan bahwa semua kata dikonversi menjadi huruf kecil, dan duplikat apa pun dihilangkan; dengan demikian, tidak seperti output sampel Anda, milik saya tidak mencantumkan Wolfdan wolfsecara terpisah. Berdasarkan deskripsi tantangan Anda, saya menganggap ini dapat diterima.

Selain itu, kodenya sangat lambat, karena menggunakan pendekatan yang cukup kasar, dan bahkan tidak menggunakan optimasi yang jelas seperti memeriksa apakah panjang kata kandidat cocok dengan kata target ± 1. Namun, kode ini berhasil melalui daftar lengkap, tanpa filter /usr/share/dict/wordsdi ... um ... Saya akan memberi tahu Anda ketika selesai, OK?

Sunting: Oke, butuh sekitar 25 menit, tapi itu selesai.

Ilmari Karonen
sumber
+1 untuk representasi akurat tentang seberapa baik GolfScript untuk manipulasi string (dan melakukan manipulasi string dalam GolfScript)
PlasmaPower
6

Bash + coreutils, 99 byte

Entah saya benar-benar salah paham pertanyaannya ( jawaban @ lambruscoAcido memberikan hasil yang sangat berbeda ), atau ini adalah aplikasi regexp yang cukup mudah:

for((i=0;i<${#1};i++)){
a=${1:0:i}
b=${1:i+1}
egrep -i "^($a$b|$a.$b|$a.${1:i}|$1.)$" $2
}|sort -u

Keluaran:

$ ./similar.sh golf / usr / share / dict / words
Goff
emas
golf
golf
kesalahan
Teluk
serigala
Serigala
$ 
Trauma Digital
sumber
Bisakah Anda jelaskan apa yang ${a:b:c} harus dilakukan?
AL
1
@ n.1 dibutuhkan karakter pada posisi bke cdalam variabela
2
@professorfish Close - substring panjangnya cmulai dari posisi b(berbasis-nol) dari variabel a. Ekspansi substring adalah salah satu ekspansi parameter bash
Digital Trauma
2
@DigitalTrauma oh saya lupa meskipun saya tetap menggunakannya di golf Bash saya
3

Python 3, 291 karakter

Sangat mudah, dan karenanya tidak terlalu pintar. Tetapi dengan kusut generator yummy besar dan lambatnya dioptimalkan. Karena Anda tidak ingin membiarkan waktu perhitungan yang dialokasikan tidak digunakan, bukan?

from itertools import*
from sys import*
a=argv[1].lower()
r,l=range,len
n=l(a)
print('\n'.join((b for b in(s.strip()for s in open(argv[2]).readlines())if l(b)>n-2and b.lower()in(''.join(compress(a,(i!=j for j in r(n))))for i in r(n))or n==l(b)and sum(1for i in r(n)if a[i]!=b.lower()[i])<2)))
Evpok
sumber
1
Dapat menggunakan l=lendan r=rangemengurangi fungsi-fungsi tersebut lebih lanjut.
TyrantWave
1

Scala - 403 130

[Diperbarui]: sepenuhnya diperbarui karena solusi sebelumnya juga memungkinkan untuk surat yang diijinkan. Tidak menggunakan regex atau alat bawaan.

def f(x:String,d:List[String])={for{y<-d;c=(x zip y filter(t=>t._1!=t._2)length);n=y.length-x.length;if c<2&n==0|c==0&n==1}yield y

Tidak Disatukan:

def f(x:String, d:List[String]) = {
  for {
    y <- d
    c = (x zip y filter (t=>t._1!=t._2) length)  // #letter changes.
    n = y.length-x.length                        // Difference in word length.
    if c<2 & n==0 | c==0 & n==1
  } yield y
}

Pemakaian:

f("golf", io.Source.fromFile("/usr/share/dict/words").getLines.toList)
lambruscoAcido
sumber
@ DigitalTrauma Bisakah Anda memberi saya contoh untuk masalah itu?
lambruscoAcido
Saya mengerti: Saya juga mempertimbangkan semua permutasi dari surat-surat itu. Sigh - jadi kenyataannya lebih mudah. Terima kasih ...
lambruscoAcido
atechnytidak mengubah satu huruf. Solusi ini melakukan sesuatu yang tidak terkait dengan pertanyaan.
Konrad Borowski
+1. sepertinya itu sesuai dengan spesifikasi yang lebih baik sekarang ;-)
Digital Trauma
Program yang lengkap akan menyenangkan, bukan hanya berfungsi.
desir
1

Python, 174 karakter:

Cepat dan to the point.

import re;from sys import*;w=argv[1]
print"\n".join(set(sum([re.findall(r"\b%s%s?[^'\n]?%s\b"%(w[:i],w[i],w[i+1:]),open(argv[2]).read(),re.I)for i in range(len(w))],[]))-{w})

Contoh:

python similar.py golf /usr/share/dict/words

Keluaran:

goof
gola
gulf
gold
gol
gowf
goli
Golo
Gulf
goaf
Wolf
Goll
Rolf
wolf
goff
Gold

Saya kira file kata OS X hanya memiliki lebih banyak entri.

xleviator
sumber
Daftar tidak harus menyertakan kata itu sendiri dan juga tidak mengabaikan tanda kutip: dengan kamus UNIX juga golf'.
desir
Apa yang Anda maksud dengan mengabaikan tanda kutip? Setelah membaca ulang prompt, saya masih tidak mengerti apa maksud Anda.
xleviator
Jika saya menjalankan kode Anda di kamus dengan golf'itu, itu akan dicetak.
desir
Ah, saya salah membaca prompt, tapi sudah diperbaiki sekarang.
xleviator
0

Haskell - 219

import System.Environment
import Data.Char
u@(x:a)%w@(y:b)|x==y=a%b|1>0=1+minimum[a%w,u%b,a%b]
x%y=max(length x)$length y
main=do[w,d]<-getArgs;readFile d>>=mapM putStrLn.filter((==1).(%map toLower w).map toLower).words
desir
sumber
0

Rebol - 213

set[i d]split system/script/args" "r:[skip i | i skip]repeat n length? i[append r compose[|(poke s: split i 1 n 'skip s)|(head remove at copy i n)]]foreach w read/lines to-file d[if all[w != i parse w r][print w]]


Tidak disatukan (dengan beberapa komentar):

set [i d] split system/script/args " "

; build parse rule
r: [skip i | i skip]       ; RULE - one letter added (prefix and postfix)

; sub-rule for each letter in word
repeat n length? i [
    append r compose [
        | (poke s: split i 1 n 'skip s)     ; RULE - letter changed
        | (head remove at copy i n)         ; RULE - letter removed
    ]
]

foreach w read/lines to-file d [
    if all [w != i parse w r] [print w]
]

Contoh penggunaan (diuji dalam Rebol 3 pada OS X Lion):

$ rebol similar.reb golf /usr/share/dict/words
goaf
goff
gol
gola
Gold
gold
goli
Goll
Golo
goof
gowf
Gulf
gulf
Rolf
Wolf
wolf

Di bawah ini adalah parseaturan yang dibuat untuk mencocokkan kata yang mirip dengan golf :

[
    skip "golf"
  | "golf" skip
  | skip "o" "l" "f"
  | "olf"
  | "g" skip "l" "f"
  | "glf"
  | "g" "o" skip "f"
  | "gof"
  | "g" "o" "l" skip
  | "gol"
]
draegtun
sumber
-1

Python (103):

f=lambda x:[a for a in open('/usr/share/dict/words')if len(x)==len(a)&sum(b!=c for b,c in zip(a,x))==1]

Cukup efisien, saya pikir. Juga, saya suka seberapa bagus golf ini di Python.

ɐɔıʇǝɥʇu
sumber
Anda tidak memperhitungkan penghapusan atau penambahan karakter.
desir