You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I received a surprise code challenge invitation from Google on July 26, 2020. After accepting the invitation, I was redirected to https://foobar.withgoogle.com where I completed my first challenge.
17
-
18
-
In this post I will share my experience solving the challenge.
12
+
In this post I will share my experience solving the first `Google FooBar Challenge`.
19
13
20
-
21
-
### The Problem: Caesar Cipher Decryption
22
-
Decrypt a code where every lowercase letter [a..z] is replaced with the corresponding one in [z..a], while every other character (including uppercase letters and punctuation) is left untouched. That is, 'a' becomes 'z', 'b' becomes 'y', 'c' becomes 'x', etc. For instance, the word "vmxibkgrlm", when decoded, would become "encryption".
23
-
24
-
There was some limitation to execution time and the external Java library usage environment provided was default Java Runtime Environment (JRE) 8.
14
+
While doing some search on Google, I received an invitation to participate in a code challenge by Google. I had no previous idea about it, frankly never heard of it. I accepted the invitation and I was redirected to [FooBar](https://foobar.withgoogle.com). After log in, a `CLI` with the instructions about the challenge and how to request a challenge was provided. The challenge had to be solved within 2 days.
25
15
16
+
### The Challenge
17
+
Decrypt a code where every lowercase letter [a..z] is replaced with the corresponding one in [z..a], while every other character (including uppercase letters and punctuation) is left untouched. That is, 'a' becomes 'z', 'b' becomes 'y', 'c' becomes 'x', etc. For instance, the word "vmxibkgrlm", when decoded, would become "encryption".
26
18
27
-
### What is Caesar Cipher?
28
-
A `Cipher` is a method for encrypting a message, intending to make it less readable. As for the `Caesar Cipher`, it's a substitution cipher that transforms a message by shifting its letters by a given offset.
29
-
19
+
__Constraints for the solution:__
20
+
- Java 8
21
+
- Limited execution time
22
+
- Prohibit usage of third-party libraries
23
+
- Parallel processing disabled
24
+
- Character limit to around 3000 (I don’t remember exactly)
30
25
31
26
### Initial Thoughts
32
-
After going through the problem and some analysis, the rough idea I could come up with as a part of the solution was manipulating the ASCII value of the letters. Addition and subtraction of numeric value of numbers should do the trick but at this point I did not think of `Caesar Cipher` at all. Implementing the initial idea to anything concrete was taking some time so I went with the simplest solution that I could work out.
27
+
The rough idea I could come up after the analysis was:
28
+
- Manipulation of the ASCII value of the letters
29
+
- Simple maths, addition/subtraction, on numeric value of letters
33
30
31
+
Since converting this idea into a concrete algorithm was taking longer than expected, I moved to another solution.
34
32
35
33
### First Attempt
36
-
To solve the problem I needed a data structure to keep a map of the encryption and easily access the decrypted value. `HashMap` was the best fit. The other part of the solution required a data structure to store the decrypted characters as a `String`. Although `Character Array` would have been the ideal way, `StringBuilder` with `Java 8``SteamAPI` was the quickest option that did the trick. Hence, I went with the implementation built based on these base data types. The rough solution did the job and ran successfully at my local but sadly it did not pass the challenge tests.
34
+
The next simplest design for the solution I could come up with consisted of the following data structures:
35
+
-`HashMap` to store the encrypted letters and easy access of decrypted letters
The implementation provided desired output in the local environment but it failed to pass the tests.
58
60
59
61
### Second Iteration
60
-
I reflected back on the limitations. I knew a cheaper data structure, `Character Array`, could have done the job instead of `StringBuilder` class. I thought that might be the reason that the solution failed to fulfill the criteria, so I refactored the code replacing StringBuilder with a simple Character Array. But this solution also failed to pass any of the tests.
61
-
62
-
At this point I was getting a little bit frustrated because the errors were not thrown back properly. I was not sure what failed. To be honest, I had lost interest after one hour of trials and gave up. I needed to prepare for interviews and I went back to my previous way, learning basics and solving challenges from different sources.
62
+
I reflected back on the constraints and refactored the code to use more primitive data structure:
But again the solution did not pass! At this point I was getting a little bit frustrated because there were no proper errors thrown. The output was just a list of failed tests. I lost interest after around an hour and I went back to my previous preparation method, solving challenges from other sources.
87
85
88
86
### Third Iteration
89
-
I wanted to solve the problem and came back to it again with less than 3 hours left to complete the other day.
87
+
The next day I went back to the challenge with around 3 hours remaining. To make sure the time spent here would be worthwhile, I did some search to know more about the challenge. Only then I realized that the challenge was invitation only, and was used by Google for recruitment. Those were good enough reasons for me to continue, but then I was seriously running out of time.
90
88
91
-
As I had never participated in `Google FooBar Challenge`, and even never heard of it, I wanted to know more as I did not want to waste more time if there would be no value in participating in the event, and I needed to continue my preparation. So after some search, I knew more about the challenge and that it was an invitation only and used by Google for recruitment. It added more motivation to solve the problem but then I was running out of time.
89
+
Then I searched for similar problems and solutions to find answers to these questions:
90
+
- How to encrypt a letter by another
91
+
- What are the standard encryption algorithms
92
92
93
-
I reflected back on the problem statement and the constraints again. As I knew that there would be other ASCII based optimum solutions which might satisfy the conditions, I did some more research on ways to encrypt letters with other letters and other standard encryption processes. It led to the `Cesar Cipher` which was the term that I was looking for. After digging more into it, I found a simple example by [Baeldung.com](https://www.baeldung.com/java-caesar-cipher)which laid the foundation to my initial ASCII based solution.
93
+
A simple example by [Baeldung](https://www.baeldung.com/java-caesar-cipher)answered my queries.
94
94
95
95
```java
96
96
StringBuilder result =newStringBuilder();
97
97
for (char character : message.toCharArray()) {
98
-
if (character !='') {
99
-
int originalAlphabetPosition = character -'a';
100
-
int newAlphabetPosition = (originalAlphabetPosition + offset) %26;
Baeldung's example `encrypts` letters. It did not `decrypt`. Letter `a` was used as the base for the encryption process. Understanding the encryption process was very important to successfully decrypt the cipher. So based on this framework I created an encryption system that generates the cipher which is our problem.
110
+
**“Any fool can know. The point is to understand.” - Albert Einstein**
Knowing that standard encryption algorithm used was `Caesar Cipher`, I wanted to understand more that led to [Cryptography](https://github.com/codeanit/til/issues/43), [Cipher](https://github.com/codeanit/til/issues/107) and [more](https://github.com/codeanit/til/issues).
116
113
117
-
for (char character : textToEncrypt.toCharArray()) {
114
+
Keeping in mind that the time was limited, I skimmed the contents.
118
115
119
-
if ( (int)character >=97&& (int)character <=122 ) {
120
-
int originalAlphabetPosition = character -'z';
121
-
int newAlphabetPosition = ( originalAlphabetPosition +25 ) %26;
122
-
result.append((char) ('z'- newAlphabetPosition));
116
+
`A **Cipher** is a method for encrypting a message, intending to make it less readable. **Caesar Cipher** is a substitution cipher that transforms a message by shifting its letters by a given offset.`
123
117
124
-
} else {
125
-
result.append(character);
126
-
}
127
-
}
118
+
Baeldung's post also made me realize that understanding of the encryption process was important to decipher. Therefore, based on Baeldung's framework, I created an encryption system that generated the cipher from the challenge.
for (char character : encryptedText.toCharArray()) {
140
-
141
-
if ( (int)character >=97&& (int)character <=122 ) {
142
-
int originalAlphabetPosition = character -'z';
143
-
int newAlphabetPosition = (originalAlphabetPosition +25 ) %26;
144
-
result.append((char) ('z'+ newAlphabetPosition));
145
-
146
-
} else {
147
-
result.append(character);
148
-
}
149
-
}
150
-
151
-
returnnewString(result);
140
+
StringBuilder result =newStringBuilder();
141
+
for (char character : encryptedText.toCharArray()) {
142
+
if ( (int)character >=97&& (int)character <=122 ) {
143
+
int originalAlphabetPosition = character -'z';
144
+
int newAlphabetPosition = (originalAlphabetPosition +25 ) %26;
145
+
result.append((char) ('z'+ newAlphabetPosition));
146
+
} else {
147
+
result.append(character);
148
+
}
149
+
}
150
+
returnnewString(result);
152
151
}
153
152
```
154
153
154
+
I submitted the solution then again it failed.
155
+
156
+
__Time <10mins!__
155
157
156
158
### Accepted Solution
157
-
The default example had implemented StringBuilder class which I thought was the reason for the failed tests. I replaced StringBuilder with Array implementation and the solution passed all the tests. Yay!
159
+
Refactored the code:
160
+
- Replaced `StringBuilder` with `Character Array`.
158
161
159
162
```java
160
163
publicstaticString solution(String x) {
161
-
int strLength = x.length();
162
-
char[] encryptedCharArr =newchar[strLength];
163
-
164
-
for (int i =0; i < strLength; i++) {
165
-
int character = x.charAt(i);
166
-
167
-
if ( character >=97&& character <=122 ) {
168
-
int originalAlphabetPosition = character -'z';
169
-
int newAlphabetPosition = (originalAlphabetPosition +25 ) %26;
After submitting the solution I reviewed the solution and the recalled overall process. Being a firm believer of `Test Driven Development (TDD)`, I wanted safety to keep the behaviours of the solution the same, I wrote simple `Unit Tests`. The unit tests did not need to be extensive covering all edge cases; neither should have many use cases covered as it had already passed the test cases of Google. I just needed something to preserve what was functional in my local.
184
-
185
-
```java
186
-
classCaesarCipherTest {
187
-
188
-
String result ="wrw blf hvv ozhg mrtsg'h vkrhlwv?";
189
-
String expected ="did you see last night's episode?";
190
-
191
-
@Test
192
-
voidsolution() {
193
-
String actual =CaesarCipher.solution(result);
194
-
Assertions.assertEquals(expected, actual);
195
-
}
196
-
197
-
@Test
198
-
voidsubmittedSolution() {
199
-
String actual =CaesarCipher.submittedSolution(result);
`Google FooBar Code Challenge` was fun. Sometimes `the unknown` leads to better results as if there had been clear test case failure outputs, It would not have pushed myself to think and rethink more. On the other hand, I would have found the solution straight forward but problems in real life are also abstract. The constraints and the test cases pushed me to use optimum data structures and algorithms.
185
+
The next day I reviewed the solution and recalled the overall process. Phew! It was a close call.
252
186
253
-
Previously, I had an interview with Google in July 2019. It was more of a casual talk I had with a nice lady who wanted to know a bit of me and to see if I fit the available role at a certain location. Unfortunately, it did not work out.
187
+
I wanted to refactor the submitted code as it was done in a hurry. And prior to refactoring, I wrote `Unit Tests` to make sure that all the methods will work as before. Those tests did not need to be extensive covering all edge cases; neither should have many use cases, the solution had already passed Google's test cases.
254
188
255
-
I am grateful to both opportunities but I am enjoying this experience more that may be because I'm more of a `code person`.
189
+
Previously, I had an interview with Google in July 2019. It was more of a casual talk I had with a nice lady to see if I fit the available role at a certain location. Unfortunately, it did not work out.
256
190
257
-
Thank you Google!
191
+
I am grateful for both opportunities but I have enjoyed this experience more may be because I'm more of a code person.
258
192
193
+
__Thank you Google!__
259
194
260
195
If code is a better language to you then please find more at [Github](https://github.com/JavaCheatsheet/codechallenge).
0 commit comments