1 Commits

Author SHA1 Message Date
fc73788989 Messy initial solution. 2022-12-06 17:03:21 +01:00
4 changed files with 133 additions and 64 deletions

View File

@@ -1,9 +1,13 @@
# Advent of Code 2022 - Assignment 4 - javascript # Advent of Code 2022 - Assignment5 javascript
## Description This repository contains answers to the assignments of Advent of Coding 2022
The problem for assignment4 deals with overlaps and string parsing. The provided solution for this argument uses substring to parse ranges from file. Furthermore it has a checkbox to trigger whether ranges should fully overlap.
## References ## References
- https://www.w3schools.com/jsref/jsref_includes.asp
- https://stackoverflow.com/questions/10261986/how-to-detect-string-which-contains-only-spaces
- https://www.w3schools.com/jsref/jsref_indexof.asp - https://www.w3schools.com/jsref/jsref_indexof.asp
- https://www.geeksforgeeks.org/convert-a-string-to-an-integer-in-javascript/#:~:text=In%20JavaScript%20parseInt()%20function,argument%20of%20parseInt()%20function. - https://stackoverflow.com/questions/8073673/how-can-i-add-new-array-elements-at-the-beginning-of-an-array-in-javascript
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring - https://stackoverflow.com/questions/966225/how-can-i-create-a-two-dimensional-array-in-javascript
- https://medium.com/@raihan_tazdid/overlapping-numbers-in-ranges-5d0f2efc294e - https://www.w3schools.com/jsref/jsref_ceil.asp
- https://stackoverflow.com/questions/30561056/console-log-a-multi-dimensional-array
- https://teamtreehouse.com/community/removing-more-than-1-element-using-pop-and-shift-method
- https://stackoverflow.com/questions/14723848/push-multiple-elements-to-array

View File

@@ -9,7 +9,7 @@
<p>Assignment:</p> <p>Assignment:</p>
<textarea rows="15" cols="50" id="assignment"></textarea> <textarea rows="15" cols="50" id="assignment"></textarea>
<input type="checkbox" id="algorithm"/> <input type="checkbox" id="algorithm"/>
<label for="algorithm">Full overlap</label> <label for="algorithm">All containers at once?</label>
<p>Answer:</p> <p>Answer:</p>
<div id="answer">Provide input first</div> <div id="answer">Provide input first</div>

175
script.js
View File

@@ -1,10 +1,11 @@
const ASSIGNMENT = 'assignment'; const ASSIGNMENT = 'assignment';
const ANSWER = 'answer'; const ANSWER = 'answer';
const ALGORITHM_CHECKBOX = 'algorithm'; const ALGORITHM_CHECKBOX = 'algorithm';
const ERROR_MESSAGE_INVALID_RANGE = "Invalid range, "; const CONTAINER_NULL_CHARACTER=0;
const COMMA_CHARACTER = ','; const INSTRUCTION_FROM='from';
const INSTRUCTION_MOVE='move';
const INSTRUCTION_TO='to';
const NEWLINE_CHARACTER = '\n'; const NEWLINE_CHARACTER = '\n';
const RANGE_CHARACTER = '-';
/** /**
* Main function * Main function
@@ -21,8 +22,8 @@ window.onload = function() {
function calculateAnswer(event) { function calculateAnswer(event) {
console.info("Calculating answer for input..."); console.info("Calculating answer for input...");
let assignment = document.getElementById(ASSIGNMENT).value; let assignment = document.getElementById(ASSIGNMENT).value;
let fullOverlap = document.getElementById(ALGORITHM_CHECKBOX).checked; let allAtOnce = document.getElementById(ALGORITHM_CHECKBOX).checked;
let answer = algorithm(assignment, fullOverlap); let answer = algorithm(assignment, allAtOnce);
document.getElementById(ANSWER).innerText = answer; document.getElementById(ANSWER).innerText = answer;
} }
@@ -30,73 +31,137 @@ function calculateAnswer(event) {
/** /**
* Calculate the answer to assignment. * Calculate the answer to assignment.
* @param assignment the input from the assignment. * @param assignment the input from the assignment.
* @param fullOverlap if input needs to fully overlap. * @param allAtOnce should all containers be moved at once.
* @return string the answer * @return string the answer
*/ */
function algorithm(assignment, fullOverlap) { function algorithm(assignment, allAtOnce) {
let lines = assignment.trim().split(NEWLINE_CHARACTER); let lines = assignment.split(NEWLINE_CHARACTER);
let containerPlan = Array.from({length:(lines[0].length+1)/4}, () => [])
console.info("Linecount:" + lines.length); console.info("Linecount:" + lines.length);
let containedPairs = 0; let parsec = true;
for(let i=0; i<lines.length; i++) { for(let i=0; i<lines.length; i++) {
let error = false; if(parsec) {
let ranges = lines[i].trim();
// Search for separation charactes -,-
let range1CharacterIndex = ranges.indexOf(RANGE_CHARACTER);
let range1EndCharacterIndex = ranges.indexOf(COMMA_CHARACTER);
let range2CharacterIndex = ranges.indexOf(RANGE_CHARACTER, range1CharacterIndex+1);
// Get range substrings // Parse containers
let range1LowerString = ranges.substring(0,range1CharacterIndex); let containerLine = lines[i];
let range1HigherString = ranges.substring(range1CharacterIndex+1, range1EndCharacterIndex);
let range2LowerString = ranges.substring(range1EndCharacterIndex+1, range2CharacterIndex);
let range2HigherString = ranges.substring(range2CharacterIndex+1);
console.debug("Parsed values: " + range1LowerString + "-" + range1HigherString + "," + range2LowerString + "-" + range2HigherString);
// Parse to int // Skip numbers
let range1Lower = parseInt(range1LowerString); if(containerLine[1] == '1') {
let range1Higher = parseInt(range1HigherString); parsec = false;
let range2Lower = parseInt(range2LowerString); i+=1;
let range2Higher = parseInt(range2HigherString); console.table(containerPlan);
// Validation
if(range1Lower > range1Higher) {
console.error(ERROR_MESSAGE_INVALID_RANGE + range1Lower + "-" + range1Higher + " on line:" + i + " for range1");
error = true;
}
if(range2Lower > range2Higher) {
console.error(ERROR_MESSAGE_INVALID_RANGE + range2Lower + "-" + range2Higher + " on line:" + i + " for range2");
error = true;
}
if(error) {
continue; continue;
} }
// Check for overlap let containers = parseContainers(containerLine);
if(fullOverlap && doesRangeFullyOverlap(range1Lower, range1Higher, range2Lower, range2Higher) if(containers == -1) {
|| !fullOverlap && doesRangeOverlap(range1Lower, range1Higher, range2Lower, range2Higher)) { // invalid containerline
console.debug("Found overlapping range:" + range1Lower + "-" + range1Higher + "," + range2Lower + "-" + range2Higher); // TODO: error
containedPairs++; console.error("Container parse failure.");
continue;
}
// Add containers
//console.debug(containers);
for(let j=0; j<containers.length; j++) {
let container = containers[j];
//console.debug(container);
if(container != CONTAINER_NULL_CHARACTER) {
//console.debug(j);
//console.debug(containerPlan);
containerPlan[j].push(container);
}
}
//console.table(containerPlan);
} else {
// Parse instructions
let instructionLine = lines[i];
let instruction = parseInstruction(instructionLine);
console.debug(instruction);
if(instruction == -1) {
// invalid instructionline
// TODO: error
console.error("Instruction parse failure.");
continue;
}
// Execute instruction
let movecount=0;
if(allAtOnce) {
while(instruction.move > 0) {
let container = containerPlan[instruction.from].shift();
containerPlan[instruction.to].unshift(container);
instruction.move--;
movecount++;
}
console.debug("moved:" + movecount);
} else {
let splicedContainers = containerPlan[instruction.from].splice(0, instruction.move);
containerPlan[instruction.to].unshift(...splicedContainers);
}
//console.table(containerPlan);
} }
} }
return "Fully overlapping timeslot counts: " + containedPairs; let result="";
for(let k=0; k<containerPlan.length; k++) {
result += containerPlan[k][0];
} }
function doesRangeFullyOverlap(lower, higher, lower2, higher2) { return "Top containers on the stack are: " + result;
console.debug("Compare range: " + lower + "-" + higher + " with " + lower2 + "-" + higher2);
if(lower > higher || lower2 > higher2) {
return false;
}
return ((lower <= lower2 && higher >= higher2) || (lower2 <= lower && higher2 >= higher));
} }
function doesRangeOverlap(lower, higher, lower2, higher2) { function parseInstruction(instructionLine) {
console.debug("Compare range: " + lower + "-" + higher + " with " + lower2 + "-" + higher2); let instruction={
if(lower > higher || lower2 > higher2) { move:0,
return false; from:0,
to:0,
} }
return higher2 >= lower && lower2 <= higher; instructionLine.replace(/\s/g, ''); // Remove whitespace
let fromIndex = instructionLine.indexOf(INSTRUCTION_FROM);
let moveIndex = instructionLine.indexOf(INSTRUCTION_MOVE);
let toIndex = instructionLine.indexOf(INSTRUCTION_TO);
// Validate
if(fromIndex < 0 || moveIndex < 0 || toIndex < 0) {
// Error
return -1;
}
// TODO validate check for numbers after indices.
// Parse
instruction.move = parseInt(instructionLine.substring(moveIndex + INSTRUCTION_MOVE.length + 1, fromIndex));
instruction.from = parseInt(instructionLine.substring(fromIndex + INSTRUCTION_FROM.length + 1, toIndex)) -1;
instruction.to = parseInt(instructionLine.substring(toIndex + INSTRUCTION_TO.length + 1)) -1;
return instruction;
}
function parseContainers(containerLine) {
let containerLineLength = (containerLine.length+1);
//console.debug("Parse ContainerLine, length: " + containerLineLength);
if(!containerLine.includes('[') || !containerLine.includes(']') || containerLineLength % 4 != 0) {
return -1;
}
let containers = [];
for(let i=0; i<containerLineLength; i+=4) {
let containerLineSubString = containerLine.substring(i, i+4).trim();
let character = containerLineSubString[1];
if(containerLineSubString[0] != '[' || containerLineSubString[2] != ']') {
// Warning invalid container format
// TODO: warning
}
containers.push((!character)? CONTAINER_NULL_CHARACTER: character);
}
//console.debug(containers);
return containers;
} }