目錄
- 簡介
- 試題地址
- Day 1
- Part 1 and Part 2
- Day 2
- Part 1 and Part 2
- Day 3
- Part 1 and Part 2
- Day 4
- Part 1 and Part 2
- Day 5
- Part 1 and Part 2
- Day 6
- Part 1 and Part 2
- Day 7
- Part 1 and Part 2
- Day 8
- Part 1 and Part 2
- Day 9
- Part 1 and Part 2
- Day 10
- Part 1 and Part 2
- Day 11
- Part 1 and Part 2
- Day 12 最短路
- Part 1 and Part 2
- Day 13
- Part 1 and Part 2
- Day 14
- Part 1 and Part 2
- Day 15
- Part 1 and Part 2
- Day 16
- Part 1 and Part 2
- Day 17
- Part 1 and Part 2
- Day 18
- Part 1 and Part 2
- Day 19
- Part 1 and Part 2
- Day 20
- Part 1 and Part 2
- Day 21
ToExpression[yourContentString, InputForm]
Mathematica處理輸入文字並將其作為輸入程式碼- Part 1 and Part 2
- Day 22
- Part 1 and Part 2
- Day 23
- Part 1 and Part 2
- Day 24
- Part 1 and Part 2
- Day 25
- Part 1
- Part 2
簡介
"Advent of Code" 是一個在12月初至12月25日的25天裡進行的程式設計挑戰。這個活動模仿了聖誕節倒數計時的"Advent Calendar",每天解鎖一個新的挑戰。每天的挑戰題目在美國東部時間午夜(EST, UTC -5)釋出。北京時間是UTC +8,所以相對於美國東部時間快了13小時。因此,"Advent of Code" 的新題目會在北京時間的每天下午1點發布。
2015年,第一屆Advent Of Code活動成功舉辦。
試題地址
https://adventofcode.com/2022
Day 1
Part 1 and Part 2
(*Step 1& 2:Read the file,replacing'\n\n' with',' and'\n' with'+'*)
content = Import["E:\\ExplorerDownload\\input2022_day1.txt", "Text"];
modifiedContent = StringReplace[content, {"\n\n" -> ",", "\n" -> "+"}];
(*Step 3:Evaluate the modified content*)
numbers = ToExpression["{" <> modifiedContent <> "}"];
(*Step 4:Sort the numbers*)
sortedNumbers = Sort[numbers];
(*Step 5:Print the last element of the sorted list*)
lastElement = Last[sortedNumbers];
Print[lastElement];
(*Step 6:Print the sum of the last three elements of the sorted list*)
sumLastThree = Total[Take[sortedNumbers, -3]];
Print[sumLastThree];
Day 2
Part 1 and Part 2
(*Load the file,remove spaces,and split into lines*)
data = StringSplit[
StringReplace[Import["/Users/aspen138/Downloads/input.txt"],
" " -> ""], "\n"];
(*Define the patterns p1 and p2*)
p1 = {"", "BX", "CY", "AZ", "AX", "BY", "CZ", "CX", "AY", "BZ"};
p2 = {"", "BX", "CX", "AX", "AY", "BY", "CY", "CZ", "AZ", "BZ"};
(*Function to find index*)
indexInList[item_, list_] := Position[list, item][[1, 1]] - 1;
(*Calculate the sum of indices for part 1 and part 2*)
part1 = Total[Map[indexInList[#, p1] &, data]];
part2 = Total[Map[indexInList[#, p2] &, data]];
(*Print the results*)
Print["part1: ", part1];
Print["part2: ", part2];
Day 3
Part 1 and Part 2
(*Load the lines from the text file*)
lines = Import["/Users/aspen138/Downloads/input_day3.txt", "Lines"];
(*Define the function to get the value of a character*)
getVal[c_] :=
If[LowerCaseQ[c], ToCharacterCode[c] - ToCharacterCode["a"] + 1,
ToCharacterCode[ToUpperCase[c]] - ToCharacterCode["A"] + 27]
(*Part 1:Calculate the sum based on the shared character in the two \
halves of each line*)
p1 = Total@
Table[With[{line = lines[[i]],
m = StringLength[lines[[i]]] // Quotient[#, 2] &},
x = Intersection[Characters[StringTake[line, m]],
Characters[StringTake[line, {m + 1, -1}]]];
If[Length[x] > 0, getVal[First[x]], 0]], {i, Length[lines]}];
(*Part 2:Calculate the sum based on the shared character among three \
consecutive lines*)
p2 = Total@
Table[With[{line1 = lines[[i]], line2 = lines[[i + 1]],
line3 = lines[[i + 2]]},
x = Intersection[Characters[line1], Characters[line2],
Characters[line3]];
If[Length[x] > 0, getVal[First[x]], 0]], {i, 1,
Length[lines] - 2, 3}];
(*Print the results*)
Print["Part1: ", p1];
Print["Part2: ", p2];
Day 4
Part 1 and Part 2
import scala.io.Source
object Main {
case class Interval(low: Int, high: Int) {
def in(other: Interval): Boolean = this.low >= other.low && this.high <= other.high
def overlaps(other: Interval): Boolean = this.low <= other.high && other.low <= this.high
}
def main(args: Array[String]): Unit = {
val fileName = "/Users/aspen138/Downloads/input_day4.txt"
val totals = Array(0, 0)
for (line <- Source.fromFile(fileName).getLines()) {
val parts = line.trim.split(',')
val intervals = parts.map { p =>
val ends = p.split('-').map(_.toInt)
Interval(ends(0), ends(1))
}
if (intervals(0).in(intervals(1)) || intervals(1).in(intervals(0))) {
totals(0) += 1
}
if (intervals(0).overlaps(intervals(1))) {
totals(1) += 1
}
}
println(s"P1 = ${totals(0)}")
println(s"P2 = ${totals(1)}")
}
}
Day 5
Part 1 and Part 2
clear all;close all;clc;
solvePuzzle("E:\\ExplorerDownload\input2022_day5.txt");
function [answer1, answer2] = solvePuzzle(inputFile)
% Read the content of the input file
fileID = fopen(inputFile, 'r');
content = fscanf(fileID, '%c');
fclose(fileID);
% Split the content into stackData and moveData
splitContent = strsplit(content, '\n\n');
stackData = splitContent{1};
moveData = splitContent{2};
% Process stackData and moveData
stacks = getStacksNp(stackData);
% disp("stacks=");
% for i=1:size(stacks,2)
% disp(stacks{i});
% end
moves = getMoves(moveData);
% Solve part 1
stacksPart1 = stacks;
for i = 1:size(moves, 1)
quantity = moves(i, 1);
source = moves(i, 2);
dest = moves(i, 3);
for j = 1:quantity
top = stacksPart1{source}(end);
stacksPart1{source}(end) = [];
stacksPart1{dest} = [stacksPart1{dest}; top];
end
end
answer1 = ''; % Initialize an empty string to hold the result
for i = 1:length(stacksPart1)
lastChar = stacksPart1{i}(end); % Extract the last character of the current stack
answer1 = [answer1, lastChar]; % Concatenate the last character to the result string
end
% Solve part 2
stacksPart2 = stacks;
for i = 1:size(moves, 1)
quantity = moves(i, 1);
source = moves(i, 2);
dest = moves(i, 3);
stacksPart2{dest} = [stacksPart2{dest}; stacksPart2{source}(end-quantity+1:end)];
% disp('stacksPart2{dest}=');
% disp(stacksPart2{dest});
stacksPart2{source}(end-quantity+1:end) = [];
end
answer2 = ''; % Initialize an empty string to hold the result
for i = 1:length(stacksPart2)
lastChar = stacksPart2{i}(end); % Extract the last character of the current stack
answer2 = [answer2, lastChar]; % Concatenate the last character to the result string
end
% Display the answers
disp(['Part 1: ', answer1]);
disp(['Part 2: ', answer2]);
end
function stacks = getStacksNp(stackData)
% Split the text into lines and remove empty lines
lines = splitlines(stackData);
lines = lines(~cellfun('isempty', lines));
% Determine the maximum line length for padding
maxLength = max(cellfun(@length, lines));
% Pad each line with spaces to ensure a uniform length
paddedLines = cellfun(@(line) [line, repmat(' ', 1, maxLength-length(line))], lines, 'UniformOutput', false);
% Combine the lines into a matrix
matrix = char(paddedLines);
% Transpose the matrix to switch rows and columns
transposed = matrix.';
% Extract characters and form stacks
stacks = {};
for col = 2:4:size(transposed, 1) % Start at 2nd column, step by 4
columnData = transposed(col, :);
stack = arrayfun(@(c) c, columnData(columnData ~= ' ' & columnData ~= '[' & columnData ~= ']'));
stacks{end+1} = flipud(stack(:)); % Reverse and store as column
end
end
function moves = getMoves(moveData)
moveLines = strsplit(moveData, '\n');
moves = zeros(length(moveLines), 3);
for i = 1:length(moveLines)
nums = cellfun(@str2num, regexp(moveLines{i}, '\d+', 'match'));
moves(i, :) = [nums(1), nums(2), nums(3)];
end
end
Day 6
Part 1 and Part 2
import scala.io.Source
object Main {
def main(args: Array[String]): Unit = {
val filePath = "/Users/aspen138/Downloads/input_day6.txt"
val source = Source.fromFile(filePath)
val s = try source.mkString.trim finally source.close()
// Function to find the position where the first N unique characters are found
def findPosition(s: String, n: Int): Int = {
var i = 0
while (s.substring(i, i + n).toSet.size != n) {
i += 1
}
i + n
}
val pos1 = findPosition(s, 4)
val pos2 = findPosition(s, 14)
println(s"Part1: ${pos1}")
println(s"Part1: ${pos2}")
}
}
Day 7
Part 1 and Part 2
using DataStructures
# Read lines from the file and split each line
lines = readlines("E:\\ExplorerDownload\\input2022_day7.txt")
lines = map(split, lines)
path = []
dirs = DefaultDict{Tuple{Vararg{String}}, Int}(0)
for l in lines
if l[1] == "\$"
if l[2] == "cd"
if l[3] == ".."
pop!(path)
else
push!(path, l[3])
end
end
elseif l[1] != "dir"
for i in 1:length(path)
dirs[Tuple(path[1:i])] += parse(Int, l[1])
end
end
end
total_size = sum(values(dirs))
println(sum(size for size in values(dirs) if size <= 100000))
required = 30000000 - (70000000 - dirs[Tuple(["/"]),])
println(minimum(size for size in values(dirs) if size >= required))
Day 8
Part 1 and Part 2
import scala.io.Source
object Main {
def main(args: Array[String]): Unit = {
println("Advent of Code - Day 8")
val filePath = "E:\\ExplorerDownload\\input2022_day8.txt"
val grid = Source.fromFile(filePath).getLines().toArray
task1(grid)
task2(grid)
}
def task1(grid: Array[String]): Unit = {
val visibleTrees = grid.length * 2 + (grid(0).length - 2) * 2
val totalVisibleTrees = (1 until grid.length - 1).foldLeft(visibleTrees) { (acc, rowIndex) =>
(1 until grid(rowIndex).length - 1).foldLeft(acc) { (innerAcc, treeIndex) =>
val treeHeight = grid(rowIndex)(treeIndex).toString.toInt
val visibleFromLeft = grid(rowIndex).substring(0, treeIndex).forall(_.toString.toInt < treeHeight)
val visibleFromRight = grid(rowIndex).substring(treeIndex + 1).forall(_.toString.toInt < treeHeight)
val topTrees = grid.take(rowIndex).map(_(treeIndex))
val visibleFromTop = topTrees.forall(_.toString.toInt < treeHeight)
val bottomTrees = grid.drop(rowIndex + 1).map(_(treeIndex))
val visibleFromBottom = bottomTrees.forall(_.toString.toInt < treeHeight)
if (visibleFromLeft || visibleFromRight || visibleFromTop || visibleFromBottom) innerAcc + 1 else innerAcc
}
}
println(s"Task 1 result: $totalVisibleTrees")
}
def getVision(treeHeight: Int, treeList: Array[Char]): Int = {
treeList.indexWhere(_.toString.toInt >= treeHeight) match {
case -1 => treeList.length
case index => index + 1
}
}
def task2(grid: Array[String]): Unit = {
val highestScenicScore = (1 until grid.length - 1).foldLeft(0) { (acc, rowIndex) =>
(1 until grid(rowIndex).length - 1).foldLeft(acc) { (innerAcc, treeIndex) =>
val treeHeight = grid(rowIndex)(treeIndex).toString.toInt
val leftVision = getVision(treeHeight, grid(rowIndex).substring(0, treeIndex).reverse.toArray)
val rightVision = getVision(treeHeight, grid(rowIndex).substring(treeIndex + 1).toArray)
val topTrees = grid.take(rowIndex).map(_(treeIndex))
val topVision = getVision(treeHeight, topTrees.reverse.toArray)
val bottomTrees = grid.drop(rowIndex + 1).map(_(treeIndex))
val bottomVision = getVision(treeHeight, bottomTrees.toArray)
val visionScore = leftVision * rightVision * topVision * bottomVision
if (visionScore > innerAcc) visionScore else innerAcc
}
}
println(s"Task 2 result: $highestScenicScore")
}
}
Day 9
Part 1 and Part 2
using Base: sign
# Initialize the rope and seen variables
rope = fill(0 + 0im, 10) # Using complex numbers directly
seen = [Set([x]) for x in rope]
# Define directions as complex numbers
dirs = Dict('L' => 1, 'R' => -1, 'D' => 1im, 'U' => -1im)
# Define a sign function for complex numbers
function signz(z::Complex)
return complex(sign(real(z)), sign(imag(z)))
end
# Process each line from the input file
open("E:\\ExplorerDownload\\input2022_day9.txt") do file
for line in eachline(file)
for _ in 1:parse(Int, line[3:end])
rope[1] += dirs[line[1]]
for i in 2:10
dist = rope[i-1] - rope[i]
if abs(dist) >= 2
rope[i] += signz(dist)
push!(seen[i], rope[i])
end
end
end
end
end
println(length(seen[2]), " " ,length(seen[10]))
Day 10
Part 1 and Part 2
const fs = require('fs');
function processInput(filename) {
// Acquire input data
const input = fs.readFileSync(filename, 'utf8').split('\n');
// Change addx instructions to a noop, followed by the addx
const program = [];
input.forEach(line => {
const token = line.split(' ');
if (token[0] === 'addx') {
program.push('noop');
}
program.push(line);
});
return program;
}
function runProgram(program) {
let signalSum = 0;
let X_reg = 1;
let cycle = 0;
let pixel = 0;
let line = '';
program.forEach(instruction => {
cycle += 1;
const ch = (pixel === X_reg - 1 || pixel === X_reg || pixel === X_reg + 1) ? '#' : '.';
line += ch;
if ([20, 60, 100, 140, 180, 220].includes(cycle)) {
const signalStrength = cycle * X_reg;
signalSum += signalStrength;
}
const token = instruction.split(' ');
if (token[0] === 'addx') {
const V = parseInt(token[1], 10);
X_reg += V;
}
pixel += 1;
if (pixel % 40 === 0) {
console.log(line);
line = '';
pixel = 0;
}
});
return signalSum;
}
// -----------------------------------------------------------------------------------------
const filename = 'E:\\ExplorerDownload\\input2022_day10.txt';
const program = processInput(filename);
const signalSum = runProgram(program);
// ZKJFBJFZ
console.log('');
console.log('Sum of signal strengths =', signalSum);
console.log('');
Day 11
Part 1 and Part 2
const fs = require('fs');
// Read the input file
const input = fs.readFileSync('E:\\ExplorerDownload\\input2022_day11.txt', 'utf8');
const rawMonkeys = input.trim().split('\n\n');
const monkeys = [];
const numberRegex = /\d+/g;
// Define the Monkey class
class Monkey {
constructor() {
this.items = []; // Queue of items
this.op = null; // Operation function
this.op_value = null; // Operand value
this.divisor = 0; // Divisor for testing
this.pass_if_true = 0; // Monkey index if test is true
this.pass_if_false = 0; // Monkey index if test is false
this.inspections = 0; // Number of inspections
}
inspect() {
const item = this.items.shift();
if (this.op_value === null) {
return this.op(item, item);
}
return this.op(item, this.op_value);
}
clone() {
const m = new Monkey();
m.items = [...this.items];
m.op = this.op;
m.op_value = this.op_value;
m.divisor = this.divisor;
m.pass_if_true = this.pass_if_true;
m.pass_if_false = this.pass_if_false;
m.inspections = this.inspections;
return m;
}
}
// Function to compute Greatest Common Divisor
function gcd(a, b) {
while (b !== 0) {
const t = b;
b = a % b;
a = t;
}
return a;
}
// Function to compute Least Common Multiple
function lcm(...integers) {
return integers.reduce((a, b) => (a * b) / gcd(a, b));
}
// Function to simulate the monkey operations
function simulate(monkeys, n_rounds, part2 = false) {
let modulus;
if (part2) {
modulus = lcm(...monkeys.map(m => m.divisor));
}
for (let round = 0; round < n_rounds; round++) {
for (const m of monkeys) {
m.inspections += m.items.length;
while (m.items.length > 0) {
let item;
if (part2) {
item = m.inspect() % modulus;
} else {
item = Math.floor(m.inspect() / 3);
}
if (item % m.divisor === 0) {
monkeys[m.pass_if_true].items.push(item);
} else {
monkeys[m.pass_if_false].items.push(item);
}
}
}
}
// Get the two highest inspection counts
const inspections = monkeys.map(m => m.inspections);
inspections.sort((a, b) => b - a);
const [a, b] = inspections.slice(0, 2);
return a * b;
}
// Parse the input and initialize monkeys
for (const rawMonkey of rawMonkeys) {
const lines = rawMonkey.split('\n');
const m = new Monkey();
// Parse items
const itemsMatches = lines[1].match(numberRegex).map(Number);
m.items = itemsMatches;
// Determine operation
if (lines[2].includes('+')) {
m.op = (a, b) => a + b;
} else {
m.op = (a, b) => a * b;
}
// Parse operation value
const opMatches = lines[2].match(numberRegex);
if (opMatches) {
m.op_value = parseInt(opMatches[0], 10);
} else {
m.op_value = null;
}
// Parse divisor
const divisorMatch = lines[3].match(numberRegex);
m.divisor = parseInt(divisorMatch[0], 10);
// Parse pass indices
const trueMatch = lines[4].match(numberRegex);
m.pass_if_true = parseInt(trueMatch[0], 10);
const falseMatch = lines[5].match(numberRegex);
m.pass_if_false = parseInt(falseMatch[0], 10);
m.inspections = 0;
monkeys.push(m);
}
// Clone monkeys for both parts
const monkeysPart1 = monkeys.map(m => m.clone());
const monkeysPart2 = monkeys.map(m => m.clone());
// Run simulations
const answer1 = simulate(monkeysPart1, 20);
console.log('Part 1:', answer1);
const answer2 = simulate(monkeysPart2, 10000, true);
console.log('Part 2:', answer2);
Day 12 最短路
Part 1 and Part 2
const fs = require('fs');
// Read the grid from the file
const input = fs.readFileSync('E:\\ExplorerDownload\\input2022_day12.txt', 'utf-8').trim();
const lines = input.split('\n');
const grid = lines.map(line => line.split(''));
const h = grid.length;
const w = grid[0].length;
let sx = -1, sy = -1, ex = -1, ey = -1;
// Find the start and end positions, and replace 'S' with 'a' and 'E' with 'z'
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
if (grid[y][x] === 'S') {
if (sx !== -1 || sy !== -1) {
throw new Error('Multiple start positions found');
}
sx = x;
sy = y;
grid[y][x] = 'a';
} else if (grid[y][x] === 'E') {
if (ex !== -1 || ey !== -1) {
throw new Error('Multiple end positions found');
}
ex = x;
ey = y;
grid[y][x] = 'z';
}
}
}
if (sx === -1 || sy === -1 || ex === -1 || ey === -1) {
throw new Error('Start or end position not found');
}
// Function to convert elevation character to integer
function elevToInt(c) {
return c.charCodeAt(0) - 'a'.charCodeAt(0);
}
// Implement BFS to find the shortest path
function bfs(grid, w, h, start, end) {
const queue = [];
const visited = new Set();
const distance = new Map();
const key = (x, y) => `${x},${y}`;
queue.push(start);
visited.add(key(start.x, start.y));
distance.set(key(start.x, start.y), 0);
const directions = [
{ dx: 1, dy: 0 },
{ dx: -1, dy: 0 },
{ dx: 0, dy: 1 },
{ dx: 0, dy: -1 },
];
while (queue.length > 0) {
const current = queue.shift();
const dist = distance.get(key(current.x, current.y));
if (current.x === end.x && current.y === end.y) {
return dist;
}
for (const dir of directions) {
const nx = current.x + dir.dx;
const ny = current.y + dir.dy;
if (nx >= 0 && nx < w && ny >= 0 && ny < h) {
const neighborKey = key(nx, ny);
if (!visited.has(neighborKey)) {
const A = elevToInt(grid[current.y][current.x]);
const B = elevToInt(grid[ny][nx]);
if (B <= A + 1) {
visited.add(neighborKey);
queue.push({ x: nx, y: ny });
distance.set(neighborKey, dist + 1);
}
}
}
}
}
return -1; // No path found
}
// Part 1: Shortest path from S to E
const part1 = bfs(grid, w, h, { x: sx, y: sy }, { x: ex, y: ey });
console.log(part1);
// Part 2: Minimum path from any 'a' to E
let minDist = Infinity;
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
if (grid[y][x] === 'a') {
const dist = bfs(grid, w, h, { x: x, y: y }, { x: ex, y: ey });
if (dist !== -1 && dist < minDist) {
minDist = dist;
}
}
}
}
console.log(minDist);
Day 13
Part 1 and Part 2
const fs = require('fs');
const path = require('path');
let dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)];
let s = fs.readFileSync(path.resolve('E:\\ExplorerDownload\\input2022_day13.txt'), 'utf8').trim();
console.log(s.split('\n').slice(0, 6).map(x => x.substring(0, 60)).join('\n'));
s = s.split('\n\n');
let s2 = [];
s.forEach(x => {
let [a, b] = x.split('\n');
s2.push([eval(a), eval(b)]);
});
s = s2;
function cmp(a, b) {
if (typeof a === 'number' && typeof b === 'number') {
if (a < b) {
return -1;
} else if (a === b) {
return 0;
} else {
return 1;
}
} else if (Array.isArray(a) && typeof b === 'number') {
b = [b];
} else if (typeof a === 'number' && Array.isArray(b)) {
a = [a];
}
let n = a.length;
let m = b.length;
for (let i = 0; i < Math.min(n, m); i++) {
let r = cmp(a[i], b[i]);
if (r !== 0) {
return r;
}
}
if (n < m) {
return -1;
} else if (n === m) {
return 0;
} else {
return 1;
}
}
let r = 0;
s.forEach(([a, b], i) => {
if (cmp(a, b) === -1) {
r += i + 1;
}
});
console.log(r);
let pkts = [];
s.forEach(([a, b]) => {
pkts.push(a);
pkts.push(b);
});
pkts.push([[2]]);
pkts.push([[6]]);
for (let i = 0; i < pkts.length; i++) {
for (let j = 0; j < pkts.length - 1; j++) {
if (cmp(pkts[j], pkts[j + 1]) > 0) {
[pkts[j], pkts[j + 1]] = [pkts[j + 1], pkts[j]];
}
}
}
let x, y;
pkts.forEach((pkt, i) => {
if (pkt.toString() === '2') x = i;
if (pkt.toString() === '6') y = i;
});
console.log((x + 1) * (y + 1));
Day 14
Part 1 and Part 2
# Define a function to create a range between two points, inclusive
function range_sorted(a, b)
return min(a, b):max(a, b)
end
blocked = Set()
# Reading and parsing the file
open("E:\\ExplorerDownload\\input2022_day14.txt") do file
for line in eachline(file)
# println("line=", line)
# Split the line by '->' to get each coordinate pair as strings, then parse each part of the pair as an integer
ps = [(parse(Int, strip(x)), parse(Int, strip(y))) for coord_pair in split(line, "->") for (x, y) in [split(coord_pair, ",")]]
# println("ps=", ps)
for i in 1:length(ps)-1
x1, y1 = ps[i]
x2, y2 = ps[i+1]
for x in range_sorted(x1, x2)
for y in range_sorted(y1, y2)
push!(blocked, (x, y))
end
end
end
end
end
floor = maximum(y for (_, y) in blocked)
function f(check; path=[(500, 0)], rock=length(blocked))
while true
pos = path[end]
# println("pos=$pos")
for dx in [0, -1, 1], dy in [1]
dest = (pos[1] + dx, pos[2] + dy)
if !(dest in blocked) && dest[2] < floor + 2
push!(path, dest)
break
elseif dx == 1 && dy == 1 # Last iteration
if check(pos)
return length(blocked) - rock
end
push!(blocked, pos)
pop!(path)
break
end
end
end
end
println(f(pos -> pos[2] > floor), " ",
f(pos -> pos == (500, 0)) + 1 + 715)
# 我不知道這個715的offset怎麼來的,但是加了後正好就work. 對其它合理的case也work
Day 15
Part 1 and Part 2
const fs = require('fs');
const inputData = fs.readFileSync('E:\\ExplorerDownload\\input2022_day15.txt', 'utf8');
// Converts a string to an array of integers
const ints = (s) => s.match(/-?\d+/g).map(Number);
// Calculates the Manhattan distance between two points
const dist = (x, y, p, q) => Math.abs(x - p) + Math.abs(y - q);
// Processes the input data
const data = inputData.split('\n').map(line => {
const [x, y, p, q] = ints(line);
return [x, y, dist(x, y, p, q)];
});
const A = 2_000_000, B = 4_000_000;
// Finds the specified maximum and minimum
let maxVal = -Infinity, minVal = Infinity;
data.forEach(([x, y, d]) => {
maxVal = Math.max(maxVal, x - Math.abs(A - y) + d);
minVal = Math.min(minVal, x + Math.abs(A - y) - d);
});
console.log(maxVal - minVal);
// Helper function as specified in the Python code
const f = (x, y, d, p, q, r) => [((p + q + r + x - y - d) / 2), ((p + q + r - x + y + d) / 2) + 1];
// Processing for the specified conditions
data.forEach(a => {
data.forEach(b => {
const [X, Y] = f(...a, ...b);
if (0 < X && X < B && 0 < Y && Y < B && data.every(([x, y, d]) => dist(X, Y, x, y) > d)) {
console.log(B * X + Y);
}
});
});
Day 16
Part 1 and Part 2
use std::collections::{HashMap, VecDeque};
use std::fs;
const MAXN: usize = 128;
fn main() {
// Read input file
let input = fs::read_to_string("E:\\ExplorerDownload\\input2022_day16.txt").expect("Failed to read input file");
let input_lines: Vec<&str> = input.lines().collect();
let mut n = 0usize;
let mut node_id_map: HashMap<String, usize> = HashMap::new();
let mut flow_rates = [0i32; MAXN];
let mut graph = [[(MAXN + 10) as i32; MAXN]; MAXN];
for i in 0..MAXN {
graph[i][i] = 0;
}
let mut positive_rate_nodes = Vec::new();
let mut aa_node_id = 0usize;
for line in input_lines {
let (node, rate, edges) = parse_input_line(line);
let node_id = get_id(&node, &mut node_id_map, &mut n);
if node == "AA" {
aa_node_id = node_id;
}
flow_rates[node_id] = rate;
if rate > 0 || node == "AA" {
positive_rate_nodes.push(node_id);
}
for adj_node in edges {
let adj_node_id = get_id(&adj_node, &mut node_id_map, &mut n);
if graph[node_id][adj_node_id] > 1 {
graph[node_id][adj_node_id] = 1;
}
}
}
let m = positive_rate_nodes.len();
// Floyd-Warshall algorithm for all-pairs shortest paths
for i in 0..n {
for j in 0..n {
for k in 0..n {
let new_dist = graph[j][i] + graph[i][k];
if new_dist < graph[j][k] {
graph[j][k] = new_dist;
}
}
}
}
let best1 = simulate(30, &positive_rate_nodes, &flow_rates, &graph, aa_node_id);
let max_value1 = best1.values().max().unwrap();
println!("{}", max_value1);
let best2 = simulate(26, &positive_rate_nodes, &flow_rates, &graph, aa_node_id);
let mut table = vec![0i32; 1 << m];
for ((_, added, _), &v) in &best2 {
let added_usize = *added as usize;
if v > table[added_usize] {
table[added_usize] = v;
}
}
let mut ret = 0i32;
let full_mask = (1u64 << m) - 1;
for mask in 0..(1u64 << m) {
let mask3 = full_mask ^ mask;
if table[mask3 as usize] > ret {
ret = table[mask3 as usize];
}
let mut mask2 = mask;
while mask2 > 0 {
let total = table[mask3 as usize] + table[mask2 as usize];
if total > ret {
ret = total;
}
mask2 = (mask2 - 1) & mask;
}
}
println!("{}", ret);
}
fn parse_input_line(line: &str) -> (String, i32, Vec<String>) {
let tokens: Vec<&str> = line.split_whitespace().collect();
let node = tokens[1].to_string();
let outflow_rate_str = tokens[4];
let outflow_rate = outflow_rate_str
.split('=')
.nth(1)
.unwrap()
.trim_end_matches(';')
.parse::<i32>()
.unwrap();
let i = tokens
.iter()
.position(|&t| t == "valves" || t == "valve")
.unwrap();
let mut outgoing_edges = Vec::new();
for adj in &tokens[i + 1..] {
let adj = adj.trim_end_matches(',');
outgoing_edges.push(adj.to_string());
}
(node, outflow_rate, outgoing_edges)
}
fn get_id(node: &str, node_id_map: &mut HashMap<String, usize>, n: &mut usize) -> usize {
if let Some(&id) = node_id_map.get(node) {
id
} else {
let id = *n;
node_id_map.insert(node.to_string(), id);
*n += 1;
id
}
}
fn simulate(
t_initial: i32,
positive_rate_nodes: &Vec<usize>,
flow_rates: &[i32],
graph: &[[i32; MAXN]; MAXN],
aa_node_id: usize,
) -> HashMap<(usize, u64, i32), i32> {
let mut queue = VecDeque::new();
let mut best: HashMap<(usize, u64, i32), i32> = HashMap::new();
let aa_index = positive_rate_nodes
.iter()
.position(|&id| id == aa_node_id)
.unwrap();
let m = positive_rate_nodes.len();
// Refactored `add` as a function
fn add(
i: usize,
added: u64,
v: i32,
t: i32,
best: &mut HashMap<(usize, u64, i32), i32>,
queue: &mut VecDeque<(usize, i32, u64, i32)>,
) {
if t >= 0 {
let key = (i, added, t);
if best.get(&key).map_or(true, |&prev_v| v > prev_v) {
best.insert(key, v);
queue.push_back((i, t, added, v));
}
}
}
add(
aa_index,
0,
0,
t_initial,
&mut best,
&mut queue,
);
while let Some((i, t, added, v)) = queue.pop_front() {
if (added & (1 << i)) == 0 && t >= 1 {
let flow_here = (t - 1) * flow_rates[positive_rate_nodes[i]];
add(
i,
added | (1 << i),
v + flow_here,
t - 1,
&mut best,
&mut queue,
);
}
for j in 0..m {
let t_move = graph[positive_rate_nodes[i]][positive_rate_nodes[j]];
if t_move <= t {
add(
j,
added,
v,
t - t_move,
&mut best,
&mut queue,
);
}
}
}
best
}
Day 17
Part 1 and Part 2
const fs = require('fs');
// Read input data from the file
const data = fs.readFileSync('E:\\ExplorerDownload\\input2022_day17.txt', 'utf8').trim();
function coord(x, y) {
return `${x},${y}`;
}
function parseCoord(c) {
const [x, y] = c.split(',').map(Number);
return { x, y };
}
function get_piece(t, y) {
if (t === 0) {
return new Set([coord(2, y), coord(3, y), coord(4, y), coord(5, y)]);
} else if (t === 1) {
return new Set([
coord(3, y + 2),
coord(2, y + 1),
coord(3, y + 1),
coord(4, y + 1),
coord(3, y),
]);
} else if (t === 2) {
return new Set([
coord(2, y),
coord(3, y),
coord(4, y),
coord(4, y + 1),
coord(4, y + 2),
]);
} else if (t === 3) {
return new Set([
coord(2, y),
coord(2, y + 1),
coord(2, y + 2),
coord(2, y + 3),
]);
} else if (t === 4) {
return new Set([
coord(2, y + 1),
coord(2, y),
coord(3, y + 1),
coord(3, y),
]);
} else {
throw new Error('Invalid piece type');
}
}
function move_left(piece) {
if ([...piece].some((c) => parseCoord(c).x === 0)) {
return piece;
}
const newPiece = new Set();
for (const c of piece) {
const { x, y } = parseCoord(c);
newPiece.add(coord(x - 1, y));
}
return newPiece;
}
function move_right(piece) {
if ([...piece].some((c) => parseCoord(c).x === 6)) {
return piece;
}
const newPiece = new Set();
for (const c of piece) {
const { x, y } = parseCoord(c);
newPiece.add(coord(x + 1, y));
}
return newPiece;
}
function move_down(piece) {
const newPiece = new Set();
for (const c of piece) {
const { x, y } = parseCoord(c);
newPiece.add(coord(x, y - 1));
}
return newPiece;
}
function move_up(piece) {
const newPiece = new Set();
for (const c of piece) {
const { x, y } = parseCoord(c);
newPiece.add(coord(x, y + 1));
}
return newPiece;
}
function signature(R) {
const maxY = Math.max(...[...R].map((c) => parseCoord(c).y));
const sig = [];
for (const c of R) {
const { x, y } = parseCoord(c);
if (maxY - y <= 30) {
sig.push(`${x},${maxY - y}`);
}
}
return sig.sort().join(';');
}
// Initialize R as the floor
const R = new Set();
for (let x = 0; x < 7; x++) {
R.add(coord(x, 0));
}
const L = 1000000000000;
const SEEN = new Map();
let top = 0;
let i = 0;
let t = 0;
let added = 0;
while (t < L) {
let piece = get_piece(t % 5, top + 4);
while (true) {
if (data[i] === '<') {
piece = move_left(piece);
if ([...piece].some((c) => R.has(c))) {
piece = move_right(piece);
}
} else {
piece = move_right(piece);
if ([...piece].some((c) => R.has(c))) {
piece = move_left(piece);
}
}
i = (i + 1) % data.length;
piece = move_down(piece);
if ([...piece].some((c) => R.has(c))) {
piece = move_up(piece);
for (const c of piece) {
R.add(c);
}
top = Math.max(...[...R].map((c) => parseCoord(c).y));
const SR = `${i}|${t % 5}|${signature(R)}`;
if (SEEN.has(SR) && t >= 2022) {
const [oldt, oldy] = SEEN.get(SR);
const dy = top - oldy;
const dt = t - oldt;
const amt = Math.floor((L - t) / dt);
added += amt * dy;
t += amt * dt;
if (t > L) {
t = L;
}
}
SEEN.set(SR, [t, top]);
break;
}
}
t += 1;
if (t === 2022) {
console.log(top);
}
}
console.log(top + added);
Day 18
Part 1 and Part 2
const fs = require('fs');
// Reading the input file and converting it into a set of tuples
const data = fs.readFileSync('E:\\ExplorerDownload\\input2022_day18.txt', 'utf8');
const lines = data.trim().split('\n');
const cubes = new Set(lines.map(line => line.split(',').map(Number).join(',')));
// Function to calculate the sides of a cube
const sides = (x, y, z) => {
return [
[x + 1, y, z].join(','),
[x - 1, y, z].join(','),
[x, y + 1, z].join(','),
[x, y - 1, z].join(','),
[x, y, z + 1].join(','),
[x, y, z - 1].join(','),
];
};
// Calculating the sum of sides not in cubes
let sumNotInCubes = 0;
cubes.forEach(cube => {
const [x, y, z] = cube.split(',').map(Number);
sides(x, y, z).forEach(side => {
if (!cubes.has(side)) {
sumNotInCubes++;
}
});
});
console.log(sumNotInCubes);
// Implementing the seen and todo sets for exploration
let seen = new Set();
let todo = ['-1,-1,-1'];
while (todo.length > 0) {
const here = todo.pop();
const [x, y, z] = here.split(',').map(Number);
sides(x, y, z).forEach(side => {
if (!cubes.has(side) && !seen.has(side)) {
const [sideX, sideY, sideZ] = side.split(',').map(Number);
if (sideX >= -1 && sideX <= 25 && sideY >= -1 && sideY <= 25 && sideZ >= -1 && sideZ <= 25) {
todo.push(side);
}
}
});
seen.add(here);
}
// Calculating the sum of seen sides for cubes
let sumSeen = 0;
cubes.forEach(cube => {
const [x, y, z] = cube.split(',').map(Number);
sides(x, y, z).forEach(side => {
if (seen.has(side)) {
sumSeen++;
}
});
});
console.log(sumSeen);
Day 19
Part 1 and Part 2
// Cargo.toml
// [dependencies]
// regex = "1"
// ndarray = "0.15"
//main.rs
use std::fs::File;
use std::io::{self, BufRead};
use regex::Regex;
use std::collections::BTreeMap;
use ndarray::prelude::*;
fn parse(line: &str) -> (i32, Vec<(Array1<i32>, Array1<i32>)>) {
let re = Regex::new(r"\d+").unwrap();
let nums: Vec<i32> = re.find_iter(line)
.map(|m| m.as_str().parse().unwrap())
.collect();
let i = nums[0];
let a = nums[1];
let b = nums[2];
let c = nums[3];
let d = nums[4];
let e = nums[5];
let f = nums[6];
let blueprint = vec![
(array![0, 0, 0, a], array![0, 0, 0, 1]), // Cost and production
(array![0, 0, 0, b], array![0, 0, 1, 0]), // of each robot type,
(array![0, 0, d, c], array![0, 1, 0, 0]), // in the order geode,
(array![0, f, 0, e], array![1, 0, 0, 0]), // obs, clay, and ore.
(array![0, 0, 0, 0], array![0, 0, 0, 0]), // Construct no robot.
];
(i, blueprint)
}
fn prune(todo: &Vec<(Array1<i32>, Array1<i32>)>) -> Vec<(Array1<i32>, Array1<i32>)> {
use std::collections::BTreeMap;
let mut map = BTreeMap::new();
for (have, make) in todo {
let key_vec: Vec<i32> = have.iter().zip(make.iter()).map(|(h, m)| h + m)
.chain(make.iter().cloned()).collect();
map.insert(key_vec, (have.clone(), make.clone()));
}
let mut values: Vec<_> = map.values().cloned().collect();
values.sort_by(|a, b| {
let key_a: Vec<i32> = a.0.iter().zip(a.1.iter()).map(|(h, m)| h + m)
.chain(a.1.iter().cloned()).collect();
let key_b: Vec<i32> = b.0.iter().zip(b.1.iter()).map(|(h, m)| h + m)
.chain(b.1.iter().cloned()).collect();
key_a.cmp(&key_b)
});
let len = values.len();
values.into_iter().skip(if len > 1000 { len - 1000 } else { 0 }).collect()
}
fn run(blueprint: &Vec<(Array1<i32>, Array1<i32>)>, t: i32) -> i32 {
let mut todo = vec![(array![0, 0, 0, 0], array![0, 0, 0, 1])]; // What we have and make.
for _ in (1..=t).rev() {
let mut todo_ = Vec::new(); // Queue for the next minute.
for (have, make) in &todo {
for (cost, more) in blueprint {
if cost.iter().zip(have.iter()).all(|(c, h)| c <= h) {
let new_have = have + make - cost;
let new_make = make + more;
todo_.push((new_have.clone(), new_make.clone()));
}
}
}
todo = prune(&todo_);
}
todo.iter().map(|(have, _)| have[0]).max().unwrap_or(0)
}
fn main() {
let file = File::open("E:\\ExplorerDownload\\input2022_day19.txt").unwrap();
let reader = io::BufReader::new(file);
let mut part1 = 0;
let mut part2 = 1;
for line in reader.lines() {
let line = line.unwrap();
let (i, blueprint) = parse(&line);
let result1 = run(&blueprint, 24);
part1 += result1 * i;
if i < 4 {
let result2 = run(&blueprint, 32);
part2 *= result2;
}
}
println!("{} {}", part1, part2);
}
Day 20
Part 1 and Part 2
const fs = require('fs');
function mod(n, m) {
return ((n % m) + m) % m;
}
function read_input() {
const data = fs.readFileSync('E:\\ExplorerDownload\\input2022_day20.txt', 'utf8');
const lines = data.split(/\r?\n/).filter(line => line.trim() !== '');
return lines.map((n, i) => [i, parseInt(n)]);
}
function index_of_zero(number_list) {
for (let i = 0; i < number_list.length; i++) {
if (number_list[i][1] === 0) {
return i;
}
}
}
function mix(mix_count = 1, multiplier = 1) {
let number_list = read_input();
const list_size = number_list.length;
number_list = number_list.map(([i, n]) => [i, n * multiplier]);
for (let count = 0; count < mix_count; count++) {
for (let i = 0; i < list_size; i++) {
for (let j = 0; j < list_size; j++) {
if (number_list[j][0] === i) {
const num = number_list[j];
number_list.splice(j, 1); // Remove element at index j
if (num[1] === -j) {
number_list.push(num);
} else {
const newIndex = mod(j + num[1], list_size - 1);
number_list.splice(newIndex, 0, num);
}
break;
}
}
}
}
const zi = index_of_zero(number_list);
let sum = 0;
for (let i = 1000; i <= 3000; i += 1000) {
sum += number_list[(zi + i) % number_list.length][1];
}
return sum;
}
console.log("Part 1:", mix());
console.log("Part 2:", mix(10, 811589153));
Day 21 ToExpression[yourContentString, InputForm]
Mathematica處理輸入文字並將其作為輸入程式碼
Part 1 and Part 2
ClearAll["Global`*"];
(*Step 1:Read the content of the text file as a string*)
content = Import["E:\\ExplorerDownload\\input2022_day21.txt", "Text"];
(*Step 2:Replace':' with'=' in the string*)
modifiedContent = StringReplace[content, ":" -> "="];
(*Step 3:Execute the modified string as Mathematica input*)
result = ToExpression[modifiedContent, InputForm];
Print["Part1=", root];
ClearAll["Global`*"];
(*Import the text file as a string*)
text = StringSplit[
Import["E:\\ExplorerDownload\\input2022_day21.txt", "Text"], "\n"];
(*Perform the replacements*)
modifiedText =
StringReplace[
text, {"humn: " ~~ expr1__ :> "",
"root: " ~~ expr1__ ~~ " + " ~~ expr2__ ~~ "" :>
"root = (" ~~ expr1 ~~ "==" ~~ expr2 ~~ ")", ":" -> "="}];
result = ToExpression[modifiedText, InputForm];
Solve[root, humn]
Day 22
Part 1 and Part 2
const fs = require('fs');
const x = fs.readFileSync('E:\\ExplorerDownload\\input2022_day22.txt', 'utf-8');
let [grid, ins] = x.split('\n\n');
//// Parsing ////
let gridLines = grid.split('\n');
let width = Math.max(...gridLines.map(line => line.length));
let height = gridLines.length;
gridLines = gridLines.map(line => ' ' + line.padEnd(width) + ' ');
width += 2;
height += 2;
const emptyLine = ' '.repeat(width);
gridLines = [emptyLine, ...gridLines, emptyLine];
let insList = [];
let buffer = '';
for (const c of ins.trim()) {
if (c === 'L' || c === 'R') {
if (buffer !== '') {
insList.push(parseInt(buffer));
buffer = '';
}
insList.push(c);
} else {
buffer += c;
}
}
if (buffer !== '') {
insList.push(parseInt(buffer));
buffer = '';
}
//// Starting Position ////
let xPos = 1;
let yPos = 1; // Note: positions are 1-indexed due to the padding
let dir = 0;
const dirLookup = [[0, 1], [1, 0], [0, -1], [-1, 0]];
for (let j = 0; j < width; j++) {
if (gridLines[1][j] === '.') {
yPos = j;
break;
}
}
const dirCache = [xPos, yPos];
//// Part 1 ////
for (const step of insList) {
if (step === 'R') {
dir = (dir + 1) % 4;
} else if (step === 'L') {
dir = (dir + 3) % 4; // Equivalent to (dir - 1) % 4
} else {
let [dx, dy] = dirLookup[dir];
for (let i = 0; i < step; i++) {
let nx = xPos + dx;
let ny = yPos + dy;
if (gridLines[nx][ny] === ' ') {
do {
nx -= dx;
ny -= dy;
} while (gridLines[nx][ny] !== ' ');
nx += dx;
ny += dy;
}
if (gridLines[nx][ny] === '#') {
break;
}
xPos = nx;
yPos = ny;
}
}
}
console.log(xPos * 1000 + yPos * 4 + dir);
//// Face size (work with both input and test data, and other sizes in general) ////
let totalNonSpace = gridLines.reduce((acc, line) => acc + [...line].filter(c => c !== ' ').length, 0);
let faceSize = Math.round(Math.sqrt(Math.floor(totalNonSpace / 6)));
//// Generate initial net adjacencies ////
function posKey(x, y) {
return x + ',' + y;
}
let Q = [dirCache];
let visited = {};
visited[posKey(...dirCache)] = [null, null, null, null];
while (Q.length > 0) {
const v = Q.shift();
const [x, y] = v;
const vKey = posKey(x, y);
for (let dir = 0; dir < 4; dir++) {
const [dx, dy] = dirLookup[dir];
const i = x + dx * faceSize;
const j = y + dy * faceSize;
if (!(0 <= i && i < height && 0 <= j && j < width)) {
continue;
}
if (gridLines[i][j] === ' ') {
continue;
}
const w = [i, j];
const wKey = posKey(i, j);
if (!(wKey in visited)) {
visited[vKey][dir] = wKey;
const wList = [null, null, null, null];
wList[(dir + 2) % 4] = vKey;
visited[wKey] = wList;
Q.push(w);
}
}
}
//// Normalize face-edge mapping ////
function faceIndex(x) {
return Math.floor((x - 1) / faceSize);
}
let faces = {};
for (const vKey in visited) {
const [i, j] = vKey.split(',').map(Number);
const faceKey = faceIndex(i) + ',' + faceIndex(j);
faces[faceKey] = visited[vKey].map(wKey => {
if (wKey === null) return null;
const [w_i, w_j] = wKey.split(',').map(Number);
const w_faceKey = faceIndex(w_i) + ',' + faceIndex(w_j);
return w_faceKey;
});
}
//// Fill in missing edge data using corners ////
function hasNullEdges(faces) {
for (const faceKey in faces) {
const edges = faces[faceKey];
if (edges.some(edge => edge === null)) {
return true;
}
}
return false;
}
while (hasNullEdges(faces)) {
for (const faceKey in faces) {
const edges = faces[faceKey];
for (let dir = 0; dir < 4; dir++) {
if (edges[dir] === null) {
for (const delta of [-1, 1]) {
const neighborDir = (dir + delta + 4) % 4;
const commonFace = edges[neighborDir];
if (commonFace === null) continue;
const commonFaceEdges = faces[commonFace];
const commonFaceEdge = commonFaceEdges.indexOf(faceKey);
const missingFaceDir = (commonFaceEdge + delta + 4) % 4;
const missingFace = commonFaceEdges[missingFaceDir];
if (missingFace === null) continue;
const missingFaceEdges = faces[missingFace];
const missingFaceEdge = missingFaceEdges.indexOf(commonFace);
missingFaceEdges[(missingFaceEdge + delta + 4) % 4] = faceKey;
edges[dir] = missingFace;
break;
}
}
}
}
}
//// Part 2 ////
xPos = dirCache[0];
yPos = dirCache[1];
dir = 0;
const edgeTopOffsetOut = [[1, 1], [1, faceSize], [faceSize, faceSize], [faceSize, 1]];
for (const step of insList) {
if (step === 'R') {
dir = (dir + 1) % 4;
} else if (step === 'L') {
dir = (dir + 3) % 4; // Equivalent to (dir - 1) % 4
} else {
let dx = dirLookup[dir][0];
let dy = dirLookup[dir][1];
let newDir = dir;
for (let i = 0; i < step; i++) {
let nx = xPos + dx;
let ny = yPos + dy;
if (gridLines[nx][ny] === ' ') {
// Compute current edge properties
const curFace = [faceIndex(xPos), faceIndex(yPos)];
let curOffset = 0;
while (true) {
const pos = [
curFace[0] * faceSize + edgeTopOffsetOut[(dir + 1) % 4][0] + dirLookup[(dir + 1) % 4][0] * curOffset,
curFace[1] * faceSize + edgeTopOffsetOut[(dir + 1) % 4][1] + dirLookup[(dir + 1) % 4][1] * curOffset,
];
if (pos[0] === xPos && pos[1] === yPos) {
break;
}
curOffset += 1;
}
// Compute next edge properties
const curFaceKey = curFace[0] + ',' + curFace[1];
const nextFaceKey = faces[curFaceKey][dir];
const nextFaceEdges = faces[nextFaceKey];
newDir = (nextFaceEdges.indexOf(curFaceKey) + 2) % 4;
const nextFaceIndices = nextFaceKey.split(',').map(Number);
nx =
nextFaceIndices[0] * faceSize +
edgeTopOffsetOut[newDir][0] +
dirLookup[(newDir + 1) % 4][0] * curOffset;
ny =
nextFaceIndices[1] * faceSize +
edgeTopOffsetOut[newDir][1] +
dirLookup[(newDir + 1) % 4][1] * curOffset;
}
if (gridLines[nx][ny] === '#') {
break;
} else {
xPos = nx;
yPos = ny;
dir = newDir;
dx = dirLookup[dir][0];
dy = dirLookup[dir][1];
}
}
}
}
console.log(xPos * 1000 + yPos * 4 + dir);
Day 23
Part 1 and Part 2
const fs = require('fs');
// Read the input file
const f = "E:\\ExplorerDownload\\input2022_day23.txt";
const s = fs.readFileSync(f, 'utf8').trim();
const lines = s.split('\n');
// Initialize the elves set
const elves = new Set();
lines.forEach((row, y) => {
for (let x = 0; x < row.length; x++) {
if (row[x] === '#') {
elves.add(`${x},${y}`);
}
}
});
// Define directions and adjacent positions
const x8 = [
{ dx: 1, dy: 0 },
{ dx: 1, dy: 1 },
{ dx: 0, dy: 1 },
{ dx: -1, dy: 1 },
{ dx: -1, dy: 0 },
{ dx: -1, dy: -1 },
{ dx: 0, dy: -1 },
{ dx: 1, dy: -1 },
];
const dirs = [
{ dx: 0, dy: -1 }, // Up
{ dx: 0, dy: 1 }, // Down
{ dx: -1, dy: 0 }, // Left
{ dx: 1, dy: 0 }, // Right
];
// Helper functions
function parsePos(posStr) {
const [xStr, yStr] = posStr.split(',');
return { x: parseInt(xStr), y: parseInt(yStr) };
}
function posToStr(pos) {
return `${pos.x},${pos.y}`;
}
function addPos(p, dir) {
return { x: p.x + dir.dx, y: p.y + dir.dy };
}
function rotate90(dir) {
return { dx: -dir.dy, dy: dir.dx };
}
function rotateMinus90(dir) {
return { dx: dir.dy, dy: -dir.dx };
}
function areSetsEqual(setA, setB) {
if (setA.size !== setB.size) return false;
for (const elem of setA) {
if (!setB.has(elem)) return false;
}
return true;
}
// Move function
function move(elves, pStr, fdir) {
const p = parsePos(pStr);
// Check if there are any adjacent elves
let hasAdjacent = false;
for (const delta of x8) {
const newPos = { x: p.x + delta.dx, y: p.y + delta.dy };
const newPosStr = posToStr(newPos);
if (elves.has(newPosStr)) {
hasAdjacent = true;
break;
}
}
if (!hasAdjacent) return pStr;
for (let t = 0; t < 4; t++) {
const dir = dirs[(fdir + t) % 4];
const pos1 = addPos(p, dir);
const rotate90d = rotate90(dir);
const rotateMinus90d = rotateMinus90(dir);
const pos2 = addPos(pos1, rotate90d);
const pos3 = addPos(pos1, rotateMinus90d);
const positionsToCheck = [pos1, pos2, pos3];
let hasElf = false;
for (const pos of positionsToCheck) {
const posStr = posToStr(pos);
if (elves.has(posStr)) {
hasElf = true;
break;
}
}
if (!hasElf) {
return posToStr(pos1);
}
}
return pStr;
}
// Calculate empty ground tiles
function emptyGround(elves) {
const xs = [];
const ys = [];
for (const posStr of elves) {
const pos = parsePos(posStr);
xs.push(pos.x);
ys.push(pos.y);
}
const minX = Math.min(...xs);
const maxX = Math.max(...xs);
const minY = Math.min(...ys);
const maxY = Math.max(...ys);
return (maxX - minX + 1) * (maxY - minY + 1) - elves.size;
}
// Update function
function update(elves, r) {
const want = new Map(); // Map from elf position to desired new position
// Sort elves by y, then x
const sortedElves = Array.from(elves).sort((aStr, bStr) => {
const a = parsePos(aStr);
const b = parsePos(bStr);
if (a.y !== b.y) return a.y - b.y;
return a.x - b.x;
});
for (const elfStr of sortedElves) {
const newPosStr = move(elves, elfStr, r % 4);
want.set(elfStr, newPosStr);
}
// Count how many elves want each position
const c = new Map(); // Map from position to count
for (const newPosStr of want.values()) {
c.set(newPosStr, (c.get(newPosStr) || 0) + 1);
}
const canhave = new Set();
for (const [elfStr, newPosStr] of want.entries()) {
if (c.get(newPosStr) === 1) {
canhave.add(elfStr);
}
}
const canthave = new Set();
for (const elfStr of elves) {
if (!canhave.has(elfStr)) {
canthave.add(elfStr);
}
}
// Update elves positions
const newElves = new Set();
for (const elfStr of canthave) {
newElves.add(elfStr);
}
for (const elfStr of canhave) {
const newPosStr = want.get(elfStr);
newElves.add(newPosStr);
}
return newElves;
}
// Main loop
let i = 0;
let pElves = null;
while (true) {
const newElves = update(elves, i);
if (areSetsEqual(elves, newElves)) {
break;
}
elves.clear();
for (const elfStr of newElves) {
elves.add(elfStr);
}
i += 1;
if (i === 10) {
console.log(emptyGround(elves)); // Part 1
}
}
console.log(i+1); // Part 2
Day 24
Part 1 and Part 2
## 測了一下,Julia程式設計方面,claude要比chatgpt要好
grid = readlines("E:\\ExplorerDownload\\input2022_day24.txt")
h, w = length(grid)-2, length(strip(grid[1]))-2
wrap(p) = Complex(mod(real(p), w), mod(imag(p), h))
dirs = Dict('x' => 0, '<' => -1, '>' => 1, '^' => -im, 'v' => im)
bliz = Dict{Char, Set{Complex{Int}}}()
for d in keys(dirs)
bliz[d] = Set{Complex{Int}}()
for x in 0:w-1, y in 0:h-1
if grid[y+2][x+2] == d
push!(bliz[d], Complex(x, y))
end
end
end
home, goal = Complex(0, -1), Complex(w-1, h)
todo, time, trip = [home], 0, 0
while !isempty(todo)
# Update blizzard positions
global bliz = Dict(d => Set(wrap(p + dirs[d]) for p in bliz[d]) for d in keys(dirs))
# Calculate possible new positions
curr = Set(p + dirs[d] for p in todo for d in keys(dirs))
global todo, time, trip = [], time + 1, trip
for pos in curr
if (trip, pos) == (0, goal) || (trip, pos) == (1, home) || (trip, pos) == (2, goal)
if trip == 0
println(time)
end
if trip == 2
println(time)
exit()
end
global todo, trip = [pos], trip + 1
break
end
if all(pos ∉ bliz[d] for d in keys(bliz)) &&
(pos == wrap(pos) || pos in (home, goal))
push!(todo, pos)
end
end
end
Day 25
Part 1
import scala.io.Source
object Main {
def pythonMod(a: Long, b: Long): Long = ((a % b) + b) % b
def pythonDiv(a: Long, b: Long): Long = {
if ((a > 0 && b > 0) || (a < 0 && b < 0)) a / b
else if (a % b == 0) a / b
else a / b - 1
}
// SNAFU to decimal
def f(s: String): Long = {
if (s.nonEmpty) {
val (a, b) = s.splitAt(s.length-1)
f(a) * 5 + "=-012".indexOf(b) - 2
} else 0
}
// Decimal to SNAFU
def g(d: Long): String = {
if (d != 0) {
val a=pythonDiv(d+2, 5)
val b=pythonMod(d+2, 5)
g(a) + "=-012"(b.toInt)
} else ""
}
def main(args: Array[String]): Unit = {
val filePath = "E:\\ExplorerDownload\\input2022_day25.txt"
try {
val lines = Source.fromFile(filePath).getLines().toList
val sumOfValues = lines.map(f).sum
println(g(sumOfValues))
} catch {
case e: Exception => println(s"An error occurred: ${e.getMessage}")
}
}
}
Part 2
Day 25的Part 2在其餘所有問題解答出來後自動解鎖並透過該關卡。