• 0 Posts
  • 48 Comments
Joined 1 year ago
cake
Cake day: January 13th, 2024

help-circle
  • Is this a new build, or an existing building?

    If it’s an existing building, with an existing HOA, then it should already have a bank account? (Probably with funds in it!)

    If it’s new, build up an emergency fund, but leave it in a bank. putting it into stocks is crazy, it’s an emergancy/maintenance fund, you need to know how much is there, trust it’s not going to just disappear and be able to access it quickly.

    Make sure you understand the voting rights and who has authority to access the money if there is going to be a significant sum in there.








  • C#

    I had an error in the escape clause of the recursion that stumped me for a bit - wasn’t counting the last towel!

    This might be the first time I have ever had to use a long/ulong in 9 years of C# dev! (corp dev is obviously boring)

    spoiler

    using System.Collections.Concurrent;

    namespace AoC2024.day_19;

    public class Day19 { private ConcurrentDictionary<string,ulong> _cachedPossibilities = new ConcurrentDictionary<string, ulong>();

    public void GoPart1()
    {
        var inputText = File.ReadAllText("\\AdventOfCode2024\\AoC\\src\\day_19\\input.txt");
        var availableTowels = GetAvailableTowels(inputText);
        var requiredPatterns = GetTargetPatterns(inputText);
        int reachablePatterns = 0;
        
        foreach (var targetPattern in requiredPatterns)
        {
            var result = DoTowelsMatch(targetPattern, availableTowels);
    
            if (result.Item1)
            {
                reachablePatterns++;
                Console.WriteLine($"Target pattern {targetPattern} can be reached with the following towels: {result.Item2.Aggregate("",(s, s1) => $"{s},{s1}")}");
            }
            else
            {
                Console.WriteLine($"Target pattern {targetPattern} can't be reached");
            }
        }
        
        Console.WriteLine($"reachable patterns: {reachablePatterns}");
    }
    
    public void GoPart2()
    {
        var inputText = File.ReadAllText("\\AdventOfCode2024\\AoC\\src\\day_19\\input.txt");
        //var inputText = File.ReadAllText("\\AdventOfCode2024\\AoC\\src\\day_19\\testInput.txt");
        var availableTowels = GetAvailableTowels(inputText);
        var requiredPatterns = GetTargetPatterns(inputText);
        ulong patternCount = 0;
        
        var tasks = new List<Task<ulong>>();
        
       // requiredPatterns = requiredPatterns.Take(5).ToList();
        
        
        foreach (var targetPattern in requiredPatterns)
        {
            var task = new Task<ulong>(() =>
            {
                Console.WriteLine(targetPattern);
                ulong taskPatternCount = 0;
                var result = DoTowelsMatch2(targetPattern, availableTowels);
    
                if (result.Item1)
                {
                    taskPatternCount = result.Item2;
                    Console.WriteLine($"Target pattern {targetPattern} can be reached with {result.Item2} permutations");
                }
                else
                {
                    Console.WriteLine($"Target pattern {targetPattern} can't be reached");
                }
    
                return taskPatternCount;
            });
            
            task.Start();
            tasks.Add(task);
        }
    
        Task.WaitAll(tasks);
    
        tasks.ForEach(task => patternCount += task.Result);
        Console.WriteLine($"{tasks.Count(task => task.Result > 0)} of the patterns were achieved");
        
        Console.WriteLine($"reachable patterns: {patternCount}");
    }
    
    private (bool,ulong) DoTowelsMatch2(string targetPattern, List<string> towelPatterns)
    {
        ulong possiblePatternCount = 0;
       
        if (_cachedPossibilities.ContainsKey(targetPattern))
        {
            _cachedPossibilities.TryGetValue(targetPattern, out possiblePatternCount);
            return (possiblePatternCount > 0,possiblePatternCount);
        }
        
        foreach (var towelPattern in towelPatterns)
        {
            if (targetPattern.StartsWith(towelPattern))
            {
                var newTargetPattern = targetPattern.Substring(towelPattern.Length);
    
                if (string.IsNullOrEmpty(newTargetPattern))
                {
                    possiblePatternCount++;
                    continue;
                }
                
                var doTowelsMatchResult = DoTowelsMatch2(newTargetPattern, towelPatterns);
                if (doTowelsMatchResult.Item1)
                {
                    possiblePatternCount += doTowelsMatchResult.Item2;
                }
            }
        }
    
        _cachedPossibilities.TryAdd(targetPattern, possiblePatternCount);
        
        return (possiblePatternCount>0,possiblePatternCount);
    }
    
    private (bool,List<string>?) DoTowelsMatch(string targetPattern, List<string> towelPatterns)
    {
        foreach (var towelPattern in towelPatterns)
        {
            if (targetPattern.StartsWith(towelPattern))
            {
                var newTargetPattern = targetPattern.Substring(towelPattern.Length);
    
                if (string.IsNullOrEmpty(newTargetPattern))
                {
                    return (true, new List<string>(){ towelPattern });
                }
                
                var doTowelsMatchResult = DoTowelsMatch(newTargetPattern, towelPatterns);
                if (doTowelsMatchResult.Item1)
                {
                    doTowelsMatchResult.Item2.Insert(0, towelPattern);
                    return (true, doTowelsMatchResult.Item2);
                }
            }
        }
    
        return (false,null);
    }
    
    private List<string> GetAvailableTowels(string input)
    {
        return input.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries).First().Split(',', StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToList();
    }
    
    private List<string> GetTargetPatterns(string input)
    {
        var lines = input.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries).ToList();
        lines.RemoveAt(0);
        return lines.Select(s => s.Trim()).ToList();
    }
    

    }


  • C#

    I did flood fill because i normally just do Dijkstra for this kind of stuff. watching the map print as it flooded was cool, had to disable it for part two though as it was too slow. Just let it run while I made a cup of tea instead of doing a binary search.

    spoiler

    namespace AoC2024.Day_18;

    public class Day18 {

    public const string CLEAR = ".";
    public const string BLOCKED = "#";
    public const string TRAVELED = "O";
    
    public void Go()
    {
        var testGrid = GenerateGrid(71, 71);
        PrintGrid(testGrid);
        var coords = GetInputCoordinates(File.ReadAllText("\\AdventOfCode2024\\AoC\\src\\Day_18\\input.txt"));
        
        testGrid = ApplyCoords(testGrid, coords.Take(1024).ToList(), BLOCKED);
        PrintGrid(testGrid);
        FloodFillGrid(testGrid, new Coordinate(0,0), new (70,70));
    }
    
    public void GoPart2()
    {
        var testGrid = GenerateGrid(71, 71);
        PrintGrid(testGrid);
        var coords = GetInputCoordinates(File.ReadAllText("\\AdventOfCode2024\\AoC\\src\\Day_18\\input.txt"));
    
        for (int i = 1; i <= coords.Count; i++)
        {
            testGrid = ApplyCoords(testGrid, coords.Take(i).ToList(), BLOCKED);
            PrintGrid(testGrid);
            var result = FloodFillGrid(testGrid, new Coordinate(0,0), new (70,70));
            if (result.Item2 == int.MaxValue)
            {
                var badCoord = coords[i - 1];
                Console.WriteLine($"!!!!Coord Number: {i} with a value of ({badCoord.Column},{badCoord.Row}) IS A BLOCKER!!!!");
                break;
            }
            else if (i%100 == 0)
            {
                var goodCoord = coords[i - 1];
                Console.WriteLine($"Coord Number: {i} with a value of ({goodCoord.Column},{goodCoord.Row}) allows an exit in {result.Item2} steps");
            }
        }
    }
    
    public List<List<string>> GenerateGrid(int width, int height)
    {
        var grid = new List<List<string>>();
        for (int i = 0; i < height; i++)
        {
            var row = new List<string>();
            for (int j = 0; j < width; j++)
            {
                row.Add(CLEAR);
            }
            grid.Add(row);
        }
    
        return grid;
    }
    
    public void PrintGrid(List<List<string>> grid)
    {
        // foreach (var row in grid)
        // {
        //     foreach (var value in row)
        //     {
        //         Console.Write($" {value} ");
        //     }
        //     Console.WriteLine();
        // }
    }
    
    public List<List<string>> ApplyCoords(List<List<string>> grid, List<Coordinate> coordinates, string value)
    {
        foreach (var coord in coordinates)
        {
            grid[coord.Row][coord.Column] = value;
        }
    
        return grid;
    }
    
    public List<Coordinate> GetInputCoordinates(string input)
    {
        var coords = new List<Coordinate>();
        foreach (var pair in input.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries))
        {
            var values = pair.Split(',', StringSplitOptions.RemoveEmptyEntries);
            coords.Add(new Coordinate(values[1], values[0]));
        }
    
        return coords;
    }
    
    public (List<List<string>>, int) FloodFillGrid(List<List<string>> grid, Coordinate start, Coordinate target)
    {
        var newGrid = grid.Select(list => new List<string>(list)).ToList();
        var previousGrid = grid;
        newGrid[start.Row][start.Column] = TRAVELED;
        int stepCounter = 0;
        while (newGrid[target.Row][target.Column] != TRAVELED)
        {
            bool valueUpdatedInLoop = false;
            previousGrid = newGrid;
            newGrid = newGrid.Select(list => new List<string>(list)).ToList().ToList();
            
            for (var row = 0; row < grid.Count; row++)
            {
                for (var column = 0; column < grid[row].Count; column++)
                {
                    if (previousGrid[row][column] == CLEAR && IsAdjacentEqual(previousGrid, new Coordinate(row,column), TRAVELED))
                    {
                        newGrid[row][column] = TRAVELED;
                        valueUpdatedInLoop = true;
                    }
                }
            }
            stepCounter++;
    
            if (!valueUpdatedInLoop)
            {
                return (newGrid,int.MaxValue);
            }
            
            //Console.WriteLine($"Step counter: {stepCounter}");
            PrintGrid(newGrid);
            
        }
    
        return (newGrid,stepCounter);
    }
    
    private bool IsAdjacentEqual(List<List<string>> grid, Coordinate location, string value)
    {
        if (location.Row < grid.Count-1 && grid[location.Row+1][location.Column] == value)
        {
            return true;
        }
        
        if (location.Column < grid[0].Count-1 && grid[location.Row][location.Column+1] == value)
        {
            return true;
        }
    
        if (location.Row > 0 && grid[location.Row-1][location.Column] == value)
        {
            return true;
        }
        
        if (location.Column > 0 && grid[location.Row][location.Column-1] == value)
        {
            return true;
        }
    
        return false;
    }
    
    public struct Coordinate
    {
        public Coordinate(int row, int column)
        {
            Row = row;
            Column = column;
        }
        
        public Coordinate(string row, string column)
        {
            Row = int.Parse(row);
            Column = int.Parse(column);
        }
        
        public int Row { get; set; }
        public int Column { get; set; }
    }
    

    }


  • #Rust

    initially, for part two I was trying to ignore a bad pair not a bad value - read the question!

    Only installed Rust on Sunday, day 1 was a mess, today was more controlled. Need to look at some of the rust solutions for std library methods I don’t know about.

    very focussed on getting it to actually compile/work over making it short or nice!

    long!

    `

    pub mod task_2 {

    pub fn task_1(input: &str) -> i32{
        let mut valid_count = 0;
    
        let reports = process_input(input);
    
        for report in reports{
            let valid = is_report_valid(report);
    
            if valid{
                valid_count += 1;
            }
        }
    
        println!("Valid count: {}", valid_count);
        valid_count
    }
    
    pub fn task_2(input: &str) -> i32{
        let mut valid_count = 0;
    
        let reports = process_input(input);
    
        for report in reports{
            let mut valid = is_report_valid(report.clone());
    
            if !valid
            {
                for position_to_delete in 0..report.len()
                {
                    let mut updated_report = report.clone();
                    updated_report.remove(position_to_delete);
                    valid = is_report_valid(updated_report);
    
                    if valid { break; }
                }
            }
    
            if valid{
                valid_count += 1;
            }
        }
    
        println!("Valid count: {}", valid_count);
        valid_count
    }
    
    fn is_report_valid(report:Vec<i32>) -> bool{
        let mut increasing = false;
        let mut decreasing = false;
        let mut valid = true;
    
        for position in 1..report.len(){
            if report[position-1] > report[position]
            {
                decreasing = true;
            }
            else if report[position-1] < report[position]
            {
                increasing = true;
            }
            else
            {
                valid = false;
                break;
            }
    
            if (report[position-1] - report[position]).abs() > 3
            {
                valid = false;
                break;
            }
    
            if increasing && decreasing
            {
                valid = false;
                break;
            }
        }
    
        return valid;
    }
    
    pub fn process_input(input: &str) -> Vec<Vec<i32>>{
        let mut reports: Vec<Vec<i32>> = Vec::new();
        for report_string in input.split("\n"){
            let mut report: Vec<i32> = Vec::new();
            for value in report_string.split_whitespace() {
                report.push(value.parse::<i32>().unwrap());
            }
            reports.push(report);
        }
    
        return reports;
    }
    

    }

    `