Skip Navigation
InitialsDiceBearhttps://github.com/dicebear/dicebearhttps://creativecommons.org/publicdomain/zero/1.0/„Initials” (https://github.com/dicebear/dicebear) by „DiceBear”, licensed under „CC0 1.0” (https://creativecommons.org/publicdomain/zero/1.0/)BB
b_van_b @programming.dev
Posts 2
Comments 24
🎄 - 2023 DAY 1 SOLUTIONS -🎄
  • Python 3

    I'm trying to practice writing clear, commented, testable functions, so I added some things that are strictly unnecessary for the challenge (docstrings, error raising, type hints, tests...), but I think it's a necessary exercise for me. If anyone has comments or criticism about my attempt at "best practices," please let me know!

    Also, I thought it was odd that the correct answer to part 2 requires that you allow for overlapping letters such as "threeight", but that doesn't occur in the sample input. I imagine that many people will hit a wall wondering why their answer is rejected.

    day01.py
    import re
    from pathlib import Path
    
    
    DIGITS = [
        "zero",
        "one",
        "two",
        "three",
        "four",
        "five",
        "six",
        "seven",
        "eight",
        "nine",
        r"\d",
    ]
    
    PATTERN_PART_1 = r"\d"
    PATTERN_PART_2 = f"(?=({'|'.join(DIGITS)}))"
    
    
    def get_digit(s: str) -> int:
        """Return the digit in the input
    
        Args:
            s (str): one string containing a single digit represented by a single arabic numeral or spelled out in lower-case English
    
        Returns:
            int: the digit as an integer value
        """
    
        try:
            return int(s)
        except ValueError:
            return DIGITS.index(s)
    
    
    def calibration_value(line: str, pattern: str) -> int:
        """Return the calibration value in the input
    
        Args:
            line (str): one line containing a calibration value
            pattern (str): the regular expression pattern to match
    
        Raises:
            ValueError: if no digits are found in the line
    
        Returns:
            int: the calibration value
        """
    
        digits = re.findall(pattern, line)
    
        if digits:
            return get_digit(digits[0]) * 10 + get_digit(digits[-1])
    
        raise ValueError(f"No digits found in: '{line}'")
    
    
    def calibration_sum(lines: str, pattern: str) -> int:
        """Return the sum of the calibration values in the input
    
        Args:
            lines (str): one or more lines containing calibration values
    
        Returns:
            int: the sum of the calibration values
        """
    
        sum = 0
    
        for line in lines.split("\n"):
            sum += calibration_value(line, pattern)
    
        return sum
    
    
    if __name__ == "__main__":
        path = Path(__file__).resolve().parent / "input" / "day01.txt"
    
        lines = path.read_text().strip()
    
        print("Sum of calibration values:")
        print(f"• Part 1: {calibration_sum(lines, PATTERN_PART_1)}")
        print(f"• Part 2: {calibration_sum(lines, PATTERN_PART_2)}")
    
    test_day01.py
    import pytest
    from advent_2023_python.day01 import (
        calibration_value,
        calibration_sum,
        PATTERN_PART_1,
        PATTERN_PART_2,
    )
    
    
    LINES_PART_1 = [
        ("1abc2", 12),
        ("pqr3stu8vwx", 38),
        ("a1b2c3d4e5f", 15),
        ("treb7uchet", 77),
    ]
    BLOCK_PART_1 = (
        "\n".join([line[0] for line in LINES_PART_1]),
        sum(line[1] for line in LINES_PART_1),
    )
    
    LINES_PART_2 = [
        ("two1nine", 29),
        ("eightwothree", 83),
        ("abcone2threexyz", 13),
        ("xtwone3four", 24),
        ("4nineeightseven2", 42),
        ("zoneight234", 14),
        ("7pqrstsixteen", 76),
    ]
    BLOCK_PART_2 = (
        "\n".join([line[0] for line in LINES_PART_2]),
        sum(line[1] for line in LINES_PART_2),
    )
    
    
    def test_part_1():
        for line in LINES_PART_1:
            assert calibration_value(line[0], PATTERN_PART_1) == line[1]
    
        assert calibration_sum(BLOCK_PART_1[0], PATTERN_PART_1) == BLOCK_PART_1[1]
    
    
    def test_part_2_with_part_1_values():
        for line in LINES_PART_1:
            assert calibration_value(line[0], PATTERN_PART_2) == line[1]
    
        assert calibration_sum(BLOCK_PART_1[0], PATTERN_PART_2) == BLOCK_PART_1[1]
    
    
    def test_part_2_with_part_2_values():
        for line in LINES_PART_2:
            assert calibration_value(line[0], PATTERN_PART_2) == line[1]
    
        assert calibration_sum(BLOCK_PART_2[0], PATTERN_PART_2) == BLOCK_PART_2[1]
    
    
    def test_no_digits():
        with pytest.raises(ValueError):
            calibration_value("abc", PATTERN_PART_1)
    
        with pytest.raises(ValueError):
            calibration_value("abc", PATTERN_PART_2)
    
  • www.theregister.com Linux has nearly half of the desktop OS Linux market

    It would be twice as much if people could stop arguing about who counts and who doesn't

    Linux has nearly half of the desktop OS Linux market
    1

    Is a dereferenced reference not equal to the original variable?

    I'm going through the interactive version of The Book, and I'm confused by the results of an exercise in Ch 4.3 - Fixing Ownership Errors.

    The following code does not work, and they say it's because it would result in the same heap space being deallocated twice:

    rust fn main() { let s = String::from("Hello world"); let s_ref = &s; // reference s let s2 = *s_ref; // dereference s_ref println!("{s2}"); }

    But in my mind, this should be equivalent to the following compilable code, which transfers ownership of s to s2 :

    rust fn main() { let s = String::from("Hello world"); let s_ref = &s; // reference s let s2 = s; // move s directly println!("{s2}"); }

    If s_ref is a reference to s, then dereferencing s_ref should return the String s, shouldn't it? Why can't s be moved to s2 with either the above code or let s2 = *&s;, which fails in the same way?

    4