Advent of Code 2019 馃く (讬讜诐 4)

砖专砖讜专 Advent of Code 讬讜诐 1 谞讞诇 讛爪诇讞讛 讙讚讜诇讛, 讜讙诐 讬诪讬诐 2 讜志3 砖讛讬讜 诪砖诪注讜转讬转 拽砖讜讞讬诐 诪拽讜讚诪诐.

讗谞讬 诪谞讬讞 砖讛讗转讙专 讛讝讛 讬砖讗专 驻讛 诇驻讞讜转 诇讬讜诪讬讬诐 砖诇讜砖讛, 讗讝 拽讞讜 讗转 讛讝诪谉 :slight_smile:
讜讗诐 诇讗 讛住驻拽转诐 诇驻转讜专 讗转 讛讬诪讬诐 讛拽讜讚诪讬诐 鈥 诇讗 讞讜讘讛, 讗讘诇 诇讻讜 注诇 讝讛! 讗诇讜 转专讙讬诇讬诐 谞讞诪讚讬诐 诪讗讜讚 砖讬砖驻专讜 讗转 讛讬讻讜诇讜转 砖诇讻诐 诪讗讜讚.

讗讝 拽讚讬诪讛, 驻专住诪讜 驻讛 讗转 讛驻转专讜谞讜转 砖诇讻诐 诇讬讜诐 讛专讘讬注讬 砖诇 Advent of Code!

诇讬讬拽 1
讞诇拽 1

讞诇拽 2

5 诇讬讬拽讬诐
讞诇拽 1
def is_optional_password(numbers):
    couple = False
    for i in range(len(numbers) - 1):
        first , second = int(numbers[i]), int(numbers[i + 1])
        if first > second:
            return False
        elif first == second:
            couple = True
    return couple


def get_optional_paddword(x=125730, y=579381):
    counter = 0
    for number in range(x, y):
        if is_optional_password(list(str(number))):
            counter += 1
    return counter


get_optional_paddword()
讞诇拽 2 - 讛讛讘讚诇 讛讜讗 专拽 讘砖讜专转 讛转谞讗讬
def is_optional_password(numbers):
    couple = False
    for i in range(len(numbers) - 1):
        first , second = int(numbers[i]), int(numbers[i + 1])
        if first > second:
            return False
        elif first == second and numbers.count(str(first)) == 2:
            couple = True
    return couple


def get_optional_paddword(x=125730, y=579381):
    counter = 0
    for number in range(x, y):
        if is_optional_password(list(str(number))):
            counter += 1
    return counter


get_optional_paddword()
3 诇讬讬拽讬诐
砖谞讬 讛讞诇拽讬诐
import collections

PUZZLE_INPUT = '264360-746325'


def len_is_6(pw):
    return len(str(pw)) == 6


def pw_has_doubles(pw):
    pw = str(pw)
    for i in range(1, len(pw)):
        if pw[i] == pw[i - 1]:
            return True
    return False


def pw_has_doubles_v2(pw):
    pw = str(pw)
    cnt = collections.Counter(pw)
    for char in pw:
        if cnt[char] == 2:
            return True
    return False



def never_decreasing(pw):
    pw = str(pw)
    for i in range(1, len(pw)):
        if pw[i] < pw[i - 1]:
            return False
    return True


def check_pw_validity(pw, v=1):
    doubles = (pw_has_doubles, pw_has_doubles_v2)
    functions = (len_is_6, doubles[v - 1], never_decreasing)
    for func in functions:
        if not func(pw):
            return False
    return True


def count_valid_passwords(min_num, max_num, v=1):
    valid_passwords = 0
    for pw in range(int(min_num), int(max_num) + 1):
        if check_pw_validity(pw, v):
            valid_passwords += 1

    return valid_passwords


print(count_valid_passwords(*PUZZLE_INPUT.split('-')))
print('-' * 10)
print(count_valid_passwords(*PUZZLE_INPUT.split('-'), v=2))
2 诇讬讬拽讬诐

:star2: :star2:
转专讙讬诇 讻讬驻讬 - 诪注谞讬讬谉 诇讗讬驻讛 讛讞诇诇讬转 转讙讬注 讘住讜祝 :flying_saucer:

Part 1 & 2
#  day 4
# part 1 & 2
def check_if_digits_increase_and_1_same_number(number):
    number = str(number)
    digit = 1
    ident = 0
    while digit < len(number):
        if int(number[digit - 1]) > int(number[digit]):
            return False
        if number[digit - 1] == number[digit]:
            ident = 1
        digit += 1
    if ident == 1:
        return True
    return False

def check_if_digits_increase_and_1_same_number_part2(number):
    number = str(number)
    digit = 1
    ident = {n: 0 for n in range(10)}
    while digit < len(number):
        if int(number[digit - 1]) > int(number[digit]):
            return False
        if number[digit - 1] == number[digit]:
            ident[int(number[digit])] += 1
        digit += 1
    if 1 in ident.values():
        return True
    return False


def count_in_range(num1, num2):
    counter = 0
    for num in range(num1, num2 + 1):
        if check_if_digits_increase_and_1_same_number(num):
            counter += 1
    return counter


def count_in_range2(num1, num2):
    counter = 0
    for num in range(num1, num2 + 1):
        if check_if_digits_increase_and_1_same_number_part2(num):
            counter += 1
    return counter


print(f"answer part 1 : {count_in_range(272091, 815432)}")
print(f"answer part 2 : {count_in_range2(272091, 815432)}")
2 诇讬讬拽讬诐
转砖讜讘讛 - 讞诇拽 1
# range input 254032-789860
def check_if_duplicates(num):
    set_of_digits = set()
    for digit in str(num):
        if digit in set_of_digits:
            return True
        else:
            set_of_digits.add(digit)
    return False


def is_valid_number(num):
    current_max = 0
    for digit in str(num):
        if int(digit) < current_max:
            return False
        else:
            current_max = int(digit)
    result = check_if_duplicates(num)
    return result


def find_valid_passwords_count(range_from, range_to):
    valid_pass = [num for num in range(range_from, range_to) if is_valid_number(num)]
    return len(valid_pass)


print(find_valid_passwords_count(254032, 789860))  # part I - 1033

转砖讜讘讛 - 讞诇拽 2
# range input 254032-789860
def is_valid_pass(num):
    result = False
    for i in range(5):
        x, y = (str(num)[i], str(num)[i+1])
        if x == y and str(num).count(x) == 2:
            result = True
    return result


def is_valid_number(num):
    current_max = 0
    for digit in str(num):
        if int(digit) < current_max:
            return False
        else:
            current_max = int(digit)
    result = is_valid_pass(num)
    return result


def find_valid_passwords_count(range_from, range_to):
    counter = 0
    for num in range(range_from, range_to + 1):
        if is_valid_number(num):
            counter += 1
    return counter


print(find_valid_passwords_count(254032, 789860))  # part II - 670

诇讬讬拽 1

转专讙讬诇 讞讚砖 讬驻讜专住诐 讘讘讜拽专 讬讜诐 砖讬砖讬 鈥 诪讛专讜 诇讛讙讬砖! 讝讛 转专讙讬诇 诇讗 拽砖讛 讘诪讬讜讞讚 讜砖讜讜讛 诇谞住讜转 讗讜转讜 :slight_smile:

转专讙讬诇 1
# Day 4

def key_options():
    return [
        key for key in range(136818, 685980)
        if is_bigger(list(str(key))) and is_got_couple(list(str(key)))
    ]


def is_bigger(digits):
    next_num = 1
    for num in range(len(digits) - 1):
        if int(digits[num]) <= int(digits[next_num]):
            next_num += 1
        else:
            return False
    return True


def is_got_couple(digits):
    next_num = 1
    for num in range(len(digits) - 1):
        if int(digits[num]) == int(digits[next_num]):
            return True
        next_num += 1
    return False

    
len(key_options())

转专讙讬诇 2
# Day 4

def key_options():
    return [
        key for key in range(136818, 685980)
        if is_bigger(list(str(key))) and is_got_couple(list(str(key)))
    ]


def is_bigger(digits):
    next_num = 1
    for num in range(len(digits) - 1):
        if int(digits[num]) <= int(digits[next_num]):
            next_num += 1
        else:
            return False
    return True


def is_got_couple(digits):
    next_num = 1
    for num in range(len(digits) - 1):
        if int(digits[num]) == int(digits[next_num]) and digits.count(digits[num]) == 2:
            return True
        next_num += 1
    return False

    
len(key_options())

诇讬讬拽 1
Advent of Code, Day 4
# Advent of Code, Day 4
def calc_passwords_amount(min_val, max_val):
    # Part 1
    count = 0
    for password in range(int(min_val), int(max_val) + 1):
        if is_valid_part1(password):
            count += 1
    print(count)
    # Part 2
    count = 0
    for password in range(int(min_val), int(max_val) + 1):
        if is_valid_part2(password):
            count += 1
    print(count)


def is_valid_part1(password):
    min_dig = 0
    doubles = 0
    i = 0
    while i < 6:
        digit = int(str(password)[i])
        if digit < min_dig:
            return False
        if digit == min_dig:
            doubles += 1
        min_dig = digit
        i += 1
    if doubles >= 1:
        return True


def is_valid_part2(password):
    min_dig = 0
    is_double = False
    is_triple = False
    digits_count = {num: 0 for num in range(10)}
    i = 0
    no_triples = True
    while i < 6:
        digit = int(str(password)[i])
        if digit < min_dig:
            return False
        min_dig = digit
        digits_count[digit] += 1
        i += 1
    for num in digits_count:
        if digits_count.get(num) == 2:
            is_double = True
    if is_double:
        return True


calc_passwords_amount('235741', '706948')
诇讬讬拽 1
讛驻转专讜谉 砖诇讬
def is_increase(i):
    return sorted(i) == list(i)


def is_two_adjacents(i):
    return any(i[j] == i[j-1] for j in range(1, len(i)))


def is_exactly_two_adjacents(i):
    return any(i.count(j) == 2 for j in set(i))


# Part 1
inputs = map(str, range(272091, 815432))
matched_numbers = [i for i in inputs if is_increase(i) and is_two_adjacents(i)]
print(len(matched_numbers))

# Part 2
print(sum(map(is_exactly_two_adjacents, matched_numbers)))
8 诇讬讬拽讬诐

讗讞诇讛 驻转专讜谉! 讗诇讙谞讟讬 诪讗讜讚. 诇讗 讞砖讘转讬 注诇 讝讛 砖-any 砖讬诪讜砖讬 讘讬讜转专 驻讛

2 诇讬讬拽讬诐

def find_how_many(begin,end):
    c=0
    for i in range(begin,end+1):
        if good_pass(str(i)):
            c+=1
    return c  

def good_pass(password):
    password=list(password)
    return sorted(password) == password and find_two_digits_part_two(password)
    
def find_two_digits_part_one(password):
    for i in range(len(password)-1):
        if password[i] == password[i+1]:
            return True
    return False

def find_two_digits_part_two(password):
    a=[]
    for i in range(len(password)-1):
        if password[i] == password[i+1]:
            a.append(password.count(password[i]))
    return 2 in a
            


print(find_how_many(234208,765869))
诇讬讬拽 1
def get_input(puzzle_input):
    return list(map(int, puzzle_input.split('-')))


def check_criteria_first(num):
    if len(str(num)) != 6: 
        return False

    return check_streak_first(num)


def check_criteria_second(num):
    str_num = str(num)
    str_num_length = len(str_num)
    if str_num_length != 6: 
        return False

    success = False
    for x in range(1, str_num_length):
        if str_num[x] < str_num[x - 1]:
            return False
 
    return check_streak_second(num)


def check_streak_first(num):
    str_num = str(num)
    str_num_length = len(str_num)

    success = False
    for x in range(1, int(str_num_length)):
        if str_num[x] < str_num[x - 1]:
            return False
        
        if str_num[x] == str_num[x - 1]:
            success = True
    
    return success


def check_streak_second(num):
    str_num = str(num)
    str_num_length = len(str_num)
    matching = {}

    streak = False
    for x in range(str_num_length):
        if str_num[x] == str_num[x - 1]:
            if str_num[x] not in matching or not streak:
                matching[str_num[x]] = 2
            else:
                matching[str_num[x]] += 1

            streak = True
        else:
            streak = False

    if 2 in matching.values():
        return True
    else:
        return False


def get_passwords(range_start, range_end, f):
    iterable = range(range_start, range_end + 1)
    return list(filter(f, iterable))


def main():
    puzzle_input = '273025-767253'
    range_start, range_end = get_input(puzzle_input)

    # First Part
    passwords = get_passwords_first(range_start, range_end, check_criteria_first)
    print(len(passwords))

    # Second Part
    passwords = get_passwords(range_start, range_end, check_criteria_second)
    print(len(passwords))


main()
诇讬讬拽 1