Bir Harf Takas


18

Web'deki en büyük forum olan postcount ++ denilen yeni bir forum oyunu yapmaya karar verdi. Bu oyunda amaç, kelimeyi yayınlamaktır, ancak kelimenin bir harf eklenmesi, kaldırılması veya değiştirilmesi gerekir. Patronunuz, daha akıllı forum oyunlarına sahip daha akıllı bir forumu olan ve rekabeti yok etmek isteyen şirket için çalışırken, kelimeyi alan bir program ve UNIX sözlüğünü yazmanızı istedi (hey, bu sizin patronunuz, yapma onunla tartış, işinden zaten çok para alıyorsun).

Programınız iki argüman alacak, kelime ve sözlük. Programı yöneten kullanıcı (evet, bir kullanıcı, şirketinizin botları çalıştırmak için kaynakları yok) mükemmel olmadığından, her ikisinde de durumu normalleştirmelisiniz. Sözlükteki sözcükler ASCII harfleri (hem büyük hem de küçük harf olabilir, ancak karşılaştırma sırasında göz ardı edilmelidir), tire, kesme işareti ve ortada ardışık olmayan boşluklar içerebilir. 78 karakterden uzun olmayacaklar. Manuel olarak kelimeleri düşünen insanların eğlencesini kırmak için oyunda kabul edilecek kelimelerin listesini çıkarmalısınız.

Bu, benzer kelimeleri kontrol ederek beklenen programınıza bir örnektir golf.

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

/usr/share/dict/wordsHer sonra satır sonu ile kelimelerin bir listesidir. Örneğin, fgets () ile bunu kolayca okuyabilirsiniz.

Çalıştığınız şirketin çok fazla yumruk kartı yok (evet, 2014 ve hala delikli kart kullanıyorlar), bu yüzden onları boşa harcamayın. Mümkün olduğunca kısa bir program yazın. Oh, ve sizden Levenshtein mesafesinin yerleşik veya harici uygulamalarını veya benzer bir algoritmayı kullanmamanız istendi. Burada ya da arkada, satıcının dile yerleştirdiği bir şey var (bunların kanıtı yok, ancak patronunuzla tartışmayın). Yani mesafe istiyorsanız, bunu kendiniz uygulamak zorunda kalacaksınız.

Herhangi bir dili kullanmakta özgürsünüz. Delikli kartlarda bile, şirket Cobol Ruby veya Haskell gibi modern programlama dillerinin çoğuna veya istediğiniz her şeye erişebilir . Dizgi manipülasyonu için iyi olduğunu düşünüyorsanız, GolfScript bile var (bilmiyorum, belki ...).

Kazanan benden 15 itibar puanı ve muhtemelen topluluktan birçok puan alır. Diğer iyi cevaplar 10 puan alacak ve topluluktan puan alacak. Puanların değersiz olduğunu duydunuz, ancak büyük olasılıkla 2050'de dolarların yerini alacaklar. Ancak bu doğrulanmadı, ancak yine de puan almak iyi bir fikir.


6
"Levenshtein mesafesinin yerleşik veya harici uygulamalarını veya benzer bir algoritmayı kullanmamalıyız?" 30 karakterlik Mathematica çözümü var.
Michael Stern

@MichaelStern ve benzer şekilde kısa bir python olanı bu regex kütüphanesinin
Martin Ender


"Ruby veya Haskell gibi" - tamam, anladım, katılmamı istiyorsun.
John Dvorak

Lütfen daha iyi bir örnek verin, böylece her türlü değişiklik görünebilir veya kullanıcılar yanlış algoritmalar göndermeye devam eder.
swish

Yanıtlar:


4

GolfScript, 59 karakter

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

Tabii, GolfScript dize manipülasyonu için harika !

GolfScript'in bu kadar iyi olmadığı şey, dosya G / Ç veya komut satırı bağımsız değişkenlerini işlemektir. Bu nedenle, bu program tüm girdilerini stdin yoluyla almayı bekler: ilk boş olmayan satır hedef sözcük olarak alınırken, kalan satırlar sözlüğü içermelidir. Unixish sisteminde, bu kodu aşağıdakilerle çalıştırabilirsiniz:

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

Ubuntu Linux kutumda yukarıdaki komutun çıktısı:

goff
wolf
gold
golfs
goof
gulf

Tüm kelimelerin küçük harfe dönüştürüldüğünü ve tüm kopyaların elendiğini unutmayın; Böylece, örnek çıktı aksine, maden listelemiyor Wolfve wolfayrı ayrı. Meydan okuma açıklamanıza dayanarak, bunun kabul edilebilir olduğunu varsayıyorum.

Ayrıca, kod oldukça yavaştır, çünkü oldukça kaba bir güç yaklaşımı kullanır ve aday kelimenin uzunluğunun hedef kelime ± 1 ile eşleştiğini kontrol etmek gibi bariz optimizasyonlar bile kullanmaz. Yine de, gitmeyi başarıyor Filtrelenmemiş /usr/share/dict/wordslistenin tamamında ... um ... bittiğinde size haber vereceğim, tamam mı?

Düzenleme: Tamam, yaklaşık 25 dakika sürdü, ama bitti.


+1, GolfScript'in dize manipülasyonu için ne kadar iyi olduğunun doğru bir temsili için (ve GolfScript'te dize manipülasyonu yapıyor)
PlasmaPower

6

Bash + coreutils, 99 bayt

Ya soruyu tamamen yanlış anladım ( @ lambruscoAcido'nun cevabı çok farklı sonuçlar veriyor ) veya bu oldukça basit bir regexp uygulaması:

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

Çıktı:

golf / usr / share / dict / words
Goff
altın
golf
çoraplar
becerememek
körfez
Kurt
Kurt
$ 

Ne ${a:b:c} yaptığını açıklar mısınız?
AL

1
@ n.1 o pozisyonlarda karakterleri alır biçin cdeğişken içindea

2
@professorfish Kapat - değişkenten (sıfır tabanlı) ckonumdan başlayan uzunluk alt dizesi . Alt dize genişletmesi bash parametre genişletmelerinden biridirba
Dijital Travma

2
@DigitalTrauma oh Bash

3

Python 3, 291 karakter

Çok basit ve bu yüzden çok zeki değil. Ama büyük bir nefis jeneratör arapsaçı ve optimize yavaşlık ile. Tahsis edilen hesaplama sürenizi kullanılmadan bırakmak istemediğiniz için, öyle mi?

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

1
Bu işlevleri daha da azaltmak için kullanabilir l=lenve kullanabilir r=range.
TyrantWave

1

Scala - 403 130

[Güncelleme]: Tamamen güncellendi çünkü eski çözüm izin verilen harflere de izin verdi. Normal ifade veya herhangi bir yerleşik araç kullanmaz.

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

Ungolfed:

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
}

Kullanımı:

f("golf", io.Source.fromFile("/usr/share/dict/words").getLines.toList)

@DigitalTrauma Bana bu konuda bir örnek verebilir misiniz?
lambruscoAcido

Anladım: Harflerin tüm permütasyonlarını da düşündüm. İç çeker - böylece gerçek daha kolaydır. Teşekkürler ...
lambruscoAcido

atechnybir harf değiştirmez. Bu çözüm, soru ile ilgisi olmayan bir şey yapar.
Konrad Borowski

+1. şimdi spec daha iyi uyuyor gibi görünüyor ;-)
Dijital Travma

Tam bir program sadece işlev değil, iyi olurdu.
swish

1

Python, 174 karakter:

Hızlı ve doğru.

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

Misal:

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

Çıktı:

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

OS X kelimeler dosyasının sadece daha fazla girişi olduğunu varsayalım.


Liste, kelimenin kendisini içermemelidir ve ayrıca kesme işaretlerini yok saymaz: UNIX sözlüğü ile de vardır golf'.
swish

Kesme işaretlerini yoksayarak ne demek istiyorsun? İstemi tekrar okuduktan sonra, hala ne elde ettiğinizi göremiyorum.
xleviator

Kodunuzu sözlükte onunla birlikte çalıştırırsam, golf'yazdırılacaktır.
swish

Ah, istemi yanlış anladım, ama şimdi düzeltildi.
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

0

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


Ungolfed (bazı yorumlarla birlikte):

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

Kullanım örneği (OS X Lion'da Rebol 3'te test edilmiştir):

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

Golf ileparse benzer kelimeleri eşleştirmek için oluşturulan kural aşağıdadır :

[
    skip "golf"
  | "golf" skip
  | skip "o" "l" "f"
  | "olf"
  | "g" skip "l" "f"
  | "glf"
  | "g" "o" skip "f"
  | "gof"
  | "g" "o" "l" skip
  | "gol"
]

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

Bence oldukça verimli. Ayrıca, bu Python golf ne kadar iyi gibi.


Karakter kaldırmayı veya eklemeyi hesaba katmazsınız.
swish
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.