אנחנו ממשיכים לחידה הרביעית שלנו באתגר. שמתם לב וודאי שהחידה הקודמת (מספר 3) היתה יותר קשה מהשתיים הראשונות. בכל מקרה הרביעית נותנת לנו הזדמנות לקחת אוויר שוב אז תרגישו חופשי להשקיע בפיתרונות קצרים ואלגנטיים.
סיסמאות חזקות
במערכת התוכנה החדשה שלנו החלטנו להשתמש בביטוי-סודי במקום בסיסמא רגילה. הביטוי מורכב ממספר מילים באנגלית, כולן באותיות קטנות וביניהן רווחים. ביטוי נקרא מאובטח אם אף מילה בו לא מופיעה יותר מפעם אחת.
לדוגמא הביטוי aa bb cc dd ee הוא מאובטח כי כל מילה מופיעה בו פעם אחת
הביטוי aa bb cc dd aa לא מתאים כסיסמא מאחר ו aa מופיעה בו פעמיים
והביטוי aa bb cc dd aaa גם בסדר
המשימה שלכם לקבל קובץ עם סיסמאות כאלה ולספר כמה מהן תקינות.
לדוגמא אם הקובץ היה מכיל את שלושת ביטויי הדוגמא היה צריך להדפיס 2.
(אגב- הפיתרון הנכון הראשון לחידה הזו הוגש בזמן אמת 37 שניות לאחר שפורסמה… אז אם אתם רציניים לגבי לגשת איתי ל AoC של השנה נסו לחשוב איך אנחנו מתמודדים עם המשוגעים ששם)
זה נקרא ה Arity של הפונקציה - כלומר כמה פרמטרים הפונקציה מצפה לקבל. בצורה כזו אליקסיר תומכת בהעמסת פונקציות (Functon Overloading), פיצ׳ר שלא קיים ב JavaScript.
import collections
path = r'C:\Python\Advent_of_code\4th_day\valid_password.txt'
counted = 0
with open(path,'r') as readline:
for line in readline:
res = line.split()
res = [item for item, count in collections.Counter(res).items() if count > 1]
if res == []:
counted += 1
print counted
אוי ואבוי שכחתי לגמרי מהחלק השני ודווקא זה חלק שאני אוהב במיוחד, תודה על התזכורת
חלק 2 - עדכון למדיניות האבטחה
מחלקת אבטחת המידע החליטה לעדכן את המדיניות כדי להקשיח עוד יותר את המערכת. עכשיו כדי שסיסמא תהיה תיקנית עלינו לוודא שאף שתי מילים אינן אנאגרמה אחת של השניה (שתי מילים הן אנאגרמה אם הן מורכבות מאותן אותיות אבל בסדר שונה).
לכן לדוגמא הטקסט abcde fghij הוא סיסמא תקני אבל הטקסט abcde xyz ecdab אינו תקני כי המילה הראשונה והאחרונה מורכבות מאותן אותיות בסדר שונה.
עדכנו את התוכנית כך שתספור כמה סיסמאות תקינות לפי המדיניות החדשה
from collections import defaultdict
def load_words(path = r'C:\Python\Advent_of_code\4th_day\valid_password.txt'):
with open(path) as readline:
for line in readline:
res = line.split()
return res
def get_anagrams(source):
d = defaultdict(list)
for word in source:
key = "".join(sorted(word))
d[key].append(word)
return d
def print_anagrams(word_source):
count = 0
d = get_anagrams(word_source)
acc = 0
for key, anagrams in d.iteritems():
if len(anagrams) > 1:
print(key, anagrams)
count += 1
word_source = load_words()
print_anagrams(word_source)
''' The code find if there are anagrams in each line in the file and returns the valid lines (w\o anagram)'''
from collections import defaultdict
def load_words(path = r'C:\Python\Advent_of_code\4th_day\valid_password.txt'):
count = 0
count_lines = 0
with open(path) as readline:
for line in readline:
count_lines += 1
res = line.split()
count += print_anagrams(res)
print "There are {} lines in total".format(count_lines)
print "{} lines are invalid".format(count)
result = count_lines - count
print "{} lines are valid".format(result)
def get_anagrams(source):
d = defaultdict(list)
for word in source:
key = "".join(sorted(word))
d[key].append(word)
return d
def print_anagrams(word_source):
count = 0
d = get_anagrams(word_source)
for key, anagrams in d.iteritems():
if len(anagrams) > 1:
count += 1
break
return count
load_words()