1 Commits

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

View File

@@ -1,9 +1,14 @@
# Advent of Code 2022 - Assignment 4 - javascript # Advent of Code - assignment 9 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_indexof.asp - https://betterprogramming.pub/tuples-in-javascript-57ede9b1c9d2
- https://www.geeksforgeeks.org/convert-a-string-to-an-integer-in-javascript/#:~:text=In%20JavaScript%20parseInt()%20function,argument%20of%20parseInt()%20function. - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring - https://www.javascripttutorial.net/javascript-multidimensional-array/
- https://medium.com/@raihan_tazdid/overlapping-numbers-in-ranges-5d0f2efc294e - 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> <body>
<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"/>
<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>

203
script.js
View File

@@ -1,28 +1,142 @@
const ASSIGNMENT = 'assignment'; const ASSIGNMENT = 'assignment';
const ANSWER = 'answer'; const ANSWER = 'answer';
const ALGORITHM_CHECKBOX = 'algorithm';
const ERROR_MESSAGE_INVALID_RANGE = "Invalid range, ";
const COMMA_CHARACTER = ',';
const NEWLINE_CHARACTER = '\n'; const NEWLINE_CHARACTER = '\n';
const RANGE_CHARACTER = '-';
/** /**
* Main function * Main function
*/ */
window.onload = function() { window.onload = function() {
document.getElementById(ASSIGNMENT).addEventListener("input", calculateAnswer); 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. * Listener function for input in assignment field.
* @param event the onInput event * @param event the onInput event
*/ */
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 answer = algorithm(event.target.value);
let fullOverlap = document.getElementById(ALGORITHM_CHECKBOX).checked;
let answer = algorithm(assignment, fullOverlap);
document.getElementById(ANSWER).innerText = answer; document.getElementById(ANSWER).innerText = answer;
} }
@@ -30,73 +144,36 @@ 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, fullOverlap) { function algorithm(assignment) {
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; let rope = new Rope(10);
let visitedPositions = [rope.getTailPosition()];
for(let i=0; i<lines.length; i++) { for(let i=0; i<lines.length; i++) {
let error = false; let line = lines[i].replace(/\s/g, ''); // Remove all whitespace
let ranges = lines[i].trim(); let direction = line[0];
// Search for separation charactes -,- let count = parseInt(line.substring(1));
let range1CharacterIndex = ranges.indexOf(RANGE_CHARACTER);
let range1EndCharacterIndex = ranges.indexOf(COMMA_CHARACTER);
let range2CharacterIndex = ranges.indexOf(RANGE_CHARACTER, range1CharacterIndex+1);
// Get range substrings if(isNaN(count)) { // Validate count
let range1LowerString = ranges.substring(0,range1CharacterIndex); console.error("Invalid number in line: " + 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
let range1Lower = parseInt(range1LowerString);
let range1Higher = parseInt(range1HigherString);
let range2Lower = parseInt(range2LowerString);
let range2Higher = parseInt(range2HigherString);
// 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) { while(count > 0) {
continue; rope.step(direction);
let tailPosition = rope.getTailPosition();
if(!visitedPositions.includes(tailPosition) ) { // Add only unique tailpositions
visitedPositions.push(tailPosition);
} }
// Check for overlap count--;
if(fullOverlap && doesRangeFullyOverlap(range1Lower, range1Higher, range2Lower, range2Higher)
|| !fullOverlap && doesRangeOverlap(range1Lower, range1Higher, range2Lower, range2Higher)) {
console.debug("Found overlapping range:" + range1Lower + "-" + range1Higher + "," + range2Lower + "-" + range2Higher);
containedPairs++;
} }
} }
return "Fully overlapping timeslot counts: " + containedPairs; console.log(visitedPositions);
} return "Amount of positions for tail: " + visitedPositions.length;
function doesRangeFullyOverlap(lower, higher, lower2, higher2) {
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) {
console.debug("Compare range: " + lower + "-" + higher + " with " + lower2 + "-" + higher2);
if(lower > higher || lower2 > higher2) {
return false;
}
return higher2 >= lower && lower2 <= higher;
} }

View File

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