Ode Golf - Usuwanie liter

17

Biorąc pod uwagę plik słownika (plik tekstowy zawierający słowo lub frazę w każdym wierszu, z możliwą interpunkcją, ale bez liczb; wiersze są alfabetycznie), musisz wyprowadzić każdą kombinację słów, w której jedną literę można usunąć ze słowa, aby utworzyć drugą; usunięta litera powinna być ujęta w nawiasy.

Na przykład dane wejściowe

cat
cart
code
golf
ode
verify
versify

powinien dać wynik

ca(r)t
(c)ode
ver(s)ify

Wiele sposobów uzyskania tej samej pary można wyświetlić tylko raz. Możesz wyprowadzać scra(p)pedlub scrap(p)ed, ale nie oba jednocześnie.

Wyjście powinno być uporządkowane alfabetycznie według dłuższego wpisu;

mart
mar
mat
ma

powinien mieć wynik

ma(r)
ma(t)
ma(r)t
mar(t)

a dwa ostatnie mogą być w dowolnej kolejności.

Plik słownika może zawierać wielkie litery, spacje, łączniki lub apostrofy; należy je zignorować. Na przykład,

inlay 
in-play

powinien produkować in(p)lay. Twój wynik powinien być w tym samym przypadku. Dozwolone są dodatkowe białe znaki.

Dane wejściowe mogą być STDIN lub z pliku; jest oddzielony znakami nowej linii. Wyjściem może być wartość zwracana przez funkcję lub STDOUT (lub zapisana do pliku, jeśli chcesz).

To jest , więc wygrywa najkrótszy kod w bajtach.

(To moje pierwsze wyzwanie na PPCG - daj mi znać, jeśli zrobiłem coś złego, a ja to naprawię.)

Deusovi
źródło
3
Jaka powinna być wydajność mart mar mat ma? Czy by to mar(t) ma(r)t ma(r) ma(t)bylo
Sp3000,
@Sp: Zapomniałem określić zamówienie - edytowane w celu wyjaśnienia.
Deusovi
W pierwszym przykładzie słowo golf nie znajduje się w wynikach. Czy to dlatego, że to słowo, które nie ma innych kombinacji?
LukStorms
@Luk: Tak! W przypadku większości plików słowników będzie wiele słów, które w ogóle nie tworzą innych słów - nie powinny one pojawiać się nigdzie w wynikach.
Deusovi
2
Co powiesz na zezwolenie na funkcję z (dużym) parametrem łańcucha, zwracanie żądanego wyniku jako tablicy łańcucha? Dzięki temu skupiono się na algorytmie, unikając konieczności zarządzania we / wy pliku.
edc65

Odpowiedzi:

1

Perl -an0, 101 + 3 bajty

@F=sort{length$a<=>length$b}map{s/\W//g;lc}@F;map{$`.$'~~@F?print"$`($1)$'\n":$\while/(.)(?!\1)/g}@F;

gdzie

  • @Fto słownik przechowywany w tablicy, dostarczany przez magię flagi środowiska wykonawczego. (b-oost, BoO # @% @ # $% $ # @ T)
  • map{s/\W//g;lc}@Fusuwa wszystkie symbole ze słów i zamienia wszystko małymi literami. (boost, boot)
  • sort{length$b<=>length$a}sortuje według długości. (boot, boost)
  • map{ (...) while/(.)(?!\1)/g}@Fdopasowuje wszystkie znaki, po których nie występuje ten sam znak ([b] oot, bo [o] t, boo [t], ...)
  • print"$`($1)$'\n"drukuje części poprzedzające, nawiasowane i udane dopasowanie ... (boo (s) t)
  • if $`.$'~~@F... jeśli łączenie wszystkiego przed i po meczu znajduje się w słowniku. ([podnieść])
bopjesvla
źródło
5

JavaScript (ES6), 225

Funkcja z parametrem ciągu, brak danych wejściowych z pliku. Zapytałem OP, czy to może być ważne.

Przetestuj uruchomienie fragmentu w przeglądarce zgodnej z EcmaScript 6 (implementacja funkcji strzałek, ciągu szablonu, operatora rozprzestrzeniania - Firefox, może Safari lub MS Edge, a nie Chrome)

f=t=>t.split`
`.map(w=>(d[k=w.replace(/\W/g,'').toLowerCase()]={},k),d={},r=[]).map(w=>[...w].map((c,i,v)=>(d[v[i]='',x=v.join``]&&!d[x][w]&&r.push(d[x][w]=(v[i]=`(${c})`,v.join``)),v[i]=c)))&&r.sort((a,b)=>a.length-b.length)

// LESS GOLFED

Q=t=>{
  // convert to canonical form and put in a dictionary
  // each value in the dictionary is an hashtable tha will store the list
  // of words that can generate the current word, removing a letter
  d={},
  t=t.split`\n`.map(w=>(k=w.replace(/\W/g,'').toLowerCase(),d[k]={},k))
  r=[], // result array 
  t.forEach(w =>
    [...w].forEach((c,i,v)=>( // for each letter in word, try to remove
      v[i]='', x=v.join``, // build string with missing letter
      v[i]='('+c+')', y=v.join``, // and build string with brackets
      v[i]=c, // restore the current letter
      d[x] && // if the word with removed letter is present in the dictionary
      !d[x][w] && // and not already from the same generating word
         r.push(d[x][w]=y) // update dictionary and add word to result array
    ))
  )
  return r.sort((a,b)=>a.length-b.length) // sort result by length
}  

// TEST
function test() { R.innerHTML=f(I.value) }
textarea { height: 20em }
Test <button onclick="test()">-></button>
<span id=R></span>
<br><textarea id=I>cat
cart
code
golf
node
scraped
scrapped
verify
versify
mart
mar
mat
ma</textarea>

edc65
źródło
@ETHproductions right, thx
edc65
3

Ruby, 173

->d{o=[]
c={}
d=d.sort_by{|w|[w.size,w]}.map{|w|w=w.upcase.gsub /[^A-Z]/,''
c[w]=l=1
w.size.times{|i|p,x,s=w[0...i],w[i],w[i+1..-1]
c[p+s]&&l!=x&&o<<p+"(#{w[i]})"+s
l=x}}
o}

Przetestuj tutaj: http://ideone.com/86avbe

Wersja do odczytu tutaj: http://ideone.com/ynFItB

Cristian Lupascu
źródło
Na telefonie komórkowym, więc nie mogę teraz testować - czy mógłbyś dodać walizkę testową dla SCRAPPED / SCRAPED?
Deusovi
@Deusovi Ten przypadek nie działa poprawnie. Naprawiam to teraz ...
Cristian Lupascu
@Deusovi Zaktualizowano!
Cristian Lupascu
Ta odpowiedź nie zapewnia poprawnego wyniku np ['jacklantern','jackslantern','jack-o-lantern']. Dla nagrania.
14mRh4X0r
1
@ 14mRh4X0r nie może znaleźć tej prośby w pytaniu ... The output should be ordered by the longer entry;...and the latter two could be in either order.
edc65
1

Ruby, 211

Postanowiłem zastosować inne podejście do rozwiązania tego problemu, używając wyrażenia regularnego.

->d{o=[]
d.map{|x|x.upcase!.gsub! /[-' ]/,''}
d.map{|x|(x.size+1).times{|i|o+=d.map{|w|w.b.sub! /(#{x[0...i]})(.)(#{x[i..-1]})/,'\1(\2)\3'if w[i]!=w[i+1]}}}
o.compact.sort_by{|w|[w.size,w.gsub(/[()]/,'')]}.uniq}
14mRh4X0r
źródło
0

Perl 5, 210

Kod ładuje dane wejściowe do posortowanej tablicy i sprawdza każdą wartość względem wszystkich wartości w tablicy, które są o 1 bajt dłuższe.

map{@W=split//,$w=$_;map{@X=split//,$x=$_;if(@W+1==@X){$i=0;while($W[$i]eq$X[$i]&&$i<@W){$i++}$c=$X[$i];$e=substr($w,$i);print substr($w,0,$i)."($c)$e\n",if substr($x,$i+1)eq$e}}@D}@D=sort(map{s/[^\w]//g;lc}<>)

Test

$ perl dictionairy_same_words.pl dictionairywords.txt
ca(r)t
in(p)lay
ma(r)
ma(t)
mar(t)
ma(r)t
(c)ode
ver(s)ify
LukStorms
źródło
0

Haskell, 201 bajtów

import Data.List
import Data.Char
a#(b:c)=(a,b,c)
g a=[l++'(':m:')':n|x<-a,((l,m,n):_)<-[[o|o@(i,j,k)<-zipWith(#)(inits x)$init$tails x,elem(i++k)a]]]
f=sortOn length.g.map(filter isLetter.map toLower)

Nie jestem pewien, jaki format wejściowy jest dozwolony. fpobiera listę ciągów znaków. Jeśli dozwolony jest tylko jeden ciąg (z nl oddzielnymi słowami), dodaj .linesdo f(+6 bajtów).

Przykład użycia:

f ["cat","cart","code","golf","od-e","verify","versify","on","s-o-n","Scrapped","scraped"]

["(s)on","ca(r)t","(c)ode","ver(s)ify","scra(p)ped"]

Jak to działa: zmień każde słowo na małe i zachowaj tylko litery. Podziel każde słowo xna dwie części w każdej możliwej pozycji i potrój trzy razy, (i,j,k)gdzie ijest pierwsza część, jto pierwszy znak drugiej części i kogon drugiej części. Zachowaj trójki tam, gdzie i++kpojawia się również na liście słów. Jeśli ta lista nie jest pusta, weź pierwszy element i wywołaj go (l,m,n). Zamień wszystkie te nagłówki list do wymaganego formatu wyjściowego, otaczając mgo ()i umieszczając pomiędzy li n.

nimi
źródło