Solving Globant’s 20 Years’ Puzzles!

All solutions to the anniversary challenge riddles

Federico Kereki
Globant
Published in
8 min readSep 11, 2023

--

Globant just became 20 years old and created a Riddles Challenge for all Globers, with exciting prizes for winners!

The contest is now over, so let’s see the riddles and their solutions.

First Riddle

The first problem required finding arithmetic expressions to produce some specific results.

Only using the ordered digits of the current year (2023, i.e., 2, 0, 2, and 3) and simple arithmetic operators (+, -, *, /, parenthesis, power, square root, floor(), ceiling() and factorial) write equations that give numbers from 11 to 19.

How can we go about this? There are many solutions, so I’ll just show my own. I’m adding extra parentheses to clarify calculations, but they aren’t needed according to PEMDAS! I used all allowed operations and provided two alternatives for each number just for variety, but there are many more possible solutions.

  • 11 = ⌊√202⌋ – 3
    11 = 20/2 + ⌊√3⌋
  • 12 = (2 + 0) × 2 × 3
    12 = (2 × 0)! × 2! × 3!
  • 13 = (20 / 2) + 3
    13 = 2 – 0! + (2 × 3!)
  • 14 = 20 – (2 × 3)
    14 = 2 + 0 + (2 × 3!)
  • 15 = (2 + 0! + 2) × 3
    15 = 20 – 2 – 3
  • 16 = (20 / 2) + 3!
    16 = 20 – 2 – ⌊√(3!)⌋
  • 17 = ⌊√202⌋ + 3
    17 = 20 – (⌊√2⌋ × 3)
  • 18 = (2 + 0!) × 2 × 3
    18 = 20 – ⌊√(2×3)⌋
  • 19 = 20 – ⌈2/3⌉
    19 = 20 + 2 – 3

You can get more results, such as 20 = 20 + ⌊2/3⌋, 21 = 20 + ⌈2/3⌉, 22 = 20 + ⌊2³⌋, etc.; how high can you go? Also, find expressions for numbers 0 to 10.

Second Riddle

The second question asked to find a number — and it wasn’t a short one!

What is the smallest natural number where the result of moving the digit on the far right to the front of the number is a number 9 times greater?

There are three ways of solving this puzzle; let’s go over them.

First way

Say the solution is written as abc…xyz. What can the first digit be? If it is 2 or greater, when multiplied by 9, the result will have one more digit; the only possibility is a=1 and then z=9. We can find the digits one by one by multiplying:

  • Start with 1bc…wxy9, with a=1 and z=9.
  • 1bc…wxy9 × 9 ends in 1, so y=1.
  • 1bc…wx19 × 9 ends in 71, so x=7.
  • 1bc…w719 × 9 ends in 471, so w=4, etc.

Keep this up, and you’ll eventually get the solution: a 44-digit number, 10112359550561797752808988764044943820224719.

Second way

A second way is trickier but directly leads to the solution. Let’s write an repeating fractional number N=0.abc…xyzabc…xyzabc…xyz…. We then know that 9×N=0.zabc…xyzabc…xyzabc…xy…, and therefore 90×N=z.abc…xyzabc…xyzabc…xyz…. Subtracting, 90×N-N= 89×N= z, so N=z/89. Since N must be greater than 0.1 (because a isn’t zero), we need z=9. Using an infinite precision calculator (or working by hand!) we find N=0.10112359550561797752808988764044943820224719…, the same result as before.

Third way

The third solution is the most obvious one! You could google for the answer, but finding the right prompt isn’t that easy. One prompt that works is “riddle: a number is multiplied by 9 when you move the last digit to the front”, and the first search result provides the solution.

Third Riddle

The third puzzle involved an image at https://statics.globant.com/more/RELEASE-globant-20years-v1.0.6/statics/image-riddle.svg and cryptically said, “There’s a hyperlink hidden somehow, somewhere, in the picture. Follow the clues, and you’ll get the answer to this riddle!

The image is nice… but it’s not what you need to look at!

The key wasn’t in the image but in the page’s HTML source code! In it, you find:

<!-- This is not a comment: 
(() => {
if(location.origin === 'https://statics.globant.com/more/RELEASE-globant-20years-v1.0.6/statics/'){
location.href = '20.html';
}
})();
-->

If you change the URL to https://statics.globant.com/more/RELEASE-globant-20years-v1.0.6/statics/20.html, you get a seemingly wrong 404 page… but it’s really not, as it acknowledges in really tiny lettering!

“This is not a 404”, it says

If you check the source code for this page, you find the following code, and note that the else part is unreachable:

function validate() {
if (true) {
alert("Invalid code ;) : " + document.getElementById("fcode").value);
} else {
location.href = "2ccdda74-1346-49cf-8a33-7813b6207b4d.html";
}
}

Change the URL to https://statics.globant.com/more/RELEASE-globant-20years-v1.0.6/statics/2ccdda74-1346-49cf-8a33-7813b6207b4d.html, and you get a final form:

The final form requires you to write something… but what?

What to type in to get the final answer? There’s a weird Xsjuf!zpvs!f.nbjm text that could provide a hint, but what does it mean? The source code for this page includes an encryption function:

function encrypt() {
var input = document.getElementById("inputText").value;
var encrypted = "";

for (var i = 0; i < input.length; i++) {
var charCode = input.charCodeAt(i);
encrypted += String.fromCharCode(charCode + 1);
}

document.getElementById("encryptedText").value = encrypted;
}

It seems that text is encrypted with a Caesar’s Cipher that changes each character to the next one. If we decrypt Xsjuf!zpvs!f.nbjm with that, it turns into Write your e-mail, so that’s the final step: enter your e-mail address in the text box, click Encrypt, and you’ll get the solution!

Fourth Riddle

The last question was more involved but essentially required you to encode two dates plus a check bit in a 32-bit packet.

The Marketing Department of the duty-free shop of an airport wants to obtain statistics about its clients. For this purpose, there is a small device at the entrance that scans the passport and obtains the date of issue of the passport and the owner’s date of birth. Each date consists of the day, month, and year, and the range of years that the system manages goes from 1900 to 2023. This information is sent through a channel with a very small bandwidth (32 bits per packet). In turn, there is a very small probability of error in the transfer (much less than 1/32) that should be detected when receiving a package if there was an error in the delivery through a parity check (its redundancy must be included in the packet)

The problem is, how do you encode two dates in just 31 bits? We could think of using separate fields:

  • A day is 1..31, so 5 bits
  • A month is 1..12, so 4 bits
  • A year is 0 (1900) to 123 (2023) so 7 bits
  • All in all, 16 bits for each date — no space for the check bit!

Maybe we can do better by numbering the days in a year, from 0 to 365? (Yes, we may have a 366-day long year.)

  • A day is 0..365, so 9 bits
  • A year is 0 to 123, so 7 bits
  • Again, 16 bits!

What about numbering the days in the whole period? 124 years are 45,291 days, and we need 16 bits for that… wrong again? We have a last trick: we’ll encode both dates together, as a single number. For two dates we have 45,291² (=2,051,274,6281) possible pairs, and that number requires 31 bits; success!

(Actually, we have fewer possibilities, because the passport date must be greater than the birth date, but that won't make a difference for the general solution. Including that would halve the number of pairs and leave an extra free bit, so we would require 30 bits for the dates and have space for two check bits instead of just one!)

The problem required implementing a JavaScript or Python solution; we’ll leave that up to you. The needed steps are:

  1. Write a function that will turn a date from 1900 to 2023 into the number of days since January 1st, 1900.
  2. Use that function to turn the birth date into a number between 0 and 45,290; call it B.
  3. Apply that function to the passport date, and generate another number between 0 and 45,290; call it P.
  4. Calculate N=45,291 × B + P; it will be a number that requires 31 bits.
  5. To generate the number to be sent, add a 32nd bit so the count of all 1 bits is even.

When the receiver gets the packet with the N value, it will check if the count of 1 bits is even; if not, it will know there was a transmission problem. After that, it can do arithmetic to split N into B and P, and some final work to turn B and P into full dates; done!

Conclusion

The contest was a success, with many Globers pitching in and providing solutions to the puzzles — and Globant is now on its way to the next 20 years!

Appendix-JavaScript code for the 4th riddle

const DAY_ZERO = new Date(Date.UTC(1900, 0, 1, 0, 0, 0)).getTime();

const MS_PER_DAY = 24 * 60 * 60 * 1000;

const deltaSince1900 = (yyyy, mm, dd) =>
Math.floor((new Date(yyyy, mm - 1, dd, 0, 0, 0).getTime() - DAY_ZERO) / MS_PER_DAY);

const DAYS_YEARS = deltaSince1900(2024, 1, 1) + 1;

const deltaToYMD = (delta) => {
const dateN = new Date(DAY_ZERO + delta * MS_PER_DAY);
return [dateN.getUTCFullYear(), dateN.getUTCMonth() + 1, dateN.getUTCDate()];
};

const countBits = (num32) => {
let bits;
for (bits = 0; num32; num32 >>= 1) {
bits += num32 & 1;
}
return bits;
};

function globantEncoder(yB, mB, dB, yP, mP, dP) {
const dateB = deltaSince1900(yB, mB, dB);
const dateP = deltaSince1900(yP, mP, dP);
const combined = dateB * DAYS_YEARS + dateP;
const parity = countBits(combined) & 1;
return (combined * 2 + parity) | 0;
}

function globantDecoder(encoded) {
if (encoded < 0) encoded += 2 << 32;
const parity = encoded & 1;
const combined = (encoded - parity) / 2;
const dateB = Math.floor(combined / DAYS_YEARS);
const dateP = combined % DAYS_YEARS;
return [...deltaToYMD(dateB), ...deltaToYMD(dateP), parity === (countBits(combined) & 1)];
}

const xxx = globantEncoder(1960, 9, 22, 2023, 8, 31);
console.log('ENCODED', xxx);
console.log('DECODED', JSON.stringify(globantDecoder(xxx))); // should succeed
console.log('DECODED', JSON.stringify(globantDecoder(xxx ^ 128))); // changed combined dates; should fail
console.log('DECODED', JSON.stringify(globantDecoder(xxx ^ 1))); // kept combined dates, changed parity; should fail

// Expected output:
// ENCODED 2009108513
// DECODED [1960,9,22,2023,8,31,true]
// DECODED [1960,9,22,2023,11,3,false]
// DECODED [1960,9,22,2023,8,31,false]

--

--

Federico Kereki
Globant

Computer Systems Engineer, MSc in Education, Subject Matter Expert at Globant