Compare commits
1 Commits
assignment
...
assignment
| Author | SHA1 | Date | |
|---|---|---|---|
| ee5e17f444 |
20
README.md
20
README.md
@@ -1,12 +1,12 @@
|
|||||||
# Advent of Code 2022 - Assignment3 javascript solution
|
# Advent of Code 2022 - assignment2 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.
|
Assignment2 involves a game of rock paper scissors. The solution uses an enum for rock, paper, scissor values it defines two functions for selecting a winning and losing hand. The winning and losing hand take advantage of the fact that each next value in the rock, paper, scissor trio beats the previous (looping back to rock). For losing it is the other way around. The winning_hand function is also used to determine the score for player. In the GUI there is a checkbox for selecting solution options (part1,part2).
|
||||||
|
|
||||||
## References
|
## References
|
||||||
- https://stackoverflow.com/questions/94037/convert-character-to-ascii-code-in-javascript
|
- https://www.psychologytoday.com/us/blog/the-blame-game/201504/the-surprising-psychology-rock-paper-scissors#:~:text=There%20are%20four%20possible%20outcomes,Douglas%20Walker%20and%20Graham%20Walker.
|
||||||
- https://stackoverflow.com/questions/20474257/split-string-into-two-parts
|
- https://www.sohamkamani.com/javascript/enums/
|
||||||
- https://www.folkstalk.com/2022/10/find-common-characters-in-two-strings-javascript-with-code-examples.html
|
- https://codingbeautydev.com/blog/javascript-remove-all-whitespace-from-string/#:~:text=To%20remove%20all%20whitespace%20from%20a%20string%20in%20JavaScript%2C%20call,all%20whitespace%20removed%20from%20str%20.
|
||||||
- https://stackoverflow.com/questions/351409/how-to-append-something-to-an-array
|
- https://www.geeksforgeeks.org/how-to-check-a-key-exists-in-javascript-object/#:~:text=There%20are%20mainly%20two%20methods,property%20is%20in%20the%20object.
|
||||||
- https://stackoverflow.com/questions/9862761/how-to-check-if-character-is-a-letter-in-javascript
|
- https://stackoverflow.com/questions/5765398/whats-the-best-way-to-convert-a-number-to-a-string-in-javascript
|
||||||
- https://stackoverflow.com/questions/1966476/how-can-i-process-each-letter-of-text-using-javascript
|
- https://www.w3schools.com/jsref/jsref_switch.asp
|
||||||
- https://www.w3schools.com/js/js_arrays.asp
|
- https://www.w3schools.com/tags/att_input_type_checkbox.asp
|
||||||
|
|||||||
@@ -9,8 +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">Interpret X,Y,Z as Rock Paper Scissor.</label>
|
||||||
|
|
||||||
<p>Answer:</p>
|
<p>Answer:</p>
|
||||||
<div id="answer">Provide input first</div>
|
<div id="answer">Provide input first</div>
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
|
|||||||
240
script.js
240
script.js
@@ -1,11 +1,55 @@
|
|||||||
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_NO_SUCH_CHARACTER_IN_RPS = "Non existant character in rock paper scissor game selected: ";
|
||||||
const CHARCODE_UPPER_CORRECTION=6;
|
const ERROR_MESSAGE_TOO_FEW_CHARACTERS_IN_LINE = "Too few characters in line: ";
|
||||||
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 OPTION_LOSE = 'X';
|
||||||
|
const OPTION_TIE = 'Y';
|
||||||
|
const OPTION_WIN = 'Z';
|
||||||
|
|
||||||
|
const RPS = Object.freeze({
|
||||||
|
ROCK: 1,
|
||||||
|
PAPER: 2,
|
||||||
|
SCISSORS: 3,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select winning hand for given hand.
|
||||||
|
* @param hand the chosen hand
|
||||||
|
* @return RPS the winning hand
|
||||||
|
*/
|
||||||
|
winning_hand: function(hand) {
|
||||||
|
hand++;
|
||||||
|
if(hand > RPS.SCISSORS) {
|
||||||
|
hand = RPS.ROCK;
|
||||||
|
}
|
||||||
|
return hand;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select losing hand for given hand.
|
||||||
|
* @param hand the chosen hand
|
||||||
|
* @return RPS the losing hand
|
||||||
|
*/
|
||||||
|
losing_hand: function(hand) {
|
||||||
|
hand--;
|
||||||
|
if(hand < RPS.ROCK) {
|
||||||
|
hand = RPS.SCISSORS;
|
||||||
|
}
|
||||||
|
return hand;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const RPS_ALIAS_MAP = Object.freeze({
|
||||||
|
"A": RPS.ROCK,
|
||||||
|
"B": RPS.PAPER,
|
||||||
|
"C": RPS.SCISSORS,
|
||||||
|
"X": RPS.ROCK,
|
||||||
|
"Y": RPS.PAPER,
|
||||||
|
"Z": RPS.SCISSORS,
|
||||||
|
})
|
||||||
|
const SCORE_LOSE = 0;
|
||||||
|
const SCORE_TIE = 3;
|
||||||
|
const SCORE_WIN = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main function
|
* Main function
|
||||||
@@ -22,8 +66,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 interpret_as_rps = document.getElementById(ALGORITHM_CHECKBOX).checked;
|
||||||
let answer = algorithm(assignment, byCompartiments);
|
let answer = algorithm(assignment, interpret_as_rps);
|
||||||
|
|
||||||
document.getElementById(ANSWER).innerText = answer;
|
document.getElementById(ANSWER).innerText = answer;
|
||||||
}
|
}
|
||||||
@@ -33,121 +77,115 @@ function calculateAnswer(event) {
|
|||||||
* @param assignment the input from the assignment.
|
* @param assignment the input from the assignment.
|
||||||
* @return string the answer
|
* @return string the answer
|
||||||
*/
|
*/
|
||||||
function algorithm(assignment, byCompartiments) {
|
function algorithm(assignment, interpret_as_rps) {
|
||||||
let priorityScoreSum = 0;
|
let errors = 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);
|
||||||
|
let score = 0;
|
||||||
console.info("Linecount:" + lines.length);
|
console.info("Linecount:" + lines.length);
|
||||||
|
|
||||||
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 rps_match = lines[i].replace(/\s/g, ''); // remove all whitespace
|
||||||
let compartiment1 = rucksack.slice(0, rucksack.length/2);
|
if(rps_match.length < 2) {
|
||||||
let compartiment2 = rucksack.slice(rucksack.length/2);
|
console.error(ERROR_MESSAGE_TOO_FEW_CHARACTERS_IN_LINE + i + ", skipped.");
|
||||||
|
errors++;
|
||||||
console.debug("Check rucksack" + i, ": " + rucksack + " \n with compartiment1: " + compartiment1 + "\n and compartiment2: " + compartiment2);
|
continue;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assign characters from line
|
||||||
|
let opponent_hand = map_hand_character(rps_match[0]);
|
||||||
|
let player_input = rps_match[1];
|
||||||
|
let player_hand = -1;
|
||||||
|
|
||||||
|
// Validate hand
|
||||||
|
if(opponent_hand<0) {
|
||||||
|
console.error(ERROR_MESSAGE_NO_SUCH_CHARACTER_IN_RPS + rps_match[0] + " for line: " + i);
|
||||||
|
errors++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// How should we interpret input? match_option or Rock Paper Scissors.
|
||||||
|
if(interpret_as_rps) {
|
||||||
|
player_hand = interpret_player_hand_as_rps_input(player_input);
|
||||||
|
} else {
|
||||||
|
player_hand = interpret_player_hand_as_match_input(player_input, opponent_hand);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(player_hand<0) { // Invalid input
|
||||||
|
console.error(ERROR_MESSAGE_NO_SUCH_CHARACTER_IN_RPS + rps_match[1] + " for line: " + i);
|
||||||
|
errors++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
score += rps_result(player_hand, opponent_hand);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "SUM priorityscore: " + priorityScoreSum;
|
if(errors > 0) {
|
||||||
|
return errors.toString() + " Error(s) in input, see console for details."
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Player score: " + score;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find duplicate character in inputs.
|
* Interpret given input for player as a rock paper scissor character.
|
||||||
* @param string[] inputs the inputs to find duplicates in.
|
* @param char input the input for hand character (A,B,C,X,Y,Z)
|
||||||
* @return char the duplicate character
|
* @return the player hand character or -1 if invalid.
|
||||||
*/
|
*/
|
||||||
function getDuplicateCharacter(inputs) {
|
function interpret_player_hand_as_rps_input(input) {
|
||||||
console.debug("Checking inputs: " + inputs);
|
return map_hand_character(input);
|
||||||
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(duplicate) {
|
|
||||||
console.debug("Found duplicate: " + item);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns priorityscore for given character.
|
* Interpret given input for player as a match option.
|
||||||
* @param char character the character
|
* @param char input the input for match option (X,Y,Z)
|
||||||
* @return int the priorityscore for character or -1 if invalid
|
* @return the player hand character or -1 if invalid.
|
||||||
*/
|
*/
|
||||||
function getPriorityScore(character) {
|
function interpret_player_hand_as_match_input(input, opponent_hand) {
|
||||||
let result=0;
|
let player_hand = -1;
|
||||||
let uppercase = character.toUpperCase();
|
switch (input) {
|
||||||
let lowercase = character.toLowerCase();
|
case OPTION_LOSE:
|
||||||
|
player_hand = RPS.losing_hand(opponent_hand);
|
||||||
|
break;
|
||||||
|
case OPTION_WIN:
|
||||||
|
player_hand = RPS.winning_hand(opponent_hand);
|
||||||
|
break;
|
||||||
|
case OPTION_TIE:
|
||||||
|
player_hand = opponent_hand;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// validate character
|
return player_hand;
|
||||||
if( uppercase == lowercase ) {
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps the chosen hand character to
|
||||||
|
* @param hand_character the chosen character
|
||||||
|
* @return RPS the rock paper scissor hand or -1 if invalid
|
||||||
|
*/
|
||||||
|
function map_hand_character(hand_character) {
|
||||||
|
if(!(hand_character in RPS_ALIAS_MAP)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(character == uppercase) { // Switch results for upper and lowercase characters
|
return RPS_ALIAS_MAP[hand_character];
|
||||||
result -= CHARCODE_UPPER_CORRECTION;
|
}
|
||||||
character = lowercase;
|
|
||||||
|
/**
|
||||||
|
* Calculate the result of rock paper scissor match
|
||||||
|
* @param RPS player_hand the player's choice
|
||||||
|
* @param RPS opponent_hand the opponent's choice
|
||||||
|
* @return score
|
||||||
|
*/
|
||||||
|
function rps_result(player_hand, opponent_hand) {
|
||||||
|
let score = 0;
|
||||||
|
if(player_hand == opponent_hand) {
|
||||||
|
score = SCORE_TIE + player_hand; // TIE
|
||||||
|
} else if(player_hand == RPS.winning_hand(opponent_hand)) {
|
||||||
|
score = SCORE_WIN + player_hand; // WIN
|
||||||
} else {
|
} else {
|
||||||
character = uppercase;
|
score = SCORE_LOSE + player_hand; // LOSE
|
||||||
}
|
}
|
||||||
|
|
||||||
result += character.charCodeAt() - CHARCODE_START;
|
console.debug("score:" + score + ", player: " + player_hand + ", opponent: " + opponent_hand);
|
||||||
|
return score;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user