One Letter Swap

18

Das größte Forum im Internet namens postcount ++ hat beschlossen, ein neues Forum-Spiel zu entwickeln. In diesem Spiel besteht das Ziel darin, das Wort zu veröffentlichen, es muss jedoch ein Buchstabe hinzugefügt, entfernt oder geändert werden. Ihr Chef wollte, dass Sie ein Programm schreiben, das das Wort bekommt, und das UNIX-Wörterbuch, während Sie für Unternehmen arbeiten, die intelligentere Foren mit intelligenteren Forenspielen haben und die Konkurrenz zerstören möchten (hey, es ist Ihr Chef, nicht wahr?) Wenn Sie mit ihm sprechen, bekommen Sie ohnehin viel Geld von Ihrem Job.

Ihr Programm erhält zwei Argumente, das Wort und das Wörterbuch. Da der Benutzer, der das Programm verwaltet (ja, ein Benutzer, Ihr Unternehmen verfügt nicht über Ressourcen, um Bots auszuführen), nicht perfekt ist, sollten Sie den Fall in beiden Fällen normalisieren. Die Wörter im Wörterbuch können ASCII-Buchstaben (Groß- und Kleinbuchstaben, die beim Vergleich ignoriert werden sollten), Bindestriche, Apostrophe und nicht aufeinanderfolgende Leerzeichen in der Mitte enthalten. Sie dürfen nicht länger als 78 Zeichen sein. Sie müssen eine Liste von Wörtern ausgeben, die im Spiel akzeptiert werden, um den Spaß von Leuten zu unterbrechen, die manuell an Wörter denken.

Dies ist ein Beispiel für Ihr erwartetes Programm, das nach ähnlichen Wörtern sucht wie golf.

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

Dies /usr/share/dict/wordsist eine Liste von Wörtern, nach denen jeweils ein Zeilenumbruch erfolgt. Das kann man zum Beispiel mit fgets () leicht lesen.

Das Unternehmen, in dem Sie arbeiten, verfügt nicht über viele Lochkarten (ja, es ist 2014, und es werden immer noch Lochkarten verwendet). Verschwenden Sie sie also nicht. Schreiben Sie so kurz wie möglich. Oh, und Sie wurden gebeten, keine eingebauten oder externen Implementierungen von Levenshtein distance oder ähnlichen Algorithmen zu verwenden. Etwas über Not Invented Here oder Hintertüren, die anscheinend vom Anbieter in die Sprache eingefügt wurden (Sie haben keine Beweise dafür, sprechen aber nicht mit Ihrem Chef darüber). Wenn Sie also Distanz wollen, müssen Sie diese selbst implementieren.

Sie können jede Sprache verwenden. Selbst mit Lochkarten hat das Unternehmen Zugriff auf modernste Programmiersprachen wie Cobol Ruby oder Haskell oder was auch immer Sie wollen. Sie haben sogar GolfScript, wenn Sie denken, dass es für die Manipulation von Saiten gut ist (ich weiß es vielleicht nicht ...).

Der Gewinner erhält 15 Reputationspunkte von mir und wahrscheinlich viele andere Punkte von der Community. Die anderen guten Antworten erhalten 10 Punkte und auch Punkte von der Community. Sie haben gehört, dass Punkte wertlos sind, aber höchstwahrscheinlich werden sie im Jahr 2050 die Gelehrten ersetzen. Das wurde jedoch nicht bestätigt, aber es ist eine gute Idee, Punkte zu sammeln.

Konrad Borowski
quelle
6
Wir sollten nicht "eingebaute oder externe Implementierungen von Levenshtein-Abstand oder einem ähnlichen Algorithmus verwenden"? Da ist die 30-stellige Mathematica-Lösung.
Michael Stern
@MichaelStern und eine ähnlich kurze Python-Version mit dem Fuzzy-Matching dieser Regex-Bibliothek
Martin Ender
2
Fast das gleiche wie codegolf.stackexchange.com/questions/6939/… .
Howard
"wie Ruby oder Haskell" - ok, ich habe es verstanden, du willst, dass ich mitmache.
John Dvorak
Bitte geben Sie ein besseres Beispiel an, damit alle Arten von Änderungen angezeigt werden oder die Leute weiterhin falsche Algorithmen einreichen.
Swish

Antworten:

4

GolfScript, 59 Zeichen

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

Natürlich eignet sich GolfScript hervorragend zur Manipulation von Saiten!

Was GolfScript nicht so gut kann, ist der Umgang mit Datei-E / A oder Befehlszeilenargumenten. Daher erwartet dieses Programm, dass alle Eingaben über stdin empfangen werden: Die erste nicht leere Zeile wird als Zielwort angenommen, während die verbleibenden Zeilen das Wörterbuch enthalten sollten. Auf einem Unixish-System können Sie diesen Code ausführen, z. B .:

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

Auf meiner Ubuntu Linux-Box lautet die Ausgabe des obigen Befehls:

goff
wolf
gold
golfs
goof
gulf

Beachten Sie, dass alle Wörter in Kleinbuchstaben umgewandelt werden und alle Duplikate beseitigt werden. Daher listet mine im Gegensatz zu Ihrer Beispielausgabe nicht Wolfund wolfseparat auf. Aufgrund Ihrer Beschreibung der Herausforderung gehe ich davon aus, dass dies akzeptabel ist.

Außerdem ist der Code sehr langsam, da er einen ziemlich brachialen Ansatz verwendet und nicht einmal offensichtliche Optimierungen wie die Überprüfung, ob die Länge des Kandidatenworts mit der des Zielworts ± 1 übereinstimmt durch die vollständige, ungefilterte /usr/share/dict/wordsListe in ... ähm ... lass es dich wissen, wenn es fertig ist, OK?

Bearbeiten: OK, es dauerte etwa 25 Minuten, aber es wurde beendet.

Ilmari Karonen
quelle
+1 für eine genaue Darstellung, wie gut GolfScript für die Manipulation von Saiten (und die Durchführung von Saiten-Manipulation in GolfScript) ist
PlasmaPower
6

Bash + Coreutils, 99 Bytes

Entweder habe ich die Frage völlig falsch verstanden ( die Antwort von @ lambruscoAcido liefert sehr unterschiedliche Ergebnisse ), oder dies ist eine ziemlich einfache Regexp-Anwendung:

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

Ausgabe:

$ ./similar.sh golf / usr / share / dict / words
Goff
Gold
Golf
Golf
doof
Golf
Wolf
Wolf
$ 
Digitales Trauma
quelle
Können Sie bitte erklären, was zu ${a:b:c} tun ist?
AL
1
@ n.1 es nimmt die Zeichen an den Positionen bauf cin der Variablena
2
@professorfish Close - Dies ist die Teilzeichenfolge der Länge cab der Position b( nullbasiert ) der Variablen a. Die Substring-Erweiterung ist eine der Bash-Parameter-Erweiterungen
Digital Trauma
2
@DigitalTrauma oh, ich habe vergessen, obwohl ich es weiterhin in meinen Bash-Golfspielen verwende
3

Python 3, 291 Zeichen

Sehr unkompliziert und daher nicht sehr schlau. Aber mit einem großen leckeren Generatorgewirr und optimierter Langsamkeit. Weil Sie Ihre zugewiesene Rechenzeit nicht ungenutzt lassen möchten, oder?

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
quelle
1
Kann diese Funktionen nutzen l=lenund r=rangeweiter reduzieren.
TyrantWave
1

Scala - 403 130

[Aktualisiert]: Vollständig aktualisiert, da die vorherige Lösung auch permutierte Buchstaben zulässt. Verwendet kein Regex oder eingebaute Werkzeuge.

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
}

Verwendung:

f("golf", io.Source.fromFile("/usr/share/dict/words").getLines.toList)
lambruscoAcido
quelle
@DigitalTrauma Kannst du mir ein Beispiel für dieses Problem geben?
LambruscoAcido
Ich habe es verstanden: Ich habe auch alle Permutationen der Buchstaben berücksichtigt. Seufz - so fällt die Realität leichter. Vielen Dank ...
LambruscoAcido
atechnyändert keinen Buchstaben. Diese Lösung hat nichts mit der Frage zu tun.
Konrad Borowski
+1. sieht aus wie es passt die Spezifikation jetzt besser ;-)
Digital Trauma
Ein komplettes Programm wäre schön, nicht nur zu funktionieren.
Swish
1

Python, 174 Zeichen:

Schnell und auf den Punkt.

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

Beispiel:

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

Ausgabe:

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

Ich nehme an, dass die OS X-Wortdatei nur mehr Einträge enthält.

xleviator
quelle
Die Liste sollte kein Wort selbst enthalten und ignoriert auch keine Apostrophe: mit dem UNIX-Wörterbuch hat sie auch golf'.
Swish
Was meinst du damit, Apostrophe zu ignorieren? Nach dem erneuten Lesen der Eingabeaufforderung sehe ich immer noch nicht, worauf Sie hinaus wollen.
Xleviator
Wenn ich Ihren Code auf Wörterbuch mit golf'darin laufen lasse , wird es gedruckt.
Swish
Ah, ich hatte die Aufforderung falsch verstanden, aber sie ist jetzt behoben.
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
Swish
quelle
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]]


Ungolfed (mit einigen Kommentaren):

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

Anwendungsbeispiel (getestet in Rebol 3 unter 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

Nachfolgend finden Sie die parseRegel, die erstellt wurde, um ähnliche Wörter wie Golf zu finden :

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

Sehr effizient, denke ich. Außerdem gefällt mir, wie gut das in Python gespielt hat.

ɐɔıɐɔuʇǝɥʇs
quelle
Sie berücksichtigen nicht das Entfernen oder Hinzufügen eines Charakters.
Swish