1 Commits

Author SHA1 Message Date
312a514472 Solution for part 1. 2022-12-22 23:07:39 +01:00
4 changed files with 153 additions and 131 deletions

View File

@@ -1,12 +1,14 @@
# Advent of Code 2022 - Assignment3 javascript solution
This problem is all about searching for duplicates in strings. The solution is implemented using slice to split the string in half.
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.
# Advent of Code - assignment 9 javascript
This repository contains answers to the assignments of Advent of Coding 2022
## References
- https://stackoverflow.com/questions/94037/convert-character-to-ascii-code-in-javascript
- https://stackoverflow.com/questions/20474257/split-string-into-two-parts
- https://www.folkstalk.com/2022/10/find-common-characters-in-two-strings-javascript-with-code-examples.html
- https://stackoverflow.com/questions/351409/how-to-append-something-to-an-array
- 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
- https://betterprogramming.pub/tuples-in-javascript-57ede9b1c9d2
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length
- https://www.javascripttutorial.net/javascript-multidimensional-array/
- https://flaviocopes.com/how-to-replace-whitespace-javascript/
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
- https://www.sohamkamani.com/javascript/enums/
- https://www.w3schools.com/js/js_switch.asp
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
- https://stackoverflow.com/questions/4564414/delete-first-character-of-string-if-it-is-0
- https://stackoverflow.com/questions/1959040/is-it-possible-to-send-a-variable-number-of-arguments-to-a-javascript-function

View File

@@ -8,8 +8,6 @@
<body>
<p>Assignment:</p>
<textarea rows="15" cols="50" id="assignment"></textarea>
<input type="checkbox" id="algorithm"/>
<label for="algorithm">Solution by compartiment.</label>
<p>Answer:</p>
<div id="answer">Provide input first</div>

256
script.js
View File

@@ -1,10 +1,5 @@
const ASSIGNMENT = 'assignment';
const ANSWER = 'answer';
const ALGORITHM_CHECKBOX = 'algorithm';
const CHARCODE_START=64;
const CHARCODE_UPPER_CORRECTION=6;
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';
/**
@@ -12,18 +7,136 @@ const NEWLINE_CHARACTER = '\n';
*/
window.onload = function() {
document.getElementById(ASSIGNMENT).addEventListener("input", calculateAnswer);
document.getElementById(ALGORITHM_CHECKBOX).addEventListener("click", calculateAnswer);
}
const DIRECTIONS = {
UP: 'U',
DOWN: 'D',
LEFT: 'L',
RIGHT: 'R'
};
class Knot {
constructor(x, y) {
this.x=x;
this.y=y;
}
}
/*class Rope {
constructor(headX, headY, tailX, tailY) {
this.headX = headX;
this.headY = headY;
this.tailX = tailX;
this.tailY = tailY;
console.info("Created Rope with head:" + headX + "," + headY + " and tail: " + tailX + "," + tailY);
}
step = function (direction) {
let oldHeadX = this.headX;
let oldHeadY = this.headY;
switch (direction) {
case DIRECTIONS.UP:
this.headY++;
break;
case DIRECTIONS.DOWN:
this.headY--;
break;
case DIRECTIONS.LEFT:
this.headX--;
break;
case DIRECTIONS.RIGHT:
this.headX++;
break;
default:
console.error("Invalid direction given: " + direction);
}
this.__correctTail(oldHeadX, oldHeadY);
}
getTailPosition = function () {
return "" + this.tailX + "," + this.tailY;
}
__correctTail = function (oldHeadX, oldHeadY) {
let absoluteDifferenceX = Math.abs(this.headX - this.tailX);
let absoluteDifferenceY = Math.abs(this.headY - this.tailY);
if (absoluteDifferenceX > 1 || absoluteDifferenceY > 1) {
this.tailX = oldHeadX;
this.tailY = oldHeadY;
console.debug("Corrected tail Position: (" + this.tailX + ", " + this.tailY + "), head position: (" + this.headX + ", " + this.headY + ")");
}
}
};*/
class Rope {
constructor(count) {
if(count < 2) {
console.error("Rope needs at least 2 knots.");
return;
}
let knots = [];
while(count > 0) {
knots.push(new Knot(0,0));
count--;
}
this.head = knots[0];
this.knots = Array.from(knots).slice(1);
this.tail = this.knots[this.knots.length-1];
console.info("Created Rope with " + knots.length + " knots.");
}
step = function(direction) {
let oldHeadX = this.head.x;
let oldHeadY = this.head.y;
switch(direction) {
case DIRECTIONS.UP:
this.head.y++;
break;
case DIRECTIONS.DOWN:
this.head.y--;
break;
case DIRECTIONS.LEFT:
this.head.x--;
break;
case DIRECTIONS.RIGHT:
this.head.x++;
break;
default:
console.error("Invalid direction given: " + direction);
}
this.__correctTails(oldHeadX, oldHeadY, this.head, this.knots[0], this.knots.slice(1));
}
getTailPosition = function() {
return "" + this.tail.x + "," + this.tail.y;
}
__correctTails = function(oldHeadX, oldHeadY, head, tail, tails) {
let absoluteDifferenceX = Math.abs(head.x - tail.x);
let absoluteDifferenceY = Math.abs(head.y - tail.y);
let oldTailX = tail.x;
let oldTailY = tail.y;
if(absoluteDifferenceX > 1 || absoluteDifferenceY > 1) {
tail.x = oldHeadX;
tail.y = oldHeadY;
console.debug("Corrected tail Position: (" + this.tail.x + ", " + this.tail.y + "), head position: (" + this.head.x + ", " + this.head.y + ")");
}
if(tails.length > 0)
this.__correctTails(oldTailX, oldTailY, tail, tails[0], tails.slice(1));
}
};
/**
* Listener function for input in assignment field.
* @param event the onInput event
*/
function calculateAnswer(event) {
console.info("Calculating answer for input...");
let assignment = document.getElementById(ASSIGNMENT).value;
let byCompartiments = document.getElementById(ALGORITHM_CHECKBOX).checked;
let answer = algorithm(assignment, byCompartiments);
let answer = algorithm(event.target.value);
document.getElementById(ANSWER).innerText = answer;
}
@@ -33,121 +146,34 @@ function calculateAnswer(event) {
* @param assignment the input from the assignment.
* @return string the answer
*/
function algorithm(assignment, byCompartiments) {
let priorityScoreSum = 0;
function algorithm(assignment) {
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);
console.info("Linecount:" + lines.length);
let rope = new Rope(10);
let visitedPositions = [rope.getTailPosition()];
for(let i=0; i<lines.length; i++) {
let rucksack = lines[i].replace(/\s/g, ''); // Remove whitespace
let compartiment1 = rucksack.slice(0, rucksack.length/2);
let compartiment2 = rucksack.slice(rucksack.length/2);
let line = lines[i].replace(/\s/g, ''); // Remove all whitespace
let direction = line[0];
let count = parseInt(line.substring(1));
if(isNaN(count)) { // Validate count
console.error("Invalid number in line: " + lines[i]);
}
console.debug("Check rucksack" + i, ": " + rucksack + " \n with compartiment1: " + compartiment1 + "\n and compartiment2: " + compartiment2);
for(item of compartiment2) {
if(compartiment1.includes(item)) {
console.debug("Found duplicate: " + item + " in rucksack" + i);
let priorityScore = getPriorityScore(item);
if(priorityScore < 0) {
console.error(ERROR_MESSAGE_INVALID_ITEM_CHARACTER + item + " on line: " + i);
continue;
}
priorityScoreSum += priorityScore;
break;
}
}
}
while(count > 0) {
rope.step(direction);
let tailPosition = rope.getTailPosition();
return "SUM priorityscore: " + priorityScoreSum;
}
/**
* Find duplicate character in inputs.
* @param string[] inputs the inputs to find duplicates in.
* @return char the duplicate character
*/
function getDuplicateCharacter(inputs) {
console.debug("Checking inputs: " + inputs);
if(inputs.length < 2) {
return -1;
}
for(let item of inputs[0]) {
let duplicate = true
for(let j=1; j<inputs.length; j++) {
duplicate = duplicate && inputs[j].includes(item);
if(!visitedPositions.includes(tailPosition) ) { // Add only unique tailpositions
visitedPositions.push(tailPosition);
}
if(duplicate) {
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;
count--;
}
}
result += character.charCodeAt() - CHARCODE_START;
return result;
console.log(visitedPositions);
return "Amount of positions for tail: " + visitedPositions.length;
}

View File

@@ -6,10 +6,6 @@ body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
textarea {
display: block;
}
#answer {
color: purple
}