Initial Commit

This commit is contained in:
Jose Caban
2025-11-30 20:28:10 -05:00
commit e9ac699e67
209 changed files with 39737 additions and 0 deletions

View File

@@ -0,0 +1,242 @@
using System.Numerics;
var exampleData = new ProblemData("example-input.txt");
var puzzleData = new ProblemData("puzzle-input.txt");
Console.WriteLine("!! === Part01 === !!");
Console.WriteLine("Example root yells: {0}", exampleData.GetMonkeyValuePart01("root"));
Console.WriteLine("Puzzle root yells: {0}", puzzleData.GetMonkeyValuePart01("root"));
Console.WriteLine("!! === Part02 === !!");
Console.WriteLine("Example human yells: {0}", exampleData.GetMonkeyValuePart02());
Console.WriteLine("Puzzle human yells: {0}", puzzleData.GetMonkeyValuePart02());
abstract class MonkeyCommand
{
public MonkeyCommand(string name)
{
Name = name;
}
public abstract BigInteger GetValue();
public string Name { get; protected set; }
public static bool DebugPrint { get; set; } = false;
}
class MonkeyYellCommand
: MonkeyCommand
{
public MonkeyYellCommand(string name, BigInteger val)
: base(name)
{
Value = val;
}
public BigInteger Value { get; set; }
public override BigInteger GetValue()
{
return Value;
}
}
class MonkeyMathCommand
: MonkeyCommand
{
public MonkeyMathCommand(string name, Dictionary<string, MonkeyCommand> lookupTable, string left, string right, char op)
: base(name)
{
LookupTable = lookupTable;
Left = left;
Right = right;
if ((op != '-') && (op != '+') && (op != '*') && (op != '/') && (op != '=')) throw new InvalidDataException();
Op = op;
}
public string Left { get; set; }
public string Right { get; set; }
public BigInteger RightValue
{
get
{
return LookupTable[Right].GetValue();
}
}
public BigInteger LeftValue
{
get
{
return LookupTable[Left].GetValue();
}
}
public char Op { get; set; }
public char InverseOp
{
get
{
switch (Op)
{
case '+': return '-';
case '-': return '+';
case '*': return '/';
case '/': return '*';
default: throw new InvalidDataException();
}
}
}
public Dictionary<string, MonkeyCommand> LookupTable { get; set; }
public override BigInteger GetValue()
{
BigInteger left = LeftValue;
BigInteger right = RightValue;
switch (Op)
{
case '+':
return left + right;
case '-':
return left - right;
case '*':
return left * right;
case '/':
return left / right;
case '=':
if (MonkeyCommand.DebugPrint && LookupTable["humn"].GetValue()%10000 == 0) Console.WriteLine("Comparing {0} v {1} with humn {2}", left, right, LookupTable["humn"].GetValue());
return left - right;
default: throw new InvalidDataException();
}
}
}
class ProblemData
{
private Dictionary<string, MonkeyCommand> CommandLookupPart01 { get; set; }
private Dictionary<string, MonkeyCommand> CommandLookupPart02 { get; set; }
public ProblemData(string filename)
{
CommandLookupPart01 = new Dictionary<string, MonkeyCommand>();
CommandLookupPart02 = new Dictionary<string, MonkeyCommand>();
using (StreamReader reader = System.IO.File.OpenText(filename))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (line == null) throw new InvalidDataException();
var split = line.Split(':', StringSplitOptions.TrimEntries);
var name = split[0];
MonkeyCommand monkey, monkey2;
// First see if its a value being yelled by the goddamned monkeys
int val;
if (int.TryParse(split[1], out val))
{
// It's a value monkey
monkey = new MonkeyYellCommand(name, val);
monkey2 = new MonkeyYellCommand(name, val);
}
else
{
// It's a math monkey
var mathline = split[1].Split(' ', StringSplitOptions.RemoveEmptyEntries);
monkey = new MonkeyMathCommand(name, CommandLookupPart01, mathline[0], mathline[2], mathline[1][0]);
char op = mathline[1][0];
if (name == "root")
op = '=';
monkey2 = new MonkeyMathCommand(name, CommandLookupPart02, mathline[0], mathline[2], op);
}
CommandLookupPart01[name] = monkey;
CommandLookupPart02[name] = monkey2;
}
}
}
public BigInteger GetMonkeyValuePart01(string name)
{
return CommandLookupPart01[name].GetValue();
}
public BigInteger GetMonkeyValuePart02()
{
MonkeyMathCommand rootCmd = (MonkeyMathCommand)CommandLookupPart02["root"];
// Find the side the human is on
bool isHumanOnLeft = IsHumanOnLeft(CommandLookupPart02, rootCmd);
BigInteger targetValue;
if (isHumanOnLeft)
{
targetValue = rootCmd.RightValue;
}
else
{
targetValue = rootCmd.LeftValue;
}
var humnCmd = (MonkeyYellCommand)CommandLookupPart02["humn"];
BigInteger result = 0;
BigInteger high = long.MaxValue, low = long.MinValue;
BigInteger mid = low + (high - low) / 2;
bool incrementUp = false;
humnCmd.Value = 1;
var first = isHumanOnLeft ? rootCmd.LeftValue : rootCmd.RightValue;
humnCmd.Value = 100;
var second = isHumanOnLeft ? rootCmd.LeftValue : rootCmd.RightValue;
if (second > first) incrementUp = true;
while ((isHumanOnLeft ? rootCmd.LeftValue : rootCmd.RightValue) != targetValue)
{
humnCmd.Value = mid;
var newVal = isHumanOnLeft ? rootCmd.LeftValue : rootCmd.RightValue;
if ((incrementUp && (newVal > targetValue)) || (!incrementUp && (newVal < targetValue)))
{
high = low + (high - low) / 2;
}
else
{
low = low + (high - low) / 2;
}
mid = low + (high - low) / 2;
}
return CommandLookupPart02["humn"].GetValue();
}
private static bool IsHumanOnLeft(Dictionary<string,MonkeyCommand> dict, MonkeyMathCommand command)
{
MonkeyYellCommand humnCmd = (MonkeyYellCommand)dict["humn"];
var ogRight = command.RightValue;
var ogLeft = command.LeftValue;
humnCmd.Value += 10;
var newRight = command.RightValue;
var newLeft = command.LeftValue;
humnCmd.Value -= 10;
if (ogLeft == newLeft) return false;
else if (ogRight == newRight) return true;
else throw new InvalidDataException();
}
}