

You can do basic 5 man content with AI players nowadays.
You can do basic 5 man content with AI players nowadays.
Webassemby is still limited to a single thread as far as I’m aware, so it’s not a full runtime for the language you are writing in as anything using threads behind the scenes tends to fall over unexpectedly at runtime.
Its also an absolute bastard to debug (young ecosystem)
It depends who you are trying to hide from. A VPN will hide your internet traffic from your ISP/phone company, but obviously not from the site you are visiting.
At best you might be one of may people connecting from the same (VPN) IP address, but they can still collect info from your browser/app etc to generate points to ID you if they want.
If you are a company looking for a forum, you want to be able to control it. Unfederated means you can control account access and don’t have to worry about someone going to All and seeing porn etc.
Federated could work, but you need to make it clear that it’s just a community on a platform.
You could force latest comment sort on the posts, but leave the comments sorting to the user.
The Reddit style voting/threading is superior of forums though.
An unfederated Lemmy instance for example would actually be really good.
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)
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();
}
}
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.
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!
`
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;
}
}
`
One I made up for a caster who always missed their rolls was a sentient wizards hat ‘clippy’. “I see you were trying to cast Eldrich Blast, do you need help with that” and occasionally giving them advantage (they really were rolling awfully)
I was bad at RPing it though and that campaign ended shortly after anyway
That would be wisdom! I tend to let it do that too as it’s funny
A funny one i found on Reddit:
Glasses of hindsight: provide a passive perception of 20 of events suitably far in the past
Be careful with magic items, I let my guys buy a trident of fish command… In a desert. But it turns out lots of snakes etc have a swim speed…
There was that video from a few months ago from… Prints with layers I think? That looked at the actual particulate and volatile counts and found that PLA actually gave off very little? Other plastics were much worse.
So remember that the particle counts matter as much as the danger of the particles.
(Disclaimer, that was a video, not a peer reviewed scientific paper)
They have no exhaust visible and where shown as off on the display.
extremely impressive - the atmospheric heating on the bottom as it came is was scary though!
(no engines lit here!)
Have they fixed their performance issues? They did a engine update just before Helldivers release that trashed the performance. (Awful timing)
Helldivers is now fulfilling my coop shooter needs, never really liked the base building elements of ST:E
There are ‘keyboards’ that when plugged in type Win+R CMD.exe then do whatever you want. (Other terminals are available)
I guess that stops users from trying in the first place though.
I don’t understand why they can’t restore from a backup. Sure, it may restore things that no longer were in the bank when it was lost, but it’s Blizzard’s screw up.
It’s the guild bank, so it can’t hold soulbound items etc that could actually have mechanical issues with dupes.
Blocks is relative - I think they had some issues
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.