Created
May 21, 2020 23:44
-
-
Save jsundram/68f375242cf1d39872e5b993ac83bd4b to your computer and use it in GitHub Desktop.
I got nerd sniped by @vanreece
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import defaultdict | |
import networkx as nx | |
import string | |
import matplotlib.pyplot as plt | |
def get_words(filename='/usr/share/dict/words'): | |
d = defaultdict(set) | |
with open(filename) as f: | |
for line in f: | |
word = line.strip().lower() | |
d[len(word)].add(word) | |
return d | |
def make_graphs(words_by_len): | |
letters = string.ascii_lowercase | |
graphs = {} | |
for n, words in sorted(words_by_len.items()): | |
print("Making graph for words of length %d ..." % n) | |
g = nx.Graph() | |
for word in words: | |
for i in range(n): | |
pre, post = word[:i], word[i+1:] | |
for x in letters: | |
candidate = pre + x + post | |
if candidate != word and candidate in words: | |
g.add_edge(word, candidate) | |
graphs[n] = g | |
return graphs | |
def save_graph(graph, filename): | |
# had to tweak figsize so that nodes didn't overlap | |
plt.figure(figsize=(16, 16)) | |
# circular layout is orderly and legible, compared to spring layout | |
# but obviously meaningless | |
pos = nx.circular_layout(graph) | |
# there may be something better to color by? | |
colors = [graph.degree(n) for n in graph.nodes] | |
nx.draw_networkx(graph, pos, node_color=colors, cmap=plt.cm.RdYlGn_r) | |
plt.savefig(filename) | |
plt.close() | |
def longest_simple_path(graph): | |
# this is the hard part... | |
# https://en.wikipedia.org/wiki/Longest_path_problem | |
# We have an undirected graph with cycles, so DAG algos won't help. | |
return [] | |
def main(): | |
words_by_len = get_words() | |
for n, words in words_by_len.items(): | |
print("There are %d words of length %d" % (len(words), n)) | |
del words_by_len[1] # trivial word ladder is the alphabet | |
graphs = make_graphs(words_by_len) | |
for n, graph in sorted(graphs.items()): | |
longest = longest_simple_path(graph) | |
print("longest chain for words of length %s: %s" % (n, len(longest))) | |
save_graph(graphs[2], "circle-2.png") | |
return graphs | |
if __name__ == '__main__': | |
main() |
This is probably the best way to do it: https://eprints.cs.univie.ac.at/6197/1/FindingOptimalLongestPaths.pdf
There's an implementation here: http://algo2.iti.kit.edu/kalp/ -- would need to write out to a METIS or DIMACS graph file format, then compile that code, then run it, and then translate the results back into words.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
words of length 2