Published
Edited
Feb 25, 2019
Insert cell
Insert cell
Insert cell
Insert cell
Math.random()
Insert cell
Insert cell
// create function that generates random number within a user-inputted range

function randomInRange(min, max){
// Check how many parameters are inputted.
// If 1 instead of 2, recognize that the inputs is the max value and assign 0 as min.
if (max === undefined) {
max = min;
min = 0;
}
// generate the random number to be returned
// Use Math.random to generate random value from 0 to 1, and scale it to cover the range covered by max-min
// Shift it by + min so that output covers the part of the number line specified by the user inputs.
// Round to nearest integer
let rand = Math.round((Math.random())*(max-min)+min);
return rand;
}

Insert cell
// tester function that takes in min, max, and value to be tested

function randomTester(minTest, maxTest, valueTest)
{
// Check how many parameters are inputted.
// If 2 instead of 3, recognize that the inputs are the max value and the value to be tested. Assign 0 as min.
if (valueTest === undefined) {
valueTest = maxTest;
maxTest = minTest;
minTest = 0;
}
// Test if value being tested is within the specified range. If so, return true. Otherwise, return false.
if (valueTest <= maxTest && valueTest >= minTest) {
return true+": Randomly generated value "+valueTest+" is between "+minTest+" and "+maxTest;
}
else {
return false+": Randomly generated value "+valueTest+" is not between "+minTest+" and "+maxTest;
}
}

Insert cell
//run tester in the case where only 1 parameter is passed to the random generator
{
return randomTester(23, randomInRange(23));
}
Insert cell
//run tester in the case where both parameters are passed to the random generator
{
return randomTester(13, 234, randomInRange(13, 234));
}
Insert cell
Insert cell
// set input string to title-case by capitalizing the start of each word
// does not account for special conditions

function titleCase(text) {
let textlower = (text.slice()).toLowerCase(); //set input to all lower case in case it has unusual capitalization
let textCap = ""; //initialize string to hold output
// Loop through each letter in input string, capitalizing the letter if needed before adding it to output string
// Always capitalize first letter in the input string
// For other letters, capitalize only if it is preceeded by a space, which indicates start of a new word
for (let i = 0; i < text.length; i++) {
if (i === 0) {
textCap = textCap + textlower[i].toUpperCase();
} else if (textlower[i-1] === " ") {
textCap = textCap + textlower[i].toUpperCase();
} else {
textCap = textCap + textlower[i];
}
}
return textCap;
}

Insert cell
//test titleCase
titleCase("tHERE was a QuiCk bROWn fox!")
Insert cell
//formatter1: first input optional
function formatter1(title, N)
{
// check if user only passed the function one parameter
// if so, that parameter should be N, since first input is optional
// assumes the user passes a value that would make sense being used as N, ie an int
if (N === undefined) {
N = title;
title = "Some Book";
}
// return the desired output with title in title case
return "The number " + N + " bestseller today is: " + titleCase(title);
}
Insert cell
//test formatter1 when both parameters are filled
formatter1("lord of tHE rings", 1)
Insert cell
//test formatter1 when only 2nd parameter is filled
formatter1(10)
Insert cell
//formatter2: second input optional
function formatter2(title, N)
{
// check if user only passed the function one parameter
// If so, that parameter should be the title, since second input is optional. We put in a default value for N
// assumes the user passes a value that would make sense being used as title, ie a string
if (N === undefined) {
N = 1;
}
// return the desired output with the title in title case
return "The number " + N + " bestseller today is: " + titleCase(title);
}
Insert cell
//test formatter2 when user passes in both parameters
formatter2("lOrd of the rinGs", 2)
Insert cell
//test formatter2 when user passes in only 1st parameter
formatter2("the wandERIng earTH")
Insert cell
// formatter3: both inputs optional
function formatter3(title, N)
{
if (N === undefined) {
if (title === undefined) {
// if both title, N are undefined, then the user has passed the function zero parameters
// we use default values for both title and N
title = "Some Book";
N = 1;
} else if(!isNaN(title)) {
// if only N is undefined, the user has passed the function one parameter
// check whether that parameter is a number; if so assign that parameter input to N
// and use default name for book since user did not input one
N = title;
title = "Some Book";
} else {
// if user passed the function only one parameter but that parameter is not a number, then it's a title
// keep the parameter input as the title and use a default value for N
N = 1;
}
}
// return desired outpuut with appropriate title capitalization
return "The number " + N + " bestseller today is: " + titleCase(title);
}

Insert cell
//test formatter3 in the case where user passes in no inputs
formatter3()
Insert cell
//test formatter3 when the user only inputs a title
formatter3("The lord of the rings")
Insert cell
//test formatter3 when user only inputs book rank
formatter3(23)
Insert cell
Insert cell
// password validation function; parameter passed in is the user password attempt

function validator(pwd) {
// check if password is 8-14 char, inclusive; if not return false
if (pwd.length >= 8 && pwd.length <= 14) {
// if password is the right length, check to see it contains the necessary chars
// begin checking for this by initializing counters for each desired characteristics
// also, input the list of special characters that we must check against
let digitCount = 0;
let upperCount = 0;
let specialCount = 0;
let specialList = "!@#$%^&*()-_+="
// loop through each char in the password attempt inputted by the user
for (let i = 0; i < pwd.length; i++) {
if (!isNaN(pwd[i])) {
digitCount++; // increment count of included digits if the char is a digit
}
if (pwd[i] >= "A" && pwd[i] <= "Z") {
upperCount++; // increment count of capital letters if char is capitalized
// takes advantage of how Javascript orders chars by listing all caps before all lower case letters
}
if (specialList.indexOf(pwd[i]) > -1) {
specialCount++; // increment the special character counte if the char is one of the special characters
// the condition uses the fact that indexOf returns -1 if a value is not found in the target list
}
}
if (digitCount >= 2 && upperCount >= 1 && specialCount >= 1) {
return true; // if the right number of digits, caps, and special char are located, password is valid
}
else {
return false; // if not the right number of these elements are included, password is invalid
}
}
else {
return false; // if password is not the right length, it is invalid
}
}
Insert cell
Insert cell
Insert cell
{
// validate input from the text box above, which is saved in pwdInput
// if it's valid, reset total attempts counter to 3 and tell user s/he succeeded
if (validator(pwdInput)) {
attempts.value = 3;
return("Success! You've set your password.");
}
else {
// if attempt is unsuccessful and there are still attempts left,
// decrement attempts counter and ask user to try again
// tell user how many attempts are left and what the pwd requires are
if (attempts.value > 1) {
attempts.value--;
return "TRY AGAIN. You have " + attempts.value + " attempts left. \n Passwords must be 8-14 characters, with at least 2 numbers, 1 upper case, and one of !@#$%^&*()-_+="
}
else {
// if attempt is unsuccessful and there are no attempts left,
// restart the attempts counter and tell user s/he has tried too many times
attempts.value = 3; //reset attempts counter
return "Sorry, you've tried too many times. Quitting password setting mode."
}
}
}
Insert cell
// password attempt counter, declared as global variable courtesy of Dylan H's idea as per his Piazza post
attempts = html`<input type = range min = 0 max = 3 step = 1>`
Insert cell
Insert cell
// exponentiation function that takes in a user-specified base and an exponent

function exp(base, exponent) {
if (exponent === 0) {
return 1; // covers the fact that any number to the power of 0 is 1
}
else if (exponent === 1) {
return base; // any number to the power of 1 is itself; this is the stopping condition for the recursion
}
else {
if (exponent > 0) {
return base * exp(base, exponent - 1);
// if exponent is not 0, 1 but is positive, continue calculating the exponentiation by
// calling exp but with a decremented exponent
// this is equivalent to calculating, for example, b^3 = b*(b^2)
// hope recursively calling my own function counts as using at least one custom-defined function
}
else {
return 1/(exp(base, -exponent));
// if exponent is negative, continue calculating exponentiation by
// calculating the value of the same base but to the absolute value of that exponent, then taking reciprocal
}
}
}

Insert cell
//test exponentiation function
exp(5,4)
Insert cell
//test exponentiation function
exp(2,-3)
Insert cell
Insert cell
// find minimum assuming list passed in contains only numbers

function min(numberList) {
// initialize a var containing the lowest number encountered so far; start it at the first item in the array
let minNum = numberList[0];
// loop through each item in the remainder of the list, updating minNum if the number encountered
// in the list is lower than the current value of minNum
for(var i = 1; i < numberList.length; i++) {
if(numberList[i] < minNum){
minNum = numberList[i];
}
}
return minNum; // return the smallest item in the list
}
Insert cell
// test min
min([80,3,90,1,23,45,-23,-1])

Insert cell
//find maximum assuming list passed in contains only numbers

function max(numberList) {
// initialize a var containing the largest number encountered so far; start it at the first item in the array
let maxNum = numberList[0];
for(var i = 1; i < numberList.length; i++) {
// loop through each item in the remainder of the list, updating maxNum if the number encountered
// in the list is larger than the current value of maxNum
if(numberList[i] > maxNum){
maxNum = numberList[i];
}
}
return maxNum; // return the largest item in the list
}
Insert cell
// test max
max([80,3,92,1,23,45,81,-1])
Insert cell
Insert cell
Insert cell
{
// runs the game
return hangMan(gameGuess);
}
Insert cell
// function to process guesses

function hangMan(guess) {
// check guess passed in by the user if there are still guess attempts remaining on the guess counter
if(counter.value > 1) {
if(!guess) {
return "You didn't make a guess! Try again." //if empty input, prompt user to make actual guess
}
// if actual guess is inputted, convert to lower case since our word is in lower case
// update status of the game with our guess; status shows, for example, b--b--b--
guess = (guess[0]).toLowerCase();
updateGame(guess);
// after game status has been updated, check to see if user has guessed the full word
// if so, congratulate user after restarting counter, game state
if(state.value === dictionary) {
counter.value = 8;
state.value = "---------";
return dictionary + ": You got the word! Let's play again!";
}
else if (check(guess) > -1) {
// if guess checkers says guessed letter is part of the word,
// give player the updated game status and number guesses remaining
// counter not decremented for correct guesses
return state.value + ": Great guess! You still have " + counter.value + " guesses left.";
}
else {
// if wrong guess, decrement guess counter
// if that was user's last guess, reinitiate game by resetting game state and counter and tell user game over
// if there are guesses remaining, tell user the guess was wrong, the state of the game, guesses remaining
counter.value--;
if (counter.value === 0) {
counter.value = 8;
state.value = "---------";
return state.value + ": Nope, sorry! And you're out of turns. Let's start over";
}
else {
return state.value + ": Nope, sorry. " + counter.value + " guesses left.";
}
}
}
// if there are no turns remaining, restart the game by resetting counter, game state and informing user
counter.value = 8;
state.value = "---------";
return "Sorry, you're out of turns."
}
Insert cell
// checks if user's letter guess is in the target word
// returns -1 if guess is not in word

function check(guess) {
return dictionary.indexOf(guess.toLowerCase());
}
Insert cell
// updates game state given an input

function updateGame(guess) {
let checkResult = check(guess); // check if guess appears in target word
if (checkResult > -1 ) {
// if guess does appear in target word, start a new output string
// loop through each char of the target word; if char matches guess, copy that char into the new output string
// if the char does not match, keep the existing state of the game for that slot in the string
let newvalue = "";
for (let i = 0; i < dictionary.length; ++i) {
if (dictionary[i] === guess) {
newvalue += guess;
}
else {
newvalue += state.value[i];
}
}
state.value = newvalue; // update game state to the new value that incorporates the latest guess
}
}
Insert cell
//it's a small game...just one word to guess
dictionary = "bumblebee"
Insert cell
// Thanks to Dylan H for his idea on implementing global variables in Observable, as he posted in Piazza.
// "Global variable" tracking number of remaining guesses. Counter deducted for wrong guesses only.
counter = html`<input type = range min = 0 max = 8 step = 1>`
Insert cell
//"Global variable" tracking state of the game. Initialize with blanks for all the letters of "bumblebee"
state = html`<input value = "---------">`
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more