Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Class Photos

It’s photo day at the local school, and you’re the photographer assigned to take class photos. The class that you’ll be photographing has an even number of students, and all these students are wearing red or blue shirts. In fact, exactly half of the class is wearing red shirts, and the other half is wearing blue shirts. You’re responsible for arranging the students in two rows before taking the photo. Each row should contain the same number of the students and should adhere to the following guidelines:

  • All students wearing red shirts must be in the same row.
  • All students wearing blue shirts must be in the same row.
  • Each student in the back row must be strictly taller than the student directly in front of them in the front row.

You’re given two input arrays: one containing the heights of all the students with red shirts and another one containing the heights of all the students with blue shirts. These arrays will always have the same length, and each height will be a positive integer. Write a function that returns whether or not a class photo that follows the stated guidelines can be taken.

Note: you can assume that each class has at least 2 students.

Sample Input

redShirtHeights=[5, 8, 1, 3, 4]
blueShirtHeights=[6, 9, 2, 4, 5]

Sample Output

true

Solution

  1. Sort lists in reversed order
  2. Find which row goes in the back and which row goes in the front by comparing the tallest height of red and blue lists
  3. Loop through both lists and compare height for each position
  4. Return false if a position in the front row is taller than a position in the back row, else return true

Time Complexity: O(n log n)

Space Complexity: O(1)

Algorithm used: Greedy Algorithm

static boolean canTakeClassPhotos(List<Integer> redShirtHeights, List<Integer> blueShirtHeights) {
    Collections.sort(redShirtHeights, Collections.reverseOrder());
    Collections.sort(blueShirtHeights, Collections.reverseOrder());

    System.out.println("redShirtHeights: " + redShirtHeights);
    System.out.println("blueShirtHeights: " + blueShirtHeights);

    boolean canTakePhoto = true;

    String frontRowColor = (redShirtHeights.get(0) < blueShirtHeights.get(0)) ? "RED" : "BLUE";

    System.out.println("frontRowColor: " + frontRowColor);

    for (int i = 0; i < redShirtHeights.size(); i++) {
        int redShirtHeight = redShirtHeights.get(i);// front row
        int blueShirtHeight = blueShirtHeights.get(i);// back row

        if (frontRowColor.equals("RED")) {

            if (redShirtHeight >= blueShirtHeight) {
                canTakePhoto = false;
                break;
            }

        } else if (frontRowColor.equals("BLUE")) {
            if (redShirtHeight <= blueShirtHeight) {
                canTakePhoto = false;
                break;
            }
        }
    }

    System.out.println("canTakePhoto: " + canTakePhoto + "\n\n");

    return canTakePhoto;
}
List<Integer> redShirtHeights = Arrays.asList(5, 8, 1, 3, 4);
List<Integer> blueShirtHeights = Arrays.asList(6, 9, 2, 4, 5);

canTakeClassPhotos(redShirtHeights, blueShirtHeights);// true

redShirtHeights = Arrays.asList(6, 9, 2, 4, 5);
blueShirtHeights = Arrays.asList(5, 8, 1, 3, 4);

canTakeClassPhotos(redShirtHeights, blueShirtHeights);// true

redShirtHeights = Arrays.asList(6, 9, 2, 4, 5, 1);
blueShirtHeights = Arrays.asList(5, 8, 1, 3, 4, 9);

canTakeClassPhotos(redShirtHeights, blueShirtHeights);// false

redShirtHeights = Arrays.asList(6);
blueShirtHeights = Arrays.asList(6);

canTakeClassPhotos(redShirtHeights, blueShirtHeights);// false

 

Source code on Github

February 15, 2017

Javascript Debugging

Programming code might contain syntax errors, or logical errors. Many of these errors are difficult to diagnose. Often, when programming code contains errors, nothing will happen. There are no error messages, and you will get no indications where to search for errors. Searching for (and fixing) errors in programming code is called code debugging.

Debugging is the process of testing, finding, and reducing bugs (errors) in computer programs. The first known computer bug was a real bug (an insect) stuck in the electronics.

JavaScript Debuggers

Debugging is not easy. But fortunately, all modern browsers have a built-in JavaScript debugger.

Built-in debuggers can be turned on and off, forcing errors to be reported to the user.

With a debugger, you can also set breakpoints (places where code execution can be stopped), and examine variables while the code is executing.

Normally, otherwise follow the steps at the bottom of this page, you activate debugging in your browser with the F12 key, and select “Console” in the debugger menu.

The console.log() Method

If your browser supports debugging, you can use console.log() to display JavaScript values in the debugger window:

<!DOCTYPE html>
<html>
<body>

<h1>First Web Page</h1>

<script>
num1 = 2;
num2 = 6;
sum = num1 + num2;
console.log(sum);// 8
</script>

</body>
</html>

Setting Breakpoints

In the debugger window, you can set breakpoints in the JavaScript code. At each breakpoint, JavaScript will stop executing, and let you examine JavaScript values. After examining values, you can resume the execution of code (typically with a play button).

The debugger Keyword

The debugger keyword stops the execution of JavaScript, and calls (if available) the debugging function.

This has the same function as setting a breakpoint in the debugger.

If no debugging is available, the debugger statement has no effect.

With the debugger turned on, this code will stop executing before it executes the third line.

var x = 15 * 5;
debugger;
document.getElementById("demo").innerHTML = x;

 

How to open developer tools in your favorite browser

Chrome
  • Open the browser.
  • From the menu, select “More tools”.
  • From tools, choose “Developer tools”.
  • Finally, select Console.
Firefox
  • Open the browser.
  • From the menu, select “Web Developer”.
  • Finally, select “Web Console”.
Edge
  • Open the browser.
  • From the menu, select “Developer Tools”.
  • Finally, select “Console”.
Opera
  • Open the browser.
  • From the menu, select “Developer”.
  • From “Developer”, select “Developer tools”.
  • Finally, select “Console”.
Safari
  • Go to Safari, Preferences, Advanced in the main menu.
  • Check “Enable Show Develop menu in menu bar”.
  • When the new option “Develop” appears in the menu:
    Choose “Show Error Console”.
October 10, 2010

Javascript Runtime

Call Stack

JavaScript engine uses a call stack to manage  execution contexts : the Global Execution Context and Function Execution Contexts.

The call stack works based on the LIFO principle i.e., last-in-first-out.

When you execute a script, the JavaScript engine creates a Global Execution Context and pushes it on top of the call stack.

Whenever a function is called, the JavaScript engine creates a Function Execution Context for the function, pushes it on top of the Call Stack, and starts executing the function.

If a function calls another function, the JavaScript engine creates a new Function Execution Context for the function that is being called and pushes it on top of the call stack.

When the current function completes, the JavaScript engine pops it off the call stack and resumes the execution where it left off in the last code listing.

The script will stop when the call stack is empty.

Stack Overflow

The call stack has a fixed size, depending on the implementation of the host environment, either the web browser or Node.js. If the number of the execution contexts exceeds the size of the stack, a stack overflow will occur.

 

Asynchronous Calls

JavaScript is the single-threaded programming language. The JavaScript engine has only one call stack so that it only can do one thing at a time. When executing a script, the JavaScript engine executes code from top to bottom, line by line. In other words, it is synchronous.

Asynchronous is the opposite of synchronous, which means happening at the same time. So how does JavaScript carry asynchronous tasks such as callbacks,  promises , and  async/await ? This is where the event loop comes into the picture.

If you have a function that takes a long time to execute, then you cannot do anything on the web browser during the function’s execution. The webpage just hangs. A function that takes a long time to execute is known as a blocking function. Technically, the blocking functions block all the interactions with the webpage such as mouse click. Some examples of blocking functions are the functions that download files from a remote server or functions that call an API from an external server.

To prevent blocking functions from blocking other activities, you typically wrap them in callback functions which can be executed later.

When an asynchronous function is invoked, the function is then placed into a queue called callback queue or task queue.

The event loop is a constantly running process that monitors both the callback queue and the call stack.

If the call stack is not empty, the event loop waits until it is empty and places the next function from the callback queue to the call stack. If the callback queue is empty, nothing will happen.

In this example, the timeout is 0 second so the message 'Execute immediately.' should appear before the message 'start!'. However, it is not the case. The console.log('Execute immediately.');is placed on the callback queue and executed only when the call stack is empty. In other words, it is executed only after the console.log('end!') is completed.

console.log('start!');

setTimeout(() => {
    console.log('Execute immediately.');
}, 0);

console.log('end!');

Output

start!
end!
Execute immediately.

 

 

October 10, 2010

Javascript Network Request

Fetch API

The Fetch API is a modern interface that allows you to make HTTP requests to servers from web browsers. The Fetch API is much simpler and cleaner. It uses the promise  to deliver more flexible features to make requests to servers from the web browsers. The fetch() method is available in the global scope that instructs the web browsers to send a request to a URL. You don’t have to install any library. 

Syntax

let promise = fetch(url, [options]);

Without options that is a simple GET request, downloading the contents of the url. The browser starts the request right away and returns a promise that the calling code should use to get the result.

POST Request

method – set to POST

body – the request body, one of following goes in the options.

    • a string (e.g. JSON-encoded)
    • Formdata object, to submit the data as form/multipart
    • Blob / BufferSource to send binary data

The JSON format is used most of the time.

let headers = {
    "Content-Type": "application/json",
    "x-api-key":"lovemesomecoding"
};
let user = {
    firstName: 'Folau',
    lastName: 'Kaveinga',
    email: 'folaukaveinga@gmail.com'
};

let options = {};
options.method = "POST";
options.body = JSON.stringify(user);
options.headers = headers;

let url = "http://localhost:8888/users/signup";

let response = await fetch(url, options);

if (response.ok) { // if HTTP-status is 200-299
    let data = await response.json();

    let content = "";
    content += "id: "+data.id+"<br>";
    content += "firstName: "+data.firstName+"<br>";
    content += "lastName: "+data.lastName+"<br>";
    content += "email: "+data.email+"<br>";

    document.getElementById("signUpContent").innerHTML = content;
    document.getElementById("errorMsg").innerHTML = "";
} else {
    let error = await response.json();
    console.log(error);
    document.getElementById("errorMsg").innerHTML = error.message;
}

GET Request

let headers = {
    "Content-Type": "application/json",
    "token":"lovemesomecoding-token"
};

let options = {};
options.method = "GET";
options.headers = headers;

let id = 1;

let url = "http://localhost:8888/users/"+id;

let response = await fetch(url, options);

if (response.ok) { // if HTTP-status is 200-299
    let data = await response.json();

    let content = "";
    content += "id: "+data.id+"<br>";
    content += "firstName: "+data.firstName+"<br>";
    content += "lastName: "+data.lastName+"<br>";
    content += "email: "+data.email+"<br>";

    document.getElementById("getUserContent").innerHTML = content;
    document.getElementById("errorMsg").innerHTML = "";
} else {
    let error = await response.json();
    console.log(error);
    document.getElementById("errorMsg").innerHTML = error.message;
}

PUT Request

let headers = {
    "Content-Type": "application/json",
    "token":"lovemesomecoding"
};
let user = {
    firstName: 'Folau',
    lastName: 'Kaveinga',
    email: 'folaukaveinga@gmail.com',
    id: 1
};

let options = {};
options.method = "PUT";
options.body = JSON.stringify(user);
options.headers = headers;

let url = "http://localhost:8888/users";

let response = await fetch(url, options);
//console.log(response);

if (response.ok) { // if HTTP-status is 200-299
    let data = await response.json();

    let content = "";
    content += "id: "+data.id+"<br>";
    content += "firstName: "+data.firstName+"<br>";
    content += "lastName: "+data.lastName+"<br>";
    content += "email: "+data.email+"<br>";

    document.getElementById("updateUserContent").innerHTML = content;
    document.getElementById("errorMsg").innerHTML = "";
} else {
    let error = await response.json();
    console.log(error);
    document.getElementById("errorMsg").innerHTML = error.message;
}

Upload File

Upload File
<br>
<div class="form-group">
    <label for="exampleFormControlFile1">file input</label>
    <input type="file" class="form-control-file" id="uploadingFile">
</div>
<button onclick="uploadFile()" type="button" class="btn btn-outline-primary">Upload File</button>
const formData = new FormData();
const fileField = document.getElementById("uploadingFile");
formData.append('file', fileField.files[0]);

let headers = {
    "token":"lovemesomecoding"
};

let options = {};
options.method = "POST";
options.body = formData;
options.headers = headers;

let url = "http://localhost:8888/users/document";

let response = await fetch(url, options);

if (response.ok) { // if HTTP-status is 200-299
    let data = await response.json();

    document.getElementById("uploadFileStatus").innerHTML = "uploaded: "+data;
    document.getElementById("errorMsg").innerHTML = "";
} else {
    let error = await response.json();
    console.log(error);
    document.getElementById("errorMsg").innerHTML = error.message;
}

Upload Multiple Files

Upload Files
<br>
<div class="form-group">
    <label for="exampleFormControlFile1">files input</label>
    <input type="file" class="form-control-file" id="uploadingFiles" multiple>
</div>
<button onclick="uploadFiles()" type="button" class="btn btn-outline-primary">Upload Files</button>
const formData = new FormData();
const fileField = document.getElementById("uploadingFiles");

for (let i = 0; i < fileField.files.length; i++) {
    formData.append('files', fileField.files[i]);
}

let headers = {
    "token":"lovemesomecoding"
};

let options = {};
options.method = "POST";
options.body = formData;
options.headers = headers;

let url = "http://localhost:8888/users/documents";

let response = await fetch(url, options);

if (response.ok) { // if HTTP-status is 200-299
    let data = await response.json();

    document.getElementById("uploadFileStatus").innerHTML = "uploaded: "+data;
    document.getElementById("errorMsg").innerHTML = "";

} else {
    let error = await response.json();
    console.log(error);
    document.getElementById("errorMsg").innerHTML = error.message;
}

Fetch source code on Github

Axios API

Install axios via npm

npm install axios

CDN script

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

Create an instance of Axios

const axiosInstance = axios.create({
    baseURL: 'http://localhost:8888',
    timeout: 1000,
    headers: {
        "Content-type": "application/json",
        "token": "foobar"
    }
});

POST Request

let headers = {
    "x-api-key":"lovemesomecoding"
};
let user = {
    firstName: 'Folau',
    lastName: 'Kaveinga',
    email: 'folaukaveinga@gmail.com'
};

let options = {};
options.method = "POST";
options.data = JSON.stringify(user);
options.headers = headers;

let url = "/users/signup";

let response = await axiosInstance(url, options);

console.log(response);

if (response.status >= 200) { 
    let data = await response.data;

    let content = "";
    content += "id: "+data.id+"<br>";
    content += "firstName: "+data.firstName+"<br>";
    content += "lastName: "+data.lastName+"<br>";
    content += "email: "+data.email+"<br>";

    document.getElementById("signUpContent").innerHTML = content;
    document.getElementById("errorMsg").innerHTML = "";
} else {
    let error = await response.json();
    console.log(error);
    document.getElementById("errorMsg").innerHTML = error.message;
}

 

GET Request

let headers = {
    "token":"lovemesomecoding-token"
};

let options = {};
options.method = "GET";
options.headers = headers;

let id = 1;

let url = "/users/"+id;

let response = await axiosInstance(url, options);

if (response.status >= 200) { 
    let data = await response.data;

    let content = "";
    content += "id: "+data.id+"<br>";
    content += "firstName: "+data.firstName+"<br>";
    content += "lastName: "+data.lastName+"<br>";
    content += "email: "+data.email+"<br>";

    document.getElementById("getUserContent").innerHTML = content;
    document.getElementById("errorMsg").innerHTML = "";
} else {
    let error = await response.data;
    console.log(error);
    document.getElementById("errorMsg").innerHTML = error.message;
}

 

PUT Request

let headers = {
    "token":"lovemesomecoding"
};
let user = {
    firstName: 'Folau',
    lastName: 'Kaveinga',
    email: 'folaukaveinga@gmail.com',
    id: 1
};

let options = {};
options.method = "PUT";
options.body = JSON.stringify(user);
options.headers = headers;

let url = "/users";

let response = await axiosInstance(url, options);
//console.log(response);

if (response.status >= 200) { 
    let data = await response.data;

    let content = "";
    content += "id: "+data.id+"<br>";
    content += "firstName: "+data.firstName+"<br>";
    content += "lastName: "+data.lastName+"<br>";
    content += "email: "+data.email+"<br>";

    document.getElementById("updateUserContent").innerHTML = content;
    document.getElementById("errorMsg").innerHTML = "";
} else {
    let error = await response.data;
    console.log(error);
    document.getElementById("errorMsg").innerHTML = error.message;
}

 

Upload File

const formData = new FormData();
const fileField = document.getElementById("uploadingFile");
formData.append('file', fileField.files[0]);

let headers = {
    "token":"lovemesomecoding",
    "Content-Type": "multipart/form-data"
};

let options = {
    // `onUploadProgress` allows handling of progress events for uploads
    // browser only
    onUploadProgress: function (progressEvent) {
        console.log("progressEvent");
        console.log(progressEvent);
    },
    // `onDownloadProgress` allows handling of progress events for downloads
    // browser only
    onDownloadProgress: function (progressEvent) {
        console.log("progressEvent");
        console.log(progressEvent);
    }
};
options.headers = headers;

let url = "/users/document";

let response = await axiosInstance.post(url, formData, options);

console.log(response);

if (response.status >= 200) { 
    let data = await response.data;

    document.getElementById("uploadFileStatus").innerHTML = "uploaded: "+data.finishUpload;
    document.getElementById("errorMsg").innerHTML = "";
} else {
    let error = await response.json();
    console.log(error);
    document.getElementById("errorMsg").innerHTML = error.message;
}

Upload Multiple Files

const formData = new FormData();
const fileField = document.getElementById("uploadingFiles");

for (let i = 0; i < fileField.files.length; i++) {
    formData.append('files', fileField.files[i]);
}

let headers = {
    "token":"lovemesomecoding",
    "Content-Type":"multipart/form-data"
};

let options = {
    // `onUploadProgress` allows handling of progress events for uploads
    // browser only
    onUploadProgress: function (progressEvent) {
        console.log("progressEvent");
        console.log(progressEvent);
    },
    // `onDownloadProgress` allows handling of progress events for downloads
    // browser only
    onDownloadProgress: function (progressEvent) {
        console.log("progressEvent");
        console.log(progressEvent);
    }
};

options.headers = headers;

let url = "/users/documents";

let response = await axiosInstance.post(url, formData, options);

if (response.status >= 200) { 
    let data = await response.data;

    document.getElementById("uploadFileStatus").innerHTML = "uploaded: "+data.finishUpload;
    document.getElementById("errorMsg").innerHTML = "";

} else {
    let error = await response.json();
    console.log(error);
    document.getElementById("errorMsg").innerHTML = error.message;
}

 

Axios source code on Github

October 10, 2010

Javascript Error Handling

No matter how great we are at programming, sometimes our code has errors. They may occur because of our mistakes, an unexpected user input, an erroneous server response, and for a thousand other reasons.

Javascript has try and catch to handle these errors and respond to users.

try {
    let name = getName();
} catch (error) {
    /*
    * error object that contains at least the name of the error and message that explains the error in detail.
    * Different web browsers may add more property to the error object. 
    * For example, Firefox adds filename, lineNumber, and stack properties to the error object.
    */
    console.log(error);//ReferenceError: getName is not defined
    console.log(error.name + ":" + error.message);//ReferenceError:getName is not defined
}finally {
    console.log("finally");
}

Try and Catch only works synchronously and does not work asynchronously.

/*
* try..catch only works synchronously. It does not work asynchronously.
*/

try {
    setTimeout(function() {
        getName(); // script will die here
    }, 1000);
} catch (error) {
    console.log("Error not caught here.");
}

setTimeout(function() {
    try {
        getName();
    } catch (error) {
        console.log(error);//ReferenceError: getName is not defined
        console.log(error.name + ":" + error.message);//ReferenceError:getName is not defined
    }
}, 1000);

 

Throw an Error

Use throw new typeOfError to throw an error.

function throwError(){
    throw new Error("Something went wrong due to Error!");
}

function throwReferenceError(){
    throw new ReferenceError("Something went wrong due to ReferenceError!");
}

try {
    throwError();
} catch (error) {
    console.log(error.name + ":" + error.message);
}

try {
    throwReferenceError();
} catch (error) {
    console.log(error.name + ":" + error.message);
}

 

Types of Error

  • Error
  • EvalError – an error has occurred in the eval() function. Note: Newer versions of JavaScript does not throw any EvalError. Use SyntaxError instead.
  • RangeError – a number “out of range” has occurred
  • ReferenceError – an illegal reference has occurred
  • SystaxError – a syntax error has occurred
  • TypeError – a type error has occurred
  • URIError – an error in encodeURI() has occurred

Custom Error

You can create a custom error by extending the Error class

class ValidationError extends Error {
    constructor(message) {
        super(message); // (1)
        this.name = "ValidationError"; // (2)
    }
}

function testValidationError() {
    throw new ValidationError("Whoops!");
}

try {
    testValidationError();
} catch(error) {
    console.log(error.name + ":" + error.message);
    console.log("error stack");
    console.log(error.stack);
}

 

Source code on Github

October 10, 2010