From b191f7ed0c2a52fedcb142bde176f4d70ef58198 Mon Sep 17 00:00:00 2001 From: Faisal Ahmad <71762204+fab-c14@users.noreply.github.com> Date: Tue, 3 Dec 2024 18:48:17 +0530 Subject: [PATCH 1/3] First 3 days soln technically 6 questions --- first_part_1.py | 31 +++++++++++++++++++++++++++++++ first_part_2.py | 35 +++++++++++++++++++++++++++++++++++ second_part_1.py | 30 ++++++++++++++++++++++++++++++ second_part_2.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ third_part_1.py | 25 +++++++++++++++++++++++++ third_part_2.py | 40 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 205 insertions(+) create mode 100644 first_part_1.py create mode 100644 first_part_2.py create mode 100644 second_part_1.py create mode 100644 second_part_2.py create mode 100644 third_part_1.py create mode 100644 third_part_2.py diff --git a/first_part_1.py b/first_part_1.py new file mode 100644 index 0000000..e424f64 --- /dev/null +++ b/first_part_1.py @@ -0,0 +1,31 @@ +def total_distance(left_list, right_list): + # Sort both lists + left_list.sort() + right_list.sort() + + # Calculate the total distance + total_distance = sum(abs(l - r) for l, r in zip(left_list, right_list)) + return total_distance + +# Read input file +file_path = "1st.txt" # Replace with your file path if different + +# Initialize lists +left_list = [] +right_list = [] + +# Parse the input file +with open(file_path, "r") as file: + for line in file: + numbers = list(map(int, line.split())) + if len(numbers) == 2: # Ensure there are exactly two numbers per line + left_list.append(numbers[0]) + right_list.append(numbers[1]) + +# Ensure both lists have the same length +if len(left_list) != len(right_list): + print("Error: The two lists have different lengths.") +else: + # Calculate the total distance + result = total_distance(left_list, right_list) + print(f"Total Distance: {result}") diff --git a/first_part_2.py b/first_part_2.py new file mode 100644 index 0000000..2b161d9 --- /dev/null +++ b/first_part_2.py @@ -0,0 +1,35 @@ +from collections import Counter + +def calculate_similarity_score(left_list, right_list): + # Count occurrences of each number in the right list + right_count = Counter(right_list) + + # Calculate the similarity score + similarity_score = 0 + for number in left_list: + if number in right_count: + similarity_score += number * right_count[number] + return similarity_score + +# Read input file +file_path = "1st.txt" # Replace with your file path if different + +# Initialize lists +left_list = [] +right_list = [] + +# Parse the input file +with open(file_path, "r") as file: + for line in file: + numbers = list(map(int, line.split())) + if len(numbers) == 2: # Ensure there are exactly two numbers per line + left_list.append(numbers[0]) + right_list.append(numbers[1]) + +# Ensure both lists have the same length +if len(left_list) != len(right_list): + print("Error: The two lists have different lengths.") +else: + # Calculate the similarity score + similarity_score = calculate_similarity_score(left_list, right_list) + print(f"Similarity Score: {similarity_score}") diff --git a/second_part_1.py b/second_part_1.py new file mode 100644 index 0000000..e34e103 --- /dev/null +++ b/second_part_1.py @@ -0,0 +1,30 @@ +def is_safe(report): + # Check if all differences are between 1 and 3 + differences = [report[i+1] - report[i] for i in range(len(report) - 1)] + if not all(1 <= abs(diff) <= 3 for diff in differences): + return False + + # Check if the report is strictly increasing or decreasing + is_increasing = all(diff > 0 for diff in differences) + is_decreasing = all(diff < 0 for diff in differences) + + return is_increasing or is_decreasing + +def count_safe_reports(file_path): + safe_count = 0 + + # Read and process the file + with open(file_path, "r") as file: + for line in file: + report = list(map(int, line.split())) + if is_safe(report): + safe_count += 1 + + return safe_count + +# Input file path +file_path = "second.txt" # Replace with the path to your file + +# Count and print the number of safe reports +safe_reports = count_safe_reports(file_path) +print(f"Number of Safe Reports: {safe_reports}") diff --git a/second_part_2.py b/second_part_2.py new file mode 100644 index 0000000..8dd71cd --- /dev/null +++ b/second_part_2.py @@ -0,0 +1,44 @@ +from collections import deque + +def is_safe(report): + # Check if all differences are between 1 and 3 + differences = [report[i+1] - report[i] for i in range(len(report) - 1)] + if not all(1 <= abs(diff) <= 3 for diff in differences): + return False + + # Check if the report is strictly increasing or decreasing + is_increasing = all(diff > 0 for diff in differences) + is_decreasing = all(diff < 0 for diff in differences) + + return is_increasing or is_decreasing + +def is_safe_with_dampener(report): + if is_safe(report): + return True + + # Check all subsets with one level removed + for i in range(len(report)): + modified_report = report[:i] + report[i+1:] # Remove the ith level + if is_safe(modified_report): + return True + + return False + +def count_safe_reports_with_dampener(file_path): + safe_count = 0 + + # Read and process the file + with open(file_path, "r") as file: + for line in file: + report = list(map(int, line.split())) + if is_safe_with_dampener(report): + safe_count += 1 + + return safe_count + +# Input file path +file_path = "second.txt" # Replace with your file path if different + +# Count and print the number of safe reports +safe_reports = count_safe_reports_with_dampener(file_path) +print(f"Number of Safe Reports (with Dampener): {safe_reports}") diff --git a/third_part_1.py b/third_part_1.py new file mode 100644 index 0000000..9e5fd72 --- /dev/null +++ b/third_part_1.py @@ -0,0 +1,25 @@ +import re + +def extract_and_sum_multiplications(corrupted_memory): + # Regular expression to match valid mul(X,Y) instructions + pattern = r"mul\(\s*(\d+)\s*,\s*(\d+)\s*\)" + + # Find all matches + matches = re.findall(pattern, corrupted_memory) + + # Calculate the sum of all valid multiplications + total = 0 + for x, y in matches: + total += int(x) * int(y) + + return total + +# Read input file +file_path = "third_part.txt" # Replace with your file path if different + +with open(file_path, "r") as file: + corrupted_memory = file.read() + +# Compute the result +result = extract_and_sum_multiplications(corrupted_memory) +print(f"Total Sum of Valid Multiplications: {result}") diff --git a/third_part_2.py b/third_part_2.py new file mode 100644 index 0000000..eacb9cd --- /dev/null +++ b/third_part_2.py @@ -0,0 +1,40 @@ +import re + +def process_corrupted_memory(corrupted_memory): + # Regex patterns + mul_pattern = r"mul\(\s*(\d+)\s*,\s*(\d+)\s*\)" # Matches valid mul(X,Y) + do_pattern = r"do\(\)" # Matches do() + dont_pattern = r"don't\(\)" # Matches don't() + + # State variable + mul_enabled = True + total = 0 + + + tokens = re.split(r"(\bmul\(\s*\d+\s*,\s*\d+\s*\)|do\(\)|don't\(\))", corrupted_memory) + + for token in tokens: + token = token.strip() + if not token: + continue + + if re.match(do_pattern, token): + mul_enabled = True + elif re.match(dont_pattern, token): + mul_enabled = False + elif mul_enabled and re.match(mul_pattern, token): + # Extract numbers from the valid mul instruction + x, y = map(int, re.findall(r"\d+", token)) + total += x * y + + return total + +# Read input file +file_path = "third_part.txt" # Replace with your file path if different + +with open(file_path, "r") as file: + corrupted_memory = file.read() + +# Compute the result +result = process_corrupted_memory(corrupted_memory) +print(f"Total Sum of Enabled Multiplications: {result}") From e32b872c2fad2b25eab85c6b68ba873d14d51d65 Mon Sep 17 00:00:00 2001 From: Faisal Ahmad <71762204+fab-c14@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:30:11 +0530 Subject: [PATCH 2/3] day 4 and 5 --- fifth_day_.py | 51 ++++++++++++++++++++++++++++ fifth_day_part_2.py | 82 +++++++++++++++++++++++++++++++++++++++++++++ fouth_day_part_1.py | 45 +++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 fifth_day_.py create mode 100644 fifth_day_part_2.py create mode 100644 fouth_day_part_1.py diff --git a/fifth_day_.py b/fifth_day_.py new file mode 100644 index 0000000..d9a44e7 --- /dev/null +++ b/fifth_day_.py @@ -0,0 +1,51 @@ +# Parse the input file content +def parse_input_file(file_path): + with open(file_path, 'r') as file: + content = file.read() + + # Split the content into rules and updates sections + sections = content.strip().split("\n\n") + rules = sections[0].split("\n") + updates = sections[1].split("\n") + + # Parse rules into a list of tuples + ordering_rules = [] + for rule in rules: + x, y = map(int, rule.split("|")) + ordering_rules.append((x, y)) + + # Parse updates into lists of integers + update_lists = [list(map(int, update.split(","))) for update in updates] + + return ordering_rules, update_lists + +# Function to calculate the sum of middle page numbers for valid updates +def calculate_middle_sum(ordering_rules, update_lists): + # Check if an update respects all applicable rules + def is_valid_update(update, rules): + for x, y in rules: + if x in update and y in update: + if update.index(x) > update.index(y): + return False + return True + + # Validate updates + valid_updates = [update for update in update_lists if is_valid_update(update, ordering_rules)] + + # Calculate the middle page number sum + middle_sum = 0 + for update in valid_updates: + middle_index = len(update) // 2 + middle_sum += update[middle_index] + + return middle_sum + +# File path to the input +file_path = 'fifth.txt' # Replace with your actual file path + +# Parse the input file +ordering_rules, update_lists = parse_input_file(file_path) + +# Calculate and print the result +result = calculate_middle_sum(ordering_rules, update_lists) +print(f"Sum of middle page numbers from valid updates: {result}") diff --git a/fifth_day_part_2.py b/fifth_day_part_2.py new file mode 100644 index 0000000..19b340b --- /dev/null +++ b/fifth_day_part_2.py @@ -0,0 +1,82 @@ +def parse_input_file(file_path): + with open(file_path, 'r') as file: + content = file.read() + + # Split the content into rules and updates sections + sections = content.strip().split("\n\n") + rules = sections[0].split("\n") + updates = sections[1].split("\n") + + # Parse rules into a list of tuples + ordering_rules = [] + for rule in rules: + x, y = map(int, rule.split("|")) + ordering_rules.append((x, y)) + + # Parse updates into lists of integers + update_lists = [list(map(int, update.split(","))) for update in updates] + + return ordering_rules, update_lists + +# Reorder an update using topological sorting +def reorder_update(update, rules): + from collections import defaultdict, deque + + # Build a graph based on the rules + graph = defaultdict(list) + in_degree = defaultdict(int) + + # Restrict rules to pages in the update + update_set = set(update) + for x, y in rules: + if x in update_set and y in update_set: + graph[x].append(y) + in_degree[y] += 1 + in_degree.setdefault(x, 0) + + # Perform topological sorting + queue = deque([node for node in update if in_degree[node] == 0]) + sorted_update = [] + + while queue: + node = queue.popleft() + sorted_update.append(node) + for neighbor in graph[node]: + in_degree[neighbor] -= 1 + if in_degree[neighbor] == 0: + queue.append(neighbor) + + return sorted_update + +def calculate_middle_sum_for_reordered_updates(ordering_rules, update_lists): + # Check if an update respects all applicable rules + def is_valid_update(update, rules): + for x, y in rules: + if x in update and y in update: + if update.index(x) > update.index(y): + return False + return True + + incorrectly_ordered = [] + for update in update_lists: + if not is_valid_update(update, ordering_rules): + incorrectly_ordered.append(update) + + # Reorder incorrectly ordered updates and calculate the middle sum + middle_sum = 0 + for update in incorrectly_ordered: + reordered = reorder_update(update, ordering_rules) + middle_index = len(reordered) // 2 + middle_sum += reordered[middle_index] + + return middle_sum + +# File path to the input +file_path = 'fifth.txt' # Replace with your actual file path + +# Parse the input file +ordering_rules, update_lists = parse_input_file(file_path) + +# Calculate the sum of middle page numbers for reordered updates +result = calculate_middle_sum_for_reordered_updates(ordering_rules, update_lists) +print(f"Sum of middle page numbers from reordered updates: {result}") diff --git a/fouth_day_part_1.py b/fouth_day_part_1.py new file mode 100644 index 0000000..3e25a54 --- /dev/null +++ b/fouth_day_part_1.py @@ -0,0 +1,45 @@ +def count_word_occurrences(grid, word): + rows = len(grid) + cols = len(grid[0]) + word_length = len(word) + count = 0 + + # Helper function to check if the word matches in a given direction + def match_at_direction(x, y, dx, dy): + for i in range(word_length): + nx, ny = x + i * dx, y + i * dy + if not (0 <= nx < rows and 0 <= ny < cols) or grid[nx][ny] != word[i]: + return False + return True + + # Iterate over every cell in the grid + for x in range(rows): + for y in range(cols): + # Check all 8 possible directions + directions = [ + (0, 1), # Horizontal right + (0, -1), # Horizontal left + (1, 0), # Vertical down + (-1, 0), # Vertical up + (1, 1), # Diagonal top-left to bottom-right + (-1, -1), # Diagonal bottom-right to top-left + (1, -1), # Diagonal top-right to bottom-left + (-1, 1) # Diagonal bottom-left to top-right + ] + for dx, dy in directions: + if match_at_direction(x, y, dx, dy): + count += 1 + + return count + +# Read input file +file_path = "fourth.txt" # Replace with your file path if different + +# Parse the grid from the file +with open(file_path, "r") as file: + grid = [list(line.strip()) for line in file] + +# Count occurrences of "XMAS" +word = "XMAS" +occurrences = count_word_occurrences(grid, word) +print(f"Total occurrences of '{word}': {occurrences}") From 4151014735b1f15cf791a583ab576a9efafde606 Mon Sep 17 00:00:00 2001 From: Faisal Ahmad <71762204+fab-c14@users.noreply.github.com> Date: Tue, 10 Dec 2024 22:06:23 +0530 Subject: [PATCH 3/3] solved tenth day --- tenth_day_part_1.py | 53 +++++++++++++++++++++++++++++++++++++++++++++ tenth_day_part_2.py | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 tenth_day_part_1.py create mode 100644 tenth_day_part_2.py diff --git a/tenth_day_part_1.py b/tenth_day_part_1.py new file mode 100644 index 0000000..88b5927 --- /dev/null +++ b/tenth_day_part_1.py @@ -0,0 +1,53 @@ +from collections import deque + +def parse_map(file_path): + """Read the map from a file and parse it into a 2D grid of integers.""" + with open(file_path, 'r') as file: + return [list(map(int, line.strip())) for line in file.readlines()] + +def bfs(grid, start): + """Perform BFS to find reachable height-9 positions.""" + rows, cols = len(grid), len(grid[0]) + directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] + queue = deque([start]) + visited = set() + reachable_nines = set() + + while queue: + x, y = queue.popleft() + if (x, y) in visited: + continue + visited.add((x, y)) + + # If height is 9, add to reachable nines + if grid[x][y] == 9: + reachable_nines.add((x, y)) + continue + + # Explore neighbors + for dx, dy in directions: + nx, ny = x + dx, y + dy + if 0 <= nx < rows and 0 <= ny < cols and (nx, ny) not in visited: + if grid[nx][ny] == grid[x][y] + 1: # Valid hiking trail step + queue.append((nx, ny)) + + return reachable_nines + +def compute_trailhead_scores(grid): + """Compute the score for all trailheads in the map.""" + rows, cols = len(grid), len(grid[0]) + total_score = 0 + + for x in range(rows): + for y in range(cols): + if grid[x][y] == 0: # Trailhead found + reachable_nines = bfs(grid, (x, y)) + total_score += len(reachable_nines) + + return total_score + +# Main execution +file_path = "tenth.txt" +grid = parse_map(file_path) +result = compute_trailhead_scores(grid) +print("Sum of scores of all trailheads:", result) diff --git a/tenth_day_part_2.py b/tenth_day_part_2.py new file mode 100644 index 0000000..6e67c5e --- /dev/null +++ b/tenth_day_part_2.py @@ -0,0 +1,42 @@ +from functools import lru_cache + +def parse_map(file_path): + """Read the map from a file and parse it into a 2D grid of integers.""" + with open(file_path, 'r') as file: + return [list(map(int, line.strip())) for line in file.readlines()] + +@lru_cache(None) +def count_trails(grid, x, y): + """Recursively count distinct hiking trails starting from (x, y).""" + rows, cols = len(grid), len(grid[0]) + if grid[x][y] == 9: # A trail ends at height 9 + return 1 + + total_trails = 0 + directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] + + for dx, dy in directions: + nx, ny = x + dx, y + dy + if 0 <= nx < rows and 0 <= ny < cols: + if grid[nx][ny] == grid[x][y] + 1: # Valid trail step + total_trails += count_trails(grid, nx, ny) + + return total_trails + +def compute_trailhead_ratings(grid): + """Compute the rating (distinct trails) for all trailheads.""" + rows, cols = len(grid), len(grid[0]) + total_rating = 0 + + for x in range(rows): + for y in range(cols): + if grid[x][y] == 0: # Trailhead found + total_rating += count_trails(tuple(map(tuple, grid)), x, y) + + return total_rating + +# Main execution +file_path = "tenth.txt" +grid = parse_map(file_path) +result = compute_trailhead_ratings(grid) +print("Sum of ratings of all trailheads:", result)