Skip to content

Commit ebc2d5d

Browse files
Add Project Euler problem 79 solution 1 (TheAlgorithms#8607)
Co-authored-by: Dhruv Manilawala <[email protected]>
1 parent 5ca7189 commit ebc2d5d

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

Diff for: project_euler/problem_079/__init__.py

Whitespace-only changes.

Diff for: project_euler/problem_079/keylog.txt

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
319
2+
680
3+
180
4+
690
5+
129
6+
620
7+
762
8+
689
9+
762
10+
318
11+
368
12+
710
13+
720
14+
710
15+
629
16+
168
17+
160
18+
689
19+
716
20+
731
21+
736
22+
729
23+
316
24+
729
25+
729
26+
710
27+
769
28+
290
29+
719
30+
680
31+
318
32+
389
33+
162
34+
289
35+
162
36+
718
37+
729
38+
319
39+
790
40+
680
41+
890
42+
362
43+
319
44+
760
45+
316
46+
729
47+
380
48+
319
49+
728
50+
716

Diff for: project_euler/problem_079/keylog_test.txt

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
319
2+
680
3+
180
4+
690
5+
129
6+
620
7+
698
8+
318
9+
328
10+
310
11+
320
12+
610
13+
629
14+
198
15+
190
16+
631

Diff for: project_euler/problem_079/sol1.py

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""
2+
Project Euler Problem 79: https://projecteuler.net/problem=79
3+
4+
Passcode derivation
5+
6+
A common security method used for online banking is to ask the user for three
7+
random characters from a passcode. For example, if the passcode was 531278,
8+
they may ask for the 2nd, 3rd, and 5th characters; the expected reply would
9+
be: 317.
10+
11+
The text file, keylog.txt, contains fifty successful login attempts.
12+
13+
Given that the three characters are always asked for in order, analyse the file
14+
so as to determine the shortest possible secret passcode of unknown length.
15+
"""
16+
import itertools
17+
from pathlib import Path
18+
19+
20+
def find_secret_passcode(logins: list[str]) -> int:
21+
"""
22+
Returns the shortest possible secret passcode of unknown length.
23+
24+
>>> find_secret_passcode(["135", "259", "235", "189", "690", "168", "120",
25+
... "136", "289", "589", "160", "165", "580", "369", "250", "280"])
26+
12365890
27+
28+
>>> find_secret_passcode(["426", "281", "061", "819" "268", "406", "420",
29+
... "428", "209", "689", "019", "421", "469", "261", "681", "201"])
30+
4206819
31+
"""
32+
33+
# Split each login by character e.g. '319' -> ('3', '1', '9')
34+
split_logins = [tuple(login) for login in logins]
35+
36+
unique_chars = {char for login in split_logins for char in login}
37+
38+
for permutation in itertools.permutations(unique_chars):
39+
satisfied = True
40+
for login in logins:
41+
if not (
42+
permutation.index(login[0])
43+
< permutation.index(login[1])
44+
< permutation.index(login[2])
45+
):
46+
satisfied = False
47+
break
48+
49+
if satisfied:
50+
return int("".join(permutation))
51+
52+
raise Exception("Unable to find the secret passcode")
53+
54+
55+
def solution(input_file: str = "keylog.txt") -> int:
56+
"""
57+
Returns the shortest possible secret passcode of unknown length
58+
for successful login attempts given by `input_file` text file.
59+
60+
>>> solution("keylog_test.txt")
61+
6312980
62+
"""
63+
logins = Path(__file__).parent.joinpath(input_file).read_text().splitlines()
64+
65+
return find_secret_passcode(logins)
66+
67+
68+
if __name__ == "__main__":
69+
print(f"{solution() = }")

0 commit comments

Comments
 (0)