Problem Solving Techniques
denvaar.github.io
denvaar.github.io
Polya's "How to Solve It" and Paul Zeitz's "Art and Craft of Problem Solving" are both great. Are there other resources on this topic that are worth reading?
The sections headings of Chapter 1 on Heuristics give a flavor of its approach: Search for a pattern; Draw a figure; Formulate an equivalent problem; Modify the problem; Choose effective notation; Exploit symmetry; Divide into cases; Work backward; Argue by contradiction; Pursue parity; Consider extreme cases; Generalize.
Links:
* Official Springer book web site: https://www.springer.com/gp/book/9780387961712
* Amazon: https://www.amazon.com/Problem-Solving-Through-Problems-Prob...
* Poor quality scanned PDF: https://math.la.asu.edu/~ifulman/spring13/mat194/problem-sol...
I narrowly missed a place on the Australian IMO team, and at the time was annoyed at myself for being beaten by a 10 year old. He, of course, was Terry Tao, youngest ever winner of a IMO medal, and a Fields Medalist a few years later.
- "General Methods for Solving Physics Problems", Belikov.
This was probably the key takeaway for me. Too often, specially when I'm solving hackerrank/leetcode challenges, I jump straight into the code without bothering to think about the problem first, at least for a moment.
Now I keep a physical notepad to write and/or draw at least basic models of whatever non-obvious problem or issue I'm given. I've noted that it's helped me quite a bit, at least to give me a general idea of what I should do.
- Something about it reminded me of Project Euler. Shortly afterwards read the surrounding text confirming that.
- The problem should be pretty easy to solve if we could assume that each digit is unique (i.e. appears only once in the pass phrase). Clearly the challenge here comes largely from digits being possibly present multiple times. A greedy algorithm could start with this assumption and then, upon encountering a contradiction, duplicate a digit. To decide whether such an algorithm is optimal you'd want to try and construct an example where it produces a suboptimal result. Might lead to a few iterations of refining and seeing whether you can keep it greedy.
- Could this problem be NP-hard? Could you encode NP problems in the ambiguities of "are these two identical digits also the same ones in the passcode"? At this point some meta-solving comes in: Project Euler problems allow brute-forcing in principle, but usually it won't get you far without at the very least a clever reduction. 50 login attempts might be on the order of 10-20 digits in the passphrase (if you assume digit positions being chosen at random, you could actually get a decent estimate), which is not amenable to pure brute force.
- Is it possible that there is no unique solution? It seems very likely to me, and I should probably try to construct an example. (I won't, because I'm trying to only scope out my own solution process).
- I tried to frame the problem as a partial ordering, but the difficulty is (again) in the label ambiguities. Could we give a different label to every single given digit and then try to merge them? Can this be done greedily? What to do with ambiguities? The above considerations return, from a different angle.
- The unknown length makes the number of unknowns, well, unknown. But you could postulate a length, giving you a fixed number of unknowns that need to be assigned.
- It's impossible to observe my own problem solving process without impacting it. And writing it down tends to affect it very strongly (mentally drilling down into individual facets instead of staying at "surveying level").
please note that several of the commenters today are accounts created just to praise OP
My way of solving this was to write down the rules of which the digits appear paper with a pen. Liked that you pressed for that in the article, it really helps me to understand.
However my own weakness is when it comes to put this down to code. I often tend to only use pen + paper when things can be automated. It was great to see your approach of first writing a simplified algorithm - and then take it all the way insightful.
Going to try out this in the future, thanks for good read!
/ * Created by Sneeuwpopsneeuw on 28-Aug-16. */ The code Is one big commend that basically says use ctrl+f. I found 2 items in the list that I thought where the beginning and end. Based on that I filled in the missing digits.
A string that contains each three-tuple in order but not necessarily contiguous, and is the shortest possible string that meets this criteria.
The second clause of the problem rules out simply concatinating the fifty succesful login attempts. But that does give us an upper limit on the length of the string.
N[max] = 3 * 50 = 150
Next consider the simple brute-force solution: Iterate through the integers from n (to be determined later, for now set it to zero or one) to 10^150 - 1 and check each one. Halt when the solution is found.
Depending on the urgency of the situation this is as much thinking as you might need to do. There are several fairly obvious ways to trim the amount of integers you would need to check.
But of course, the generate-and-test strategy is overkill for this problem, and relatively uninteresting compared to the possibility of devising a clever mathematical or logical solution.
One angle would be to explore generation functions that might produce minimal strings directly from the set of three-tuples.
Another angle would be to set up the problem for a contraint-solver. I'm a little rusty these days but I think you could convert the problem to a SAT instance and use an off-the shelf SAT solver.
(As an aside, watch out for unfounded assumptions, e.g. maybe all ten digits don't appear in the logins. Do digits appear more than once in a given keylog entry?)
It took me about ten minutes to write the brute force python code, and about half an hour to get it to work. (The biggest problem I had was debuggin a stupid Python 2/3 error: map() returns an iterator now not a list. FML. Also, getting conda to work in windows with vscode was a lil hassle (use cmd.exe not PowerShell.) FML.)
For the curious:
keylog = list(map(list, '''\
319
680
180
690
129
620
762
689
762
318
368
710
720
710
629
168
160
689
716
731
736
729
316
729
729
710
769
290
719
680
318
389
162
289
162
718
729
319
790
680
890
362
319
760
316
729
380
319
728
716'''.splitlines()))
def predicate(N):
f = N.find
# This works because there are no repeated digits (like 112).
for a, b, c in keylog:
i = f(a)
if -1 == i:
return False
j = f(b, i)
if -1 == j:
return False
if -1 == f(c, j):
return False
return True
def do():
n = 9999
while True:
N = str(n)
if predicate(N):
print(N)
break
n += 1
do()