import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day1/input', 'utf-8');
console.time('Time taken');
let ans: number = 1;
const inpArr: string[] = input.split(/\n/).filter(x => x);
for (let i = 0; i < inpArr.length - 1; i++) {
for (let j = i + 1; j < inpArr.length; j++) {
if (Number(inpArr[i]) + Number(inpArr[j]) === 2020) {
ans *= Number(inpArr[i]) * Number(inpArr[j]);
}
}
}
console.timeEnd('Time taken')
console.log(ans)
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day1/input', 'utf-8');
console.time('Time taken');
let ans: number = 1;
const inpArr: string[] = input.split(/\n/).filter(x => x);
for (let i = 0; i < inpArr.length - 2; i++) {
for (let j = i + 1; j < inpArr.length - 1; j++) {
for (let k = j + 1; k < inpArr.length; k++){
if (Number(inpArr[i]) + Number(inpArr[j]) + Number(inpArr[k]) === 2020) {
ans *= Number(inpArr[i]) * Number(inpArr[j]) * Number(inpArr[k]);
}
}
}
}
console.timeEnd('Time taken')
console.log(ans)
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day2/input', 'utf-8');
console.time('Time taken');
let ans: number = 0;
const inpArr: string[] = input.split(/\n/).filter(x => x);
interface PWPolicy {
charToMatch: string;
minOccur: number;
maxOccur: number;
pw: string;
}
inpArr.forEach(inpLine => {
const pwPolicyArr: string[] = inpLine.split(/\s/);
let pwPolicy: PWPolicy = {charToMatch: String(pwPolicyArr[1]).slice(0, -1),
minOccur: parseInt(pwPolicyArr[0].split('-')[0]),
maxOccur: parseInt(pwPolicyArr[0].split('-')[1]),
pw: String(pwPolicyArr[2])};
const re = new RegExp(`[${pwPolicy.charToMatch}]`, 'g');
if (pwPolicy.pw.match(re)?.length >= pwPolicy.minOccur && pwPolicy.pw.match(re)?.length <= pwPolicy.maxOccur) {
++ans;
}
});
console.timeEnd('Time taken')
console.log(ans)
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day2/input', 'utf-8');
console.time('Time taken');
let ans: number = 0;
const inpArr: string[] = input.split(/\n/).filter(x => x);
interface PWPolicy {
charToMatch: string;
firstPos: number;
secondPos: number;
pw: string;
}
const verifyCharXOR = (x: string, y: string, compChar: string): boolean => {
return (x === compChar) ? !(y === compChar) : (y === compChar);
}
inpArr.forEach(inpLine => {
const pwPolicyArr: string[] = inpLine.split(/\s/);
let pwPolicy: PWPolicy = {charToMatch: String(pwPolicyArr[1]).slice(0, -1),
firstPos: parseInt(pwPolicyArr[0].split('-')[0]),
secondPos: parseInt(pwPolicyArr[0].split('-')[1]),
pw: String(pwPolicyArr[2])};
if(verifyCharXOR(pwPolicy.pw.charAt(pwPolicy.firstPos - 1), pwPolicy.pw.charAt(pwPolicy.secondPos - 1), pwPolicy.charToMatch)){
++ans;
}
});
console.timeEnd('Time taken')
console.log(ans)
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day3/input', 'utf-8');
console.time('Time taken');
let ans: number = 0;
const inpArr: string[] = input.split(/\n/).filter(x => x);
interface SlopeParams {
xLength: number;
yLength: number;
tree: string;
openSquare: string;
}
interface TobboganParams {
xPos: number;
xMoveSpeed: number;
}
const sParams: SlopeParams = {
xLength: inpArr[0].length,
yLength: inpArr.length,
tree: "#",
openSquare: "."
};
let tParams: TobboganParams = {
xMoveSpeed: 3,
xPos: 0
};
inpArr.forEach(line => {
if(line.charAt(tParams.xPos) === sParams.tree){
++ans;
}
tParams.xPos = (tParams.xPos + tParams.xMoveSpeed ) % sParams.xLength;
});
console.timeEnd('Time taken')
console.log(ans)
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day3/input', 'utf-8');
console.time('Time taken');
let ans: number = 1;
const inpArr: string[] = input.split("\n").filter(x => x);
interface SlopeParams {
readonly xLength: number;
readonly yLength: number;
readonly tree: string;
readonly openSquare: string;
readonly slopes: [number, number][];
}
interface TobboganParams {
numberEncounters: number;
xPos: number;
yPos: number;
}
const sParams: SlopeParams = {
xLength: Number(inpArr[0].length),
yLength: Number(inpArr.length),
tree: "#",
openSquare: ".",
slopes: [[1, 1], [3, 1], [5, 1], [7, 1], [1, 2]]
};
let tParams: TobboganParams = {
numberEncounters: 0,
xPos: 0,
yPos: 0
};
for(let slope of sParams.slopes){
while(tParams.yPos < sParams.yLength) {
if (inpArr[tParams.yPos].charAt(tParams.xPos) === sParams.tree){
++tParams.numberEncounters;
}
tParams.xPos = (tParams.xPos + slope[0]) % sParams.xLength;
tParams.yPos += slope[1];
}
ans *= tParams.numberEncounters;
// Refresh
tParams.numberEncounters = 0;
tParams.xPos = 0;
tParams.yPos = 0;
}
console.timeEnd('Time taken')
console.log(ans)
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day4/input', 'utf-8');
console.time('Time taken');
const inpArr: string[] = input.split(/\n/);
type PassControl = {
readonly reqFields: string[];
validCounter: number;
}
type Passport = {
detectedFields: string[]
};
let pControl: PassControl = {
reqFields: ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"],
validCounter: 0
}
let pass: Passport = { detectedFields: [] };
inpArr.forEach((line: string) => {
if (line) {
const keyVals: string[] = line.split(/\s/)
keyVals.forEach(kv => {
let key: string = kv.split(":")[0];
pass.detectedFields.push(key);
});
}
else {
if(pControl.reqFields.every(x => {
return pass.detectedFields.includes(x)
})) {
pControl.validCounter++;
}
pass = { detectedFields: [] };
}
});
console.time('Time taken');
console.log(pControl.validCounter)
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day4/input', 'utf-8');
console.time('Time taken')
const inpArr: string[] = input.split(/\n/);
let pValidCounter: number = 0;
enum ReqFields {
byr = "byr",
iyr = "iyr",
eyr = "eyr",
hgt = "hgt",
hcl = "hcl",
ecl = "ecl",
pid = "pid",
}
type Passport = {
detectedFields: string[],
hasInvalidFields: boolean;
};
let curPass: Passport = { detectedFields: [], hasInvalidFields: false };
const performFieldValidation = (field: string, val: string): boolean => {
if (field === "cid")
return true
const fieldCasted: ReqFields = ReqFields[field as keyof typeof ReqFields];
let re: RegExp;
switch (fieldCasted) {
case ReqFields.byr:
re = new RegExp('^\\d{4}$');
return re.test(val) && Number(val) >= 1920 && Number(val) <= 2002
case ReqFields.iyr:
re = new RegExp('^\\d{4}$');
return re.test(val) && Number(val) >= 2010 && Number(val) <= 2020
case ReqFields.eyr:
re = new RegExp('^\\d{4}$');
return re.test(val) && Number(val) >= 2020 && Number(val) <= 2030
case ReqFields.hgt:
re = new RegExp('^(\\d+)(cm|in)$');
let matchRes: RegExpMatchArray = val.match(re);
if (matchRes) {
if (matchRes[2] === "cm") {
return Number(matchRes[1]) >= 150 && Number(matchRes[1]) <= 193
} else if (matchRes[2] === "in") {
return Number(matchRes[1]) >= 59 && Number(matchRes[1]) <= 76;
}
}
return false;
case ReqFields.hcl:
re = new RegExp('^#[0-9a-f]{6}$');
return re.test(val);
case ReqFields.ecl:
re = new RegExp('(amb|blu|brn|gry|grn|hzl|oth)');
return re.test(val);
case ReqFields.pid:
re = new RegExp('^\\d{9}$');
return re.test(val);
default:
return false;
}
}
inpArr.forEach((line: string) => {
if (line === "") {
if (!curPass.hasInvalidFields) {
pValidCounter++;
for (let enumVal in ReqFields) {
if (!curPass.detectedFields.includes(enumVal)) {
pValidCounter--;
break;
}
}
}
curPass = { detectedFields: [], hasInvalidFields: false };
}
else if (!curPass.hasInvalidFields) {
const keyVals: string[] = line.split(" ")
keyVals.forEach(kv => {
let kvs: string[] = kv.split(/:/);
if (performFieldValidation(kvs[0], kvs[1])) {
curPass.detectedFields.push(kvs[0]);
} else {
curPass.hasInvalidFields = true;
}
});
}
});
console.timeEnd('Time taken')
console.log(pValidCounter)
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day5/input', 'utf-8');
console.time('Time taken');
const seatsBinary: string[] = input.split(/\n/).filter(Boolean).map((seatCode) => {
return seatCode
.replaceAll(/[F|L]/g, "0")
.replaceAll(/[B|R]/g, "1");
}).sort();
const maxSeatBinaryCode: string = seatsBinary[seatsBinary.length - 1];
const row: number = parseInt(maxSeatBinaryCode.slice(0, 7), 2);
const column: number = parseInt(maxSeatBinaryCode.slice(7, 10), 2);
console.timeEnd('Time taken')
console.log(row * 8 + column)
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day5/input', 'utf-8');
console.time('Time taken');
let ans: number = 0;
const getSeatID = (seatBinary: string) : number => {
const row: number = parseInt(seatBinary.slice(0, 7), 2);
const column: number = parseInt(seatBinary.slice(7, 10), 2);
return row * 8 + column;
}
const seatsBinary: string[] = input.split(/\n/).filter(Boolean).map((seatCode) => {
return seatCode
.replaceAll(/[F|L]/g, "0")
.replaceAll(/[B|R]/g, "1");
}).sort();
let prevSeat: number | null = null;
for(let seat of seatsBinary){
let curSeat: number = getSeatID(seat);
if( prevSeat !== null && curSeat - prevSeat === 2) {
ans = curSeat - 1;
break;
}
else{
prevSeat = curSeat;
}
}
console.timeEnd('Time taken')
console.log(ans)
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day6/input', 'utf-8');
console.time('Time taken')
let sumOfAnswers: number = 0;
input.split(/\n\n/).forEach(x => {
sumOfAnswers += new Set([...x.replace(/\n/g, "")]).size;
});
console.timeEnd('Time taken')
console.log(sumOfAnswers);
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day6/input', 'utf-8');
console.time('Time taken')
let sumOfAnswers: number = 0;
input.split(/\n\n/).forEach(grp => {
const allAnswers = new Set([...grp.replace(/\n/g, "")]);
allAnswers.forEach(ans => {
if(grp.split(/\n/).filter(Boolean).every(persAns => persAns.includes(ans))){
++sumOfAnswers;
}
});
});
console.timeEnd('Time taken')
console.log(sumOfAnswers);
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day7/input', 'utf-8');
console.time('Time taken')
const bagOfInterest: string = "shiny gold";
const re1 = /^([\w\s]+) bags contain /;
const re2 = /(\d+) ([\w\s]+) bag[s]?/;
const re2_g = /(\d+) ([\w\s]+) bag[s]?/g;
type BagContainer = {
[k: string]: Set<string>;
};
let bagDict: BagContainer = {};
let ans: number = 0;
// Construct bag rules
input.split(/\n/).filter(Boolean).forEach(rule => {
let myMatches;
bagDict[rule.match(re1)[1]] = new Set();
if (re2.test(rule)) {
while ((myMatches = re2_g.exec(rule)) !== null) {
bagDict[rule.match(re1)[1]].add(myMatches[2]);
}
}
});
const containsShinyGoldBags = (bag: string) => {
const bagContents: Set<string> = bagDict[bag];
if (bagContents.has(bagOfInterest)) {
return true;
} else {
for (let containedBag of bagContents.values()) {
if (containsShinyGoldBags(containedBag)) {
return true;
}
}
}
return false;
}
// Seek for appropriate bags and count them
ans = Object.keys(bagDict).filter((x) => {
return containsShinyGoldBags(x);
}).length;
console.timeEnd('Time taken')
console.log(`Answer: ${ans}`);
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day7/input', 'utf-8');
console.time('Time taken')
const bagOfInterest: string = "shiny gold";
const re1 = /^([\w\s]+) bags contain /;
const re2 = /(\d+) ([\w\s]+) bag[s]?/;
const re2_g = /(\d+) ([\w\s]+) bag[s]?/g;
type BagInfo = {
amount: number,
type: string;
};
type BagContainer = {
[k: string]: Set<BagInfo>;
};
let bagDict: BagContainer = {};
let ans: number = 0;
// Construct bag rules
input.split(/\n/).filter(Boolean).forEach(rule => {
let myMatches;
bagDict[rule.match(re1)[1]] = new Set();
if (re2.test(rule)) {
while ((myMatches = re2_g.exec(rule)) !== null) {
bagDict[rule.match(re1)[1]].add({
amount: parseInt(myMatches[1]),
type: myMatches[2]
});
}
}
});
const getBagsNumber = (bag: string): number => {
const bagContents: Set<BagInfo> = bagDict[bag];
let bagsNumerTotal: number = 0;
for (let containedBag of bagContents.values()) {
bagsNumerTotal += containedBag.amount;
bagsNumerTotal += getBagsNumber(containedBag.type) * containedBag.amount;
}
return bagsNumerTotal;
};
// Count all the bags needed for `bagOfInterest`
ans = getBagsNumber(bagOfInterest);
console.timeEnd('Time taken')
console.log(`Answer: ${ans}`);
import { readFileSync } from 'fs';
const input: string = readFileSync('./2020/day8/input', 'utf-8');
console.time('Time taken')
enum Opcode {
acc = "acc",
jmp = "jmp",
nop = "nop"
}
const execInstruction = (opcode: string, arg: number): number => {
const opcodeCasted: Opcode = Opcode[opcode as keyof typeof Opcode];
switch (opcodeCasted) {
case Opcode.acc:
ans += arg;
return 1;
case Opcode.jmp:
return arg;
case Opcode.nop:
return 1;
}
}
let ans: number = 0;
let currInstr: number = 0;
let instrVisited: Set<number> = new Set();
const instrList: string[] = input.split(/\n/).filter(Boolean);
while (!instrVisited.has(currInstr)) {
const cmd: string[] = instrList[currInstr].split(/\s/);
instrVisited.add(currInstr);
currInstr += execInstruction(cmd[0], parseInt(cmd[1]));
}
console.timeEnd('Time taken')
console.log(`Answer: ${ans}`);