Word Spinner Puzzle


10

Questo è un puzzle di parole.

Il tuo programma dovrebbe accettare due parole sull'input standard.
La prima parola è la parola iniziale. La parola due è la parola finale.

Dalla parola iniziale devi raggiungere la parola finale cambiando / aggiungi / rimuovi una lettera alla volta. Dopo ogni modifica deve formare una nuova parola valida. Le lettere aggiunte vengono aggiunte all'inizio o alla fine. Puoi rimuovere le lettere da qualsiasi posizione (ma la parola non deve contenere più di tre lettere). Nota: non è possibile riorganizzare le lettere per formare una parola.

L'output del programma è la sequenza di parole da ottenere dalla parola iniziale alla parola finale.

Esempio:

Input:
    Post Shot

Output:
    Post
    cost
    coat
    goat
    got
    hot
    shot

Vincitore:

  • Il programma deve essere eseguito in un tempo ragionevole (meno di 10 secondi).
  • Il programma in grado di generare la sequenza di output più breve per le parole premio.
    • Zink -> Silicio
  • Se più di un programma ottiene la sequenza più breve, il programma più breve in caratteri (ignorando gli spazi bianchi).
  • Se abbiamo ancora più di una data / ora di invio del programma, verranno utilizzati.

Appunti:


potrebbe essere "post-> pot-> hot-> shot" è più breve.
TU

@ S.Mark: Quindi il tuo algoritmo batte il mio e tu vinci. Quanto sopra è un esempio di una possibile soluzione. Una soluzione più breve batte una soluzione più lunga.
Martin York,

intenzionalmente? scusa, ho appena sbagliato.
TU

2
Potrei risolverlo in Whitespace per 0 dimensioni del programma?

@Tim Nordenfur: mi piacerebbe vedere un'implementazione di spazi bianchi. Nota. ci sono due regole prima della durata del programma per decidere il vincitore. Ma se soddisfi questi requisiti :-)
Martin York,

Risposte:


2

Python, 288 caratteri

(senza contare la riga di lettura del dizionario)

X=set(open('websters-dictionary').read().upper().split())

(S,E)=raw_input().upper().split()
G={S:0}
def A(w,x):
 if x not in G and x in X:G[x]=w
while E not in G:
 for w in G.copy():
  for i in range(len(w)):
   for c in"ABCDEFGHIJKLMNOPQRSTUVWXYZ":A(w,w[:i]+c+w[i+1:]);A(w,w[:i]+w[i+1:]);A(w,c+w);A(w,w+c)
s=''
while E:s=E+'\n'+s;E=G[E]
print s

per la sfida zinkdi silicon:

ZINK
PINK
PANK
PANI
PANIC
PINIC
SINIC
SINICO
SILICO
SILICON

Ci sono alcune strane parole in quel dizionario ...


In realtà non ho controllato il contenuto. Ho appena provato a trovare un dizionario che tutti possano usare.
Martin York,

prova con guester overturn(richiede del tempo) o regatta gyrally(non ritorna) ;-)
Arnaud Le Blanc,

Sì, alcune combinazioni richiedono del tempo. Il tempo si allunga man mano che la soluzione più breve aumenta. E l'ultimo non ha soluzione - non ci sono specifiche su cosa dovrebbe succedere in quel caso :) È abbastanza facile modificarlo per gestirlo però (salva un handle in G.copy () e confronta G con esso alla fine del loop ).
Keith Randall,

16

traceroute - 10 caratteri

traceroute 

dettaglio

post#traceroute shot

Type escape sequence to abort.
Tracing the route to shot (1.1.4.2)

  1 pot (1.1.1.2) 40 msec 68 msec 24 msec
  2 hot (1.1.3.2) 16 msec 32 msec 24 msec
  3 shot (1.1.4.2) 52 msec *  92 msec

I router sono preconfigurati con OSPF abilitato e organizzato in questo modo.

inserisci qui la descrizione dell'immagine

E sì, ho bisogno di 233614 router per supportare completamente tutte le parole. :-)


Molto intelligente ma fallisci la regola dei 10 secondi. Ci vorranno eccessivamente più di 10 secondi per configurare tutti i router. :-) Qual è il percorso da: Zink -> Silicon
Martin York,

@Martin, si prega di essere ignorato per il tempo di configurazione, è proprio come costruire un dizionario, heheh, rotte per Zink -> Silicon è zink->pink->pank->pani->panic->pinic->sinic->sinico->silico->siliconche sto davvero provando con l'algoritmo Dijkstra (che viene utilizzato in OSPF) e può trovare quel percorso intorno a 1s, lo farò pubblicarlo in un post separato più tardi, una volta che ho giocato a golf.
TU

3

PHP - 886 689 644 612

Caricamento dizionario:

<?php foreach(file('websters-dictionary') as $line) {
    $word = strtolower(trim($line));
    if (strlen($word) < 3) continue;
    $c[$word] = 1;
}

Codice effettivo (basta concedere entrambi):

list($d,$e)=explode(' ',strtolower(trim(`cat`)));$f=range(@a,@z);function w($a,&$g){global$c;if(isset($c[$a]))$g[]=$a;}$h[$d]=$b=@levenshtein;$i=new SplPriorityQueue;$i->insert($d,0);$j[$d]=0;$k[$d]=$b($d,$e);while($h){if(isset($c[$l=$i->extract()])){unset($h[$l],$c[$l]);if($l==$e){for(;$m=@$n[$o[]=$l];$l=$m);die(implode("\n",array_reverse($o)));}for($p=strlen($l),$g=array();$p--;){w(substr_replace($q=$l,"",$p,1),$g);foreach($f as$r){$q[$p]=$r;w($q,$g);w($r.$l,$g);w($l.$r,$g);}}foreach($g as$m){$s=$j[$l]+1;if(!isset($h[$m])||$s<$j[$m]){$n[$m]=$l;$i->insert($m,-(($k[$m]=$b($m,$e))+$j[$m]=$s));}$h[$m]=1;}}}

utilizzo:

php puzzle.php <<< 'Zink Silicon'
# or
echo 'Zink Silicon'|php puzzle.php

Risultato:

zink
pink
pank
pani
panic
pinic
sinic
sinico
silico
silicon
(0.23s)

Questo dovrebbe funzionare in meno di 0,5 secondi per "Zink Silicon", e meno di 1 secondo per la maggior parte dei casi (a volte più a lungo quando non esiste una soluzione, ma il davanzale ritorna).

Questo utilizza l' algoritmo A * con la distanza di levenshtein per stimare un limite inferiore delle distanze.

Alcuni test interessanti:

  • vas arm -> vas bas bar barm arm (con una parola più lunga di inizio e fine)
  • oxy pom -> oxy poxy poy pom
  • regatta gyrally -> (nessuno, ma lo script termina correttamente)
  • aal presolution -> +8 caratteri
  • lenticulated aal -> -9 caratteri
  • acarology lowness -> 46 luppoli
  • caniniform lowness -> 51 luppoli
  • cauliform lowness -> 52 luppolo
  • overfoul lowness -> 54 luppoli
  • dance facia -> alcune parole nel percorso hanno 4 caratteri in più di entrambi inizio / fine

Prova Zink Silicon
Martin York l'

Ora dovrebbe funzionare :-)
Arnaud Le Blanc,

Troverò una macchina più grande:PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 71 bytes)
Martin York,

Hai appena toccato l'impostazione 128M memory_limit ;-) Prova con php -dmemory_limit=256M.
Arnaud Le Blanc,

had->handnon è una mossa valida, puoi solo aggiungere una lettera all'inizio o alla fine. Lo stesso vest->verstvale per :-)
Arnaud Le Blanc,

3

Pitone

Dal momento che non potevo golf di codici dijkstra per comprimere in poche centinaia di byte, ecco la mia versione non golfata.

import sys, heapq, time

# dijkstra algorithm from 
# http://code.activestate.com/recipes/119466-dijkstras-algorithm-for-shortest-paths/
def dijkstra(G, start, end):
   def flatten(L):
      while len(L) > 0:
         yield L[0]
         L = L[1]

   q = [(0, start, ())]
   visited = set()
   while True:
      (cost, v1, path) = heapq.heappop(q)
      if v1 not in visited:
         visited.add(v1)
         if v1 == end:
            return list(flatten(path))[::-1] + [v1]
         path = (v1, path)
         for (v2, cost2) in G[v1].iteritems():
            if v2 not in visited:
               heapq.heappush(q, (cost + cost2, v2, path))

nodes = tuple(sys.argv[1:])

print "Generating connections,",
current_time = time.time()

words = set(x for x in open("websters-dictionary", "rb").read().lower().split() if 3 <= len(x) <= max(5, *[len(l)+1 for l in nodes]))

print len(words), "nodes found"

def error():
    sys.exit("Unreachable Route between '%s' and '%s'" % nodes)

if not all(node in words for node in nodes):
    error()

# following codes are modified version of
# http://norvig.com/spell-correct.html
alphabet = 'abcdefghijklmnopqrstuvwxyz'

def edits(word):
   splits = [(word[:i], word[i:]) for i in range(len(word) + 1)]
   deletes = [a + b[1:] for a, b in splits if b]
   replaces = [a + c + b[1:] for a, b in splits for c in alphabet if b]
   prepends = [c+word for c in alphabet]
   appends = [word+c for c in alphabet]
   return words & set(deletes + replaces + prepends + appends)

# Generate connections between nodes to pass to dijkstra algorithm
G = dict((x, dict((y, 1) for y in edits(x))) for x in words)

print "All connections generated, %0.2fs taken" % (time.time() - current_time)
current_time = time.time()

try:
    route = dijkstra(G, *nodes)
    print '\n'.join(route)
    print "%d hops, %0.2fs taken to search shortest path between '%s' & '%s'" % (len(route), time.time() - current_time, nodes[0], nodes[1])
except IndexError:
    error()

test

$ python codegolf-693.py post shot
Generating connections, 15930 nodes found
All connections generated, 2.09s taken
post
host
hot
shot
4 hops, 0.04s taken to search shortest path between 'post' & 'shot'

$ python codegolf-693.py zink silicon
Generating connections, 86565 nodes found
All connections generated, 13.91s taken
zink
pink
pank
pani
panic
pinic
sinic
sinico
silico
silicon
10 hops, 0.75s taken to search shortest path between 'zink' & 'silicon'

Aggiunti i test di user300

$ python codegolf-693.py vas arm
Generating connections, 15930 nodes found
All connections generated, 2.06s taken
vas
bas
bam
aam
arm
5 hops, 0.07s taken to search shortest path between 'vas' & 'arm'

$ python codegolf-693.py oxy pom
Generating connections, 15930 nodes found
All connections generated, 2.05s taken
oxy
poxy
pox
pom
4 hops, 0.01s taken to search shortest path between 'oxy' & 'pom'

$ python codegolf-693.py regatta gyrally
Generating connections, 86565 nodes found
All connections generated, 13.95s taken
Unreachable Route between 'regatta' and 'gyrally'

Alcuni di più

$ python codegolf-693.py gap shrend
Generating connections, 56783 nodes found
All connections generated, 8.16s taken
gap
rap
crap
craw
crew
screw
shrew
shrewd
shrend
9 hops, 0.67s taken to search shortest path between 'gap' & 'shrend'

$ python codegolf-693.py guester overturn
Generating connections, 118828 nodes found
All connections generated, 19.63s taken
guester
guesten
gesten
geste
gest
gast
east
ease
erse
verse
verset
overset
oversee
overseed
oversend
oversand
overhand
overhard
overcard
overcare
overtare
overture
overturn
23 hops, 0.82s taken to search shortest path between 'guester' & 'overturn'

3 <= len(x) <= max(map(len, [nodea, nodeb]))è garantito che il percorso non passerà mai attraverso una parola più lunga di entrambe le parole iniziale e finale?
Arnaud Le Blanc,

Prova con oxy pom; il percorso più breve è oxy->poxy->poy->pom. Inoltre sembra che tu permetti permutazioni e inserimenti in qualsiasi luogo, che non sono ammessi :-)
Arnaud Le Blanc,

@utente300, parti fisse di permutazioni e inserimenti, ho incollato troppo la copia, grazie ;-) e sto impostando il limite iniziale su 5 caratteri e consenti a +1 caratteri in più di iniziare e terminare le parole, fatemi sapere se è ancora un problema. Grazie.
TU
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.