A common security method used for online banking is to ask the user
for three random characters from a passcode. For example, if the
passcode was \(531278\), they may ask
for the \(2\text{nd}\), \(3\text{rd}\), and \(5\text{th}\) characters; the expected reply
would be: \(317\).
The text file, keylog.txt,
contains fifty successful login attempts.
Given that the three characters are always asked for in order,
analyse the file so as to determine the shortest possible secret
passcode of unknown length.
L ← Empty list that will contain the sorted elements S ← Set of all nodes with no incoming edge
while S is not empty do remove a node n from S add n to L for each node m with an edge e from n to m do remove edge e from the graph if m has no other incoming edges then insert m into S
if graph has edges then return error (graph has at least one cycle) else return L (a topologically sorted order)
g = [[] for i inrange(10)] d = [0for i inrange(10)] f = [0for i inrange(10)] ls = open('p079_keylog.txt', 'r').readlines() for s in ls: x = int(s[:-1]) a = x // 100 b = x // 10 % 10 c = x % 10 g[a].append(b) g[b].append(c) d[b] += 1 d[c] += 1 f[a] = f[b] = f[c] = 1 q = Queue() for i inrange(10): if d[i] == 0and f[i]: q.put(i)
a = [] whilenot q.empty(): u = q.get() a.append(u) for v in g[u]: d[v] -= 1 if d[v] == 0: q.put(v) ans = "".join(str(x) for x in a) print(ans)
1 2 3 4 5 6 7 8 9
import networkx as nx
g = nx.DiGraph() for s inopen('p079_keylog.txt', 'r').readlines(): g.add_edge(s[0], s[1]) g.add_edge(s[1], s[2])
ans = "".join(list(nx.topological_sort(g))) print(ans)