W pewnym banku kody do systemu składają się z ciągów cyfr długości 10. Podczas każdego logowania zostajemy poproszeni o podanie pewnych 3 cyfr naszego hasła. Okazało się, że na komputerze, z którego zwykle logujemy się do systemu naszego banku ktoś zainstalował oprogramowanie zbierające dane na temat historii naszych logowań. Zakładamy przy tym, że są w nim odnotowywane jedynie poprawne próby logowania. Dane są zbierane w formie słownika pythonowego. Kluczami są trzyelementowe krotki oznaczające indeksy cyfr hasła, o które zostaliśmy poproszeni, np. klucz (0, 3, 7) oznacza, że w pewnej próbie logowania system poprosił nas o zerową, trzecią i siódmą cyfrę z hasła. Wartościami w słowniku będą natomiast cyfry hasła występujące na pozycjach z klucza. Napisz funkcję attempts(d), która dla zadanego słownika – historii logowań zwróci liczbę prób potrzebną do złamania naszego hasła (chodzi tutaj o przypadek pesymistyczny, w którym dla każdej nieznanej cyfry z hasła włamujący “trafia” dopiero podczas ostatniej próby). Przykład:
attempts({(0,1,2):(7,3,5), (3,4,5):(7,2,0), (6,7,8):(9,4,1)})==10
attempts({(0,1,2):(7,3,5), (3,4,5):(7,2,0), (6,7,8):(9,4,1), (0,8,9):(7,1,1)})==1
Napisz funkcję BST(l), która dla zadanej listy liczb całkowitych l zwróci drzewo binarnych poszukiwań powstałe poprzez dodawanie do drzewa liczb w kolejności ich występowania na liście l. Każdy węzeł drzewa ma być trzyelementową krotką, a brakujące puste poddrzewo reprezentowane jest przez obiekt None. Przykład:
BST([4,1,6,2,5,6,8])=((None, 1, (None, 2, None)), 4, ((None, 5, None), 6, (None, 8, None)))