1 Commits

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

View File

@@ -1,12 +1,13 @@
# Advent of Code 2022 - assignment2 javascript # Advent of Code 2022 - Assignment5 javascript
## Description This repository contains answers to the assignments of Advent of Coding 2022
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://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://www.w3schools.com/jsref/jsref_includes.asp
- https://www.sohamkamani.com/javascript/enums/ - https://stackoverflow.com/questions/10261986/how-to-detect-string-which-contains-only-spaces
- 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://www.w3schools.com/jsref/jsref_indexof.asp
- 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/8073673/how-can-i-add-new-array-elements-at-the-beginning-of-an-array-in-javascript
- https://stackoverflow.com/questions/5765398/whats-the-best-way-to-convert-a-number-to-a-string-in-javascript - https://stackoverflow.com/questions/966225/how-can-i-create-a-two-dimensional-array-in-javascript
- https://www.w3schools.com/jsref/jsref_switch.asp - https://www.w3schools.com/jsref/jsref_ceil.asp
- https://www.w3schools.com/tags/att_input_type_checkbox.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,8 @@
<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">Interpret X,Y,Z as Rock Paper Scissor.</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>
<script src="script.js"></script> <script src="script.js"></script>

240
script.js
View File

@@ -1,55 +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_NO_SUCH_CHARACTER_IN_RPS = "Non existant character in rock paper scissor game selected: "; const CONTAINER_NULL_CHARACTER=0;
const ERROR_MESSAGE_TOO_FEW_CHARACTERS_IN_LINE = "Too few characters in line: "; const INSTRUCTION_FROM='from';
const INSTRUCTION_MOVE='move';
const INSTRUCTION_TO='to';
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
@@ -66,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 interpret_as_rps = document.getElementById(ALGORITHM_CHECKBOX).checked; let allAtOnce = document.getElementById(ALGORITHM_CHECKBOX).checked;
let answer = algorithm(assignment, interpret_as_rps); let answer = algorithm(assignment, allAtOnce);
document.getElementById(ANSWER).innerText = answer; document.getElementById(ANSWER).innerText = answer;
} }
@@ -75,117 +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 allAtOnce should all containers be moved at once.
* @return string the answer * @return string the answer
*/ */
function algorithm(assignment, interpret_as_rps) { function algorithm(assignment, allAtOnce) {
let errors = 0; let lines = assignment.split(NEWLINE_CHARACTER);
let lines = assignment.trim().split(NEWLINE_CHARACTER); let containerPlan = Array.from({length:(lines[0].length+1)/4}, () => [])
let score = 0;
console.info("Linecount:" + lines.length); console.info("Linecount:" + lines.length);
let parsec = true;
for(let i=0; i<lines.length; i++) { for(let i=0; i<lines.length; i++) {
let rps_match = lines[i].replace(/\s/g, ''); // remove all whitespace if(parsec) {
if(rps_match.length < 2) {
console.error(ERROR_MESSAGE_TOO_FEW_CHARACTERS_IN_LINE + i + ", skipped."); // Parse containers
errors++; let containerLine = lines[i];
// Skip numbers
if(containerLine[1] == '1') {
parsec = false;
i+=1;
console.table(containerPlan);
continue; continue;
} }
// Assign characters from line let containers = parseContainers(containerLine);
let opponent_hand = map_hand_character(rps_match[0]); if(containers == -1) {
let player_input = rps_match[1]; // invalid containerline
let player_hand = -1; // TODO: error
console.error("Container parse failure.");
// Validate hand
if(opponent_hand<0) {
console.error(ERROR_MESSAGE_NO_SUCH_CHARACTER_IN_RPS + rps_match[0] + " for line: " + i);
errors++;
continue; continue;
} }
// How should we interpret input? match_option or Rock Paper Scissors. // Add containers
if(interpret_as_rps) { //console.debug(containers);
player_hand = interpret_player_hand_as_rps_input(player_input); 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 { } else {
player_hand = interpret_player_hand_as_match_input(player_input, opponent_hand); // Parse instructions
} let instructionLine = lines[i];
let instruction = parseInstruction(instructionLine);
if(player_hand<0) { // Invalid input console.debug(instruction);
console.error(ERROR_MESSAGE_NO_SUCH_CHARACTER_IN_RPS + rps_match[1] + " for line: " + i); if(instruction == -1) {
errors++; // invalid instructionline
// TODO: error
console.error("Instruction parse failure.");
continue; continue;
} }
score += rps_result(player_hand, opponent_hand); // 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);
} }
if(errors > 0) { //console.table(containerPlan);
return errors.toString() + " Error(s) in input, see console for details." }
} }
return "Player score: " + score; let result="";
} for(let k=0; k<containerPlan.length; k++) {
result += containerPlan[k][0];
/**
* Interpret given input for player as a rock paper scissor character.
* @param char input the input for hand character (A,B,C,X,Y,Z)
* @return the player hand character or -1 if invalid.
*/
function interpret_player_hand_as_rps_input(input) {
return map_hand_character(input);
}
/**
* Interpret given input for player as a match option.
* @param char input the input for match option (X,Y,Z)
* @return the player hand character or -1 if invalid.
*/
function interpret_player_hand_as_match_input(input, opponent_hand) {
let player_hand = -1;
switch (input) {
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;
} }
return player_hand; return "Top containers on the stack are: " + result;
} }
/** function parseInstruction(instructionLine) {
* Maps the chosen hand character to let instruction={
* @param hand_character the chosen character move:0,
* @return RPS the rock paper scissor hand or -1 if invalid from:0,
*/ to:0,
function map_hand_character(hand_character) { }
if(!(hand_character in RPS_ALIAS_MAP)) {
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; return -1;
} }
return RPS_ALIAS_MAP[hand_character]; // 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) {
* Calculate the result of rock paper scissor match let containerLineLength = (containerLine.length+1);
* @param RPS player_hand the player's choice //console.debug("Parse ContainerLine, length: " + containerLineLength);
* @param RPS opponent_hand the opponent's choice
* @return score if(!containerLine.includes('[') || !containerLine.includes(']') || containerLineLength % 4 != 0) {
*/ return -1;
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 {
score = SCORE_LOSE + player_hand; // LOSE
} }
console.debug("score:" + score + ", player: " + player_hand + ", opponent: " + opponent_hand); let containers = [];
return score; 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;
} }

View File

@@ -9,6 +9,7 @@ body {
textarea { textarea {
display: block; display: block;
} }
#answer { #answer {
color: purple color: purple
} }