BRUTE FORCE
By: Dan Romans
Tags: JavaScript, Process, Problem Solving, Technical Interview, Code Challenge

First thing’s first: read the requirements. Then, read them again. Say them aloud. Take a moment to digest the instructions and understand what is being asked of you. *Note: I’m going to use JavaScript to express the solution.

Write a program that outputs the largest unique set of characters that can be removed from this paragraph without letting its length drop below 50. For example: [‘H’, ‘i’, ‘!’, ‘ ’]

Upon initial assessment, it can be determined that:

A program needs to be written, which can be a JavaScript function.

function. The function needs to produce an output, so console.log() could be used.

could be used. The output should be an array of unique characters, without repetitions. The given example also implies the inclusion of mixed case, special characters, punctuation marks, and spaces.

of unique characters, without repetitions. The given example also implies the inclusion of mixed case, special characters, punctuation marks, and spaces. The input to be worked with, which will be the single argument given to the function, is “this paragraph”—the paragraph containing the instructions for the challenge. It is implied that the data type is string .

. The output should include the maximum amount of characters that can be removed from the input without letting its length become less than 50 . (It is implied that length means character count.)

If working on this challenge in person, at a technical interview, these bullet points are great points of discussion and clarification to start with. It is very important, perhaps more important, to demonstrate process before solution. Does “output” actually mean output to the terminal, or return value? Are all characters indeed applicable? Is the input in fact the whole paragraph? Et cetera.

A great next step is to establish certainties and write some pseudo code.

let input = 'I recently encountered a job application that presented a code challenge. I tackled the challenge so that I could submit my work with the application. The challenge was this: Write a program that outputs the largest unique set of characters that can be removed from this paragraph without letting its length drop below 50.' function removeUniqueSet(string) { // define function and argument

let output = [] // define output



programmatically remove characters from string... loop?

and add them to output array... .push()? // employ a conditional for input validation

if (string.length < 50) {

console.log('Input phrase has less than 50 characters.')

return // terminate execution, i.e. end function

} console.log(output)

} removeUniqueSet(input)

// [???]

HOLD THE PHONE. Let’s pause for a moment and talk about brain farts. When I decided to complete this challenge, I was by myself in the comfort of my home, but the words “here’s a little challenge” and the association with an application for a career position still made me nervous! As if the xenomorph was going to creep up behind me, somehow uncharacteristically speak, and make the last words my ears ever heard: “You’ll never get this job”.

Testing is difficult. It’s a different beast than day-to-day work. It also may conceal a person’s full potential. It’s entirely natural and common to be nervous in a testing situation. Do your best to be calm and collected. Focus on what you know, and how you work on your own time. Everything is a learning experience and provides opportunity for growth. With time and experience comes more confidence… and also greater challenges. There will always be something you don’t know, so just be yourself and enjoy the process. Be present. Take pleasure in the act of doing. Now, about that brain fart…

Due to nerves, you very well may have a moment of confusion or forgetfulness during a code challenge. Just take a breath and rework your thought process. Here’s an example: When I first analyzed this challenge, I thought: “Okay. How to start?”. I inspected the length of the paragraph to be inputted.

let input = 'I recently encountered a job application that presented a code challenge. I tackled the challenge so that I could submit my work with the application. The challenge was this: Write a program that outputs the largest unique set of characters that can be removed from this paragraph without letting its length drop below 50.' console.log(input.length)

// 322

I figured there’s only 26 letters in the alphabet and 10 digits on the keyboard. There’s not that many special characters (right?), and in this particular paragraph maybe 2 . Even if I removed a high estimate of 100 characters from the input, that would leave a remaining 222 . Was the deliverable even sensible? I could just build a unique set of every character and still be far from the 50 character remainder limit. Am I mistaken?

I was defensively focused on the validity of the challenge and failed to realize that the number of characters in the paragraph was not synonymous with the number of unique characters in the paragraph. There are many repeated characters in a paragraph! Moreover, the goal was to build the functionality required, not debate the input. So, having clarified the goal and refreshed my perspective, I got to work.

Let’s get back to the challenge.

First, we can consider that the function needs to handle an input with a length less than the remaining character minimum of 50 . So, let’s rearrange the code to hit this conditional first:

function removeUniqueSet(string) {

let output = [] if (string.length < 50) {

console.log('Input phrase has less than 50 characters.')

return

} programmatically remove characters from string... loop?

and add them to output array... .push()? console.log(output)

}

Next, let’s approach programmatically removing characters from the input. Since the function should remove elements so long as the input length does not fall below 50 we can use a while loop . This also allows the function to receive an input of unknown length. We can set a condition for the while loop that interrupts the loop when the length of the input string reaches 50 . However, we should consider creating a copy of the input string to act as a countdown value so we can operate on the initial input without inadvertently mutating it in the process. Each time the loop runs, we want to remove the character that was just evaluated—in this case: the first character.

function removeUniqueSet(string) {

let output = []

let limit = string // copy of the input string if (string.length < 50) {

console.log('Input phrase has less than 50 characters.')

return

} while (limit.length > 50) {

// *thinking ahead: add characters to output array... .push()?

limit = limit.slice(1) // reassigning value

} console.log(output)

}

Now there’s a copy of the input assigned to a variable called limit . It is used to set the condition of the while loop by keeping track of the length of limit and, at each iteration, reassigned to limit is limit minus its first character. That is achieved by using the .slice() method given an argument of 1 , the index number of the second character. Essentially it says: “transform limit into limit starting from the second character”.

At this point, we have a function that takes in a string, returns an error message if that string is less than 50 characters, or continues to pair down the copy of the input, one character at a time, until the input copy length decrements to 50 . What’s left to do is address the output. We have the output array declared at the top of the function, and have it logged to the terminal at the bottom of the function. Now we just need to build the output.

The while loop provides an opportunity to evaluate each character of the input while the condition is being met. So, at each iteration, we want to add the current character to the output array, but only if it is not already within the output array. Recall that the output result must include only unique characters, no repetitions. This can be achieved by including an if statement within the while loop with a condition that checks whether or not the output array includes a certain character. If the character being evaluated is not already included in the output array, it gets added.

function removeUniqueSet(string) {

let output = []

let limit = string if (string.length < 50) {

console.log('Input phrase has less than 50 characters.')

return

} while (limit.length > 50) {

if (!output.includes(?char?)) { // if output does not include

output.push(?char?) // add char to output

}

limit = limit.slice(1)

} console.log(output)

}

Now there’s an if statement to check if a character is in the output array. This is achieved by using a bang operator ( ! ) to reverse the logic of calling the .includes() method on the output array given an argument of a particular character. Basically saying: “if the output array does not include this character, then…” add it to the output array with the .push() method.

The last step to reaching functionality has to do with which specific characters are being evaluated. Well, we should be evaluating the input. And it makes sense to do so programmatically, from first to last, one at a time. Thankfully, we already have a loop set up. We can use it to evaluate each character of the input string by index. So, the arguments within the if statement would be the input ( string ) paired with bracket notation ( [] ) to call particular characters by index. And, since we want to go through each character of the input string, we can declare a counter variable ( i ) set to 0 in the outermost scope of the function and increment ( ++ ) the counter variable at the bottom of the while loop scope.

function removeUniqueSet(string) {

let output = []

let limit = string

let i = 0 // declare and assign counter variable if (string.length < 50) {

console.log('Input phrase has less than 50 characters.')

return

} while (limit.length > 50) {

if (!output.includes(string[i])) {

output.push(string[i]) //access character from string by index

}

limit = limit.slice(1)

i++ // increment the value of i by 1

} console.log(output)

}

We have a logical first draft of the program required by the challenge. You should verify output throughout the building process. For this article, I’ll “run” the the program and verify the output now. For extra validation, I’ll add an additional output that confirms the input count did not fall below 50 .