1 Commits

Author SHA1 Message Date
63de472207 Solution for assignment4. 2022-12-05 01:00:05 +01:00
4 changed files with 64 additions and 118 deletions

View File

@@ -1,12 +1,9 @@
# Advent of Code 2022 - Assignment3 javascript solution # Advent of Code 2022 - Assignment 4 - javascript
This problem is all about searching for duplicates in strings. The solution is implemented using slice to split the string in half. ## Description
The priority is retrieved using the ASCII charcode character for convienence. How to retrieve inputs differs between part1 and 2, therefore a checkbox is provided to toggle between different parsing methods. 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://stackoverflow.com/questions/94037/convert-character-to-ascii-code-in-javascript - https://www.w3schools.com/jsref/jsref_indexof.asp
- https://stackoverflow.com/questions/20474257/split-string-into-two-parts - https://www.geeksforgeeks.org/convert-a-string-to-an-integer-in-javascript/#:~:text=In%20JavaScript%20parseInt()%20function,argument%20of%20parseInt()%20function.
- https://www.folkstalk.com/2022/10/find-common-characters-in-two-strings-javascript-with-code-examples.html - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring
- https://stackoverflow.com/questions/351409/how-to-append-something-to-an-array - https://medium.com/@raihan_tazdid/overlapping-numbers-in-ranges-5d0f2efc294e
- https://stackoverflow.com/questions/9862761/how-to-check-if-character-is-a-letter-in-javascript
- https://stackoverflow.com/questions/1966476/how-can-i-process-each-letter-of-text-using-javascript
- https://www.w3schools.com/js/js_arrays.asp

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">Solution by compartiment.</label> <label for="algorithm">Full overlap</label>
<p>Answer:</p> <p>Answer:</p>
<div id="answer">Provide input first</div> <div id="answer">Provide input first</div>

161
script.js
View File

@@ -1,11 +1,10 @@
const ASSIGNMENT = 'assignment'; const ASSIGNMENT = 'assignment';
const ANSWER = 'answer'; const ANSWER = 'answer';
const ALGORITHM_CHECKBOX = 'algorithm'; const ALGORITHM_CHECKBOX = 'algorithm';
const CHARCODE_START=64; const ERROR_MESSAGE_INVALID_RANGE = "Invalid range, ";
const CHARCODE_UPPER_CORRECTION=6; const COMMA_CHARACTER = ',';
const ERROR_MESSAGE_INVALID_INPUT_SIZE = "Invalid input size, should be higher than 2 for: ";
const ERROR_MESSAGE_INVALID_ITEM_CHARACTER = "Invalid item character found: ";
const NEWLINE_CHARACTER = '\n'; const NEWLINE_CHARACTER = '\n';
const RANGE_CHARACTER = '-';
/** /**
* Main function * Main function
@@ -22,8 +21,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 byCompartiments = document.getElementById(ALGORITHM_CHECKBOX).checked; let fullOverlap = document.getElementById(ALGORITHM_CHECKBOX).checked;
let answer = algorithm(assignment, byCompartiments); let answer = algorithm(assignment, fullOverlap);
document.getElementById(ANSWER).innerText = answer; document.getElementById(ANSWER).innerText = answer;
} }
@@ -31,123 +30,73 @@ 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.
* @return string the answer * @return string the answer
*/ */
function algorithm(assignment, byCompartiments) { function algorithm(assignment, fullOverlap) {
let priorityScoreSum = 0;
let lines = assignment.trim().split(NEWLINE_CHARACTER);
console.info("Linecount:" + lines.length);
let increment = (byCompartiments)? 1:3;
for(let i=0; i<lines.length; i+=increment) {
let inputs = [];
let rucksack = lines[i].replace(/\s/g, ''); // Remove whitespace
if(byCompartiments) {
let compartiment1 = rucksack.slice(0, rucksack.length/2);
let compartiment2 = rucksack.slice(rucksack.length/2);
inputs = [compartiment1, compartiment2];
} else {
inputs = [rucksack, lines[i+1].replace(/\s/g, ''), lines[i+2].replace(/\s/g, '')];
}
let duplicate = getDuplicateCharacter(inputs);
if(duplicate < 0) {
console.error(ERROR_MESSAGE_INVALID_INPUT_SIZE + inputs + " on line: " + i);
}
let priorityScore = getPriorityScore(duplicate);
if(priorityScore < 0) {
console.error(ERROR_MESSAGE_INVALID_ITEM_CHARACTER + duplicate + " on line: " + i);
continue;
}
priorityScoreSum += priorityScore;
}
return "SUM priorityscore: " + priorityScoreSum;
}
/**
* Calculate the answer to assignment.
* @param assignment the input from the assignment.
* @return string the answer
*/
function algorithm1(assignment) {
let priorityScoreSum = 0;
let lines = assignment.trim().split(NEWLINE_CHARACTER); let lines = assignment.trim().split(NEWLINE_CHARACTER);
console.info("Linecount:" + lines.length); console.info("Linecount:" + lines.length);
let containedPairs = 0;
for(let i=0; i<lines.length; i++) { for(let i=0; i<lines.length; i++) {
let rucksack = lines[i].replace(/\s/g, ''); // Remove whitespace let error = false;
let compartiment1 = rucksack.slice(0, rucksack.length/2); let ranges = lines[i].trim();
let compartiment2 = rucksack.slice(rucksack.length/2); // Search for separation charactes -,-
let range1CharacterIndex = ranges.indexOf(RANGE_CHARACTER);
let range1EndCharacterIndex = ranges.indexOf(COMMA_CHARACTER);
let range2CharacterIndex = ranges.indexOf(RANGE_CHARACTER, range1CharacterIndex+1);
console.debug("Check rucksack" + i, ": " + rucksack + " \n with compartiment1: " + compartiment1 + "\n and compartiment2: " + compartiment2); // Get range substrings
let range1LowerString = ranges.substring(0,range1CharacterIndex);
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);
for(item of compartiment2) { // Parse to int
if(compartiment1.includes(item)) { let range1Lower = parseInt(range1LowerString);
console.debug("Found duplicate: " + item + " in rucksack" + i); let range1Higher = parseInt(range1HigherString);
let priorityScore = getPriorityScore(item); let range2Lower = parseInt(range2LowerString);
if(priorityScore < 0) { let range2Higher = parseInt(range2HigherString);
console.error(ERROR_MESSAGE_INVALID_ITEM_CHARACTER + item + " on line: " + i);
// 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;
} }
priorityScoreSum += priorityScore;
break; // Check for overlap
} if(fullOverlap && doesRangeFullyOverlap(range1Lower, range1Higher, range2Lower, range2Higher)
|| !fullOverlap && doesRangeOverlap(range1Lower, range1Higher, range2Lower, range2Higher)) {
console.debug("Found overlapping range:" + range1Lower + "-" + range1Higher + "," + range2Lower + "-" + range2Higher);
containedPairs++;
} }
} }
return "SUM priorityscore: " + priorityScoreSum; return "Fully overlapping timeslot counts: " + containedPairs;
} }
/** function doesRangeFullyOverlap(lower, higher, lower2, higher2) {
* Find duplicate character in inputs. console.debug("Compare range: " + lower + "-" + higher + " with " + lower2 + "-" + higher2);
* @param string[] inputs the inputs to find duplicates in. if(lower > higher || lower2 > higher2) {
* @return char the duplicate character return false;
*/ }
function getDuplicateCharacter(inputs) { return ((lower <= lower2 && higher >= higher2) || (lower2 <= lower && higher2 >= higher));
console.debug("Checking inputs: " + inputs);
if(inputs.length < 2) {
return -1;
} }
for(let item of inputs[0]) { function doesRangeOverlap(lower, higher, lower2, higher2) {
let duplicate = true console.debug("Compare range: " + lower + "-" + higher + " with " + lower2 + "-" + higher2);
for(let j=1; j<inputs.length; j++) { if(lower > higher || lower2 > higher2) {
duplicate = duplicate && inputs[j].includes(item); return false;
} }
if(duplicate) { return higher2 >= lower && lower2 <= higher;
console.debug("Found duplicate: " + item);
return item;
}
}
}
/**
* Returns priorityscore for given character.
* @param char character the character
* @return int the priorityscore for character or -1 if invalid
*/
function getPriorityScore(character) {
let result=0;
let uppercase = character.toUpperCase();
let lowercase = character.toLowerCase();
// validate character
if( uppercase == lowercase ) {
return -1;
}
if(character == uppercase) { // Switch results for upper and lowercase characters
result -= CHARCODE_UPPER_CORRECTION;
character = lowercase;
} else {
character = uppercase;
}
result += character.charCodeAt() - CHARCODE_START;
return result;
} }