Scambio di una lettera


18

Il più grande forum sul web, chiamato postcount ++, ha deciso di creare un nuovo gioco di forum. In questo gioco, l'obiettivo è pubblicare la parola, ma la parola deve avere una lettera aggiunta, rimossa o modificata. Il tuo capo voleva che tu scrivessi un programma che ottiene la parola e il dizionario UNIX, mentre lavori per un'azienda che ha un forum più intelligente con giochi di forum più intelligenti e vuole distruggere la concorrenza (ehi, è il tuo capo, non farlo discutere con lui, avrai comunque un sacco di soldi dal tuo lavoro).

Il tuo programma otterrà due argomenti, la parola e il dizionario. Poiché l'utente che gestisce il programma (sì, un utente, la tua azienda non ha risorse per eseguire i robot) non è perfetto, dovresti normalizzare il caso in entrambi. Le parole nel dizionario possono avere lettere ASCII (sia maiuscole che minuscole, ma devono essere ignorate durante il confronto), trattini, apostrofi e spazi non consecutivi nel mezzo. Non saranno più lunghi di 78 caratteri. Devi creare un elenco di parole che sarebbero accettate nel gioco, per spezzare il divertimento delle persone che pensano manualmente alle parole.

Questo è un esempio del tuo programma previsto, cercando parole simili a golf.

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

C'è /usr/share/dict/wordsun elenco di parole, con l'interruzione di riga dopo ciascuna. Puoi facilmente leggerlo con fgets (), ad esempio.

La società in cui lavori non ha molte schede perforate (sì, è il 2014 e usano ancora schede perforate), quindi non sprecarle. Scrivi il più breve programma possibile. Oh, e ti è stato chiesto di non usare implementazioni integrate o esterne della distanza di Levenshtein o algoritmi simili. Qualcosa su Non inventato Qui o backdoor che apparentemente il venditore ha inserito nella lingua (non ne hai la prova, ma non discuti con il tuo capo). Quindi, se vuoi la distanza, dovrai implementarla da solo.

Sei libero di usare qualsiasi lingua. Anche con le schede perforate, l'azienda ha accesso ai più moderni linguaggi di programmazione, come Cobol Ruby o Haskell o qualunque cosa tu voglia. Hanno anche GolfScript, se pensi che sia buono per la manipolazione delle stringhe (non lo so, forse ...).

Il vincitore ottiene 15 punti reputazione da me, e probabilmente molti altri punti dalla community. Le altre buone risposte riceveranno 10 punti e anche punti dalla comunità. Hai sentito che i punti sono inutili, ma molto probabilmente sostituiranno i dolar nel 2050. Tuttavia, ciò non è stato confermato, ma è comunque una buona idea ottenere punti.


6
Non dovremmo "utilizzare implementazioni integrate o esterne della distanza di Levenshtein o algoritmi simili"? Ecco la soluzione Mathematica a 30 caratteri.
Michael Stern,

@MichaelStern e un pitone altrettanto corto usando la corrispondenza fuzzy di questa libreria regex
Martin Ender


"come Ruby o Haskell" - ok, ce l'ho, vuoi che partecipi.
John Dvorak,

Fornisci un esempio migliore, in modo che vengano visualizzati tutti i tipi di modifiche o che le persone continuino a inviare algoritmi errati.
frizzante

Risposte:


4

GolfScript, 59 caratteri

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

Certo, GolfScript è ottimo per la manipolazione delle stringhe!

A cosa GolfScript non è così bravo è la gestione dell'I / O dei file o degli argomenti della riga di comando. Pertanto, questo programma prevede di ricevere tutto il suo input tramite stdin: la prima riga non vuota viene considerata la parola target, mentre le restanti righe dovrebbero contenere il dizionario. Su un sistema Unixish, puoi eseguire questo codice ad es. Con:

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

Sulla mia casella Ubuntu Linux, l'output del comando sopra è:

goff
wolf
gold
golfs
goof
gulf

Si noti che tutte le parole vengono convertite in minuscolo e tutti i duplicati vengono eliminati; quindi, a differenza del tuo output di esempio, il mio non viene elencato Wolfe wolfseparatamente. Sulla base della descrizione della tua sfida, presumo che questo sia accettabile.

Inoltre, il codice è molto lento, poiché utilizza un approccio di forza abbastanza bruta e non utilizza ottimizzazioni nemmeno ovvie come la verifica che la lunghezza della parola candidata corrisponda a quella della parola target ± 1. Tuttavia, riesce ad andare attraverso l' /usr/share/dict/wordselenco completo e non filtrato in ... um ... ti farò sapere quando finirà, ok?

Modifica: OK, ci sono voluti circa 25 minuti, ma è finito.


+1 per una rappresentazione accurata di quanto sia buono GolfScript per la manipolazione di stringhe (e per fare manipolazione di stringhe in GolfScript)
PlasmaPower

6

Bash + coreutils, 99 byte

O ho completamente frainteso la domanda ( la risposta di @ lambruscoAcido dà risultati molto diversi ), o questa è un'applicazione regexp abbastanza semplice:

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

Produzione:

$ ./similar.sh golf / usr / share / dict / words
Goff
oro
golf
golf
cantonata
golfo
lupo
Lupo
$ 

Puoi per favore spiegare cosa ${a:b:c} fare?
AL

1
@ n.1 prende i caratteri nelle posizioni bin cnella variabilea

2
@professorfish Close - è la sottostringa della lunghezza che cinizia dalla posizione b(a base zero) dalla variabile a. L'espansione del sottostringa è una delle espansioni dei parametri bash
Digital Trauma,

2
@DigitalTrauma oh ho dimenticato anche se continuo a usarlo nei miei golf Bash

3

Python 3, 291 caratteri

Molto semplice, e quindi non molto intelligente. Ma con un grande groviglio di generatore delizioso e una lentezza ottimizzata. Perché non vuoi lasciare inutilizzato il tempo di calcolo assegnato, vero?

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
Può usare l=lene r=rangeridurre ulteriormente tali funzioni.
TyrantWave,

1

Scala - 403 130

[Aggiornato]: completamente aggiornato perché la soluzione precedente consentiva anche lettere permutate. Non utilizza regex o altri strumenti integrati.

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
}

Uso:

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

@DigitalTrauma Puoi darmi un esempio per questo problema?
lambruscoAcido

Ho capito: ho anche considerato tutte le permutazioni delle lettere. Sospiro, quindi la realtà è più semplice. Grazie ...
lambruscoAcido

atechnynon cambia una lettera. Questa soluzione fa qualcosa di estraneo alla domanda.
Konrad Borowski,

+1. sembra che si adatti meglio alle specifiche ora ;-)
Digital Trauma

Un programma completo sarebbe bello, non solo funzione.
frizzante

1

Python, 174 caratteri:

Veloce e al punto.

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

Esempio:

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

Produzione:

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

Suppongo che il file di parole di OS X abbia solo più voci.


L'elenco non dovrebbe includere la parola stessa e inoltre non ignora gli apostrofi: anche con il dizionario UNIX golf'.
frizzante

Cosa intendi ignorando gli apostrofi? Dopo aver riletto il messaggio, non vedo ancora a cosa stai arrivando.
xleviator,

Se eseguo il codice sul dizionario con golf'esso, verrà stampato.
Swish

Ah, avevo letto male il prompt, ma ora è stato risolto.
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

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 (con alcuni commenti):

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

Esempio di utilizzo (testato in Rebol 3 su 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 seguito è riportata la parseregola creata per abbinare parole simili al 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"
]

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

Abbastanza efficiente, penso. Inoltre, mi piace quanto sia stato bello giocare a golf in Python.


Non conto per la rimozione o l'aggiunta di un personaggio.
frizzante
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.