Search Content

One More Time - Efficiency Winner

Rafał Wolsztyniak

Published on 04/07/2021

Efficiency

Here's my submitted code with the total length of 693 characters:

<script runat="server">w="Celebration Celebrate celebrate Music's dancing feeling tonight right, Don't Need, We're can't dance don't gonna right we're yeah, Come Hey! Just Mmm, free just know late more need stop time wait yeah I'm One You all and got on, the too you Oh We do it me no so".split(' ');s="⣰⣰♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢯♫⣰♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢯♫⢘⢬⢷⢔♫⣰♫⢥⢹⢨⢰⢧⢕♫⢐⢖♫⢑♫⢘⢮⢸⢩♫⢥⢿♫⢻⢝⢬♫⢲⢛⢬♫⢚⢞⢒♫⣰⣰⣰⢐♫⢲⢨⢠⢞⢼⢽⢗⢖♫⢣⢤⢕♫⢓⢵⢾⢕⢷⢫♫⢙⢯♫⢢⢶⢳⢟♫⢚⢞⢒♫⣰⢑⢴⢜⣀⢦♫⢓⢵⢾⢕⣀⢦♫⢑⢴⢜⣀⢦⣷⣷⣷⣷⣷♫⣷⣷⣷⣷♫⣰⢓⢵⢾⢕⣀⢦♫⢚⢞⢒⣷⣷♫⣷⣷⣷⣷".replace(/⣷/g,'♫⣰⢓⢵⢾⢕⣀⢦♫⢚⢞⢒♫⢑⢴⢜⣀⢦').replace(/⣰/g,'⢱⢪⢭♫');for(c=0;c<s.length;c++){i=s.charCodeAt(c)-10384;if(i>=0){t=w[i]+' '}if(s[c]=='♫'){t='<br>'}Platform.Response.Write(t)}</script>

If you want to implement it, just paste it on a CloudPage:

  • either within the <body> tag of the page
  • or remove anything and allow the above code to be the only thing placed on the page

The code is not perfect and I realized a few things that I could have done differently to make the script shorter by a few characters (which I'll mention down below).

How does this work?

First let's present the code as it would be written if we didn't have the character count constraint on us:

<script runat="server">
var words = "Celebration Celebrate celebrate Music's dancing feeling tonight right, Don't Need, We're can't dance don't gonna right we're yeah, Come Hey! Just Mmm, free just know late more need stop time wait yeah I'm One You all and got on, the too you Oh We do it me no so".split(' ');
var structure = "⣰⣰♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢯♫⣰♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢯♫⢘⢬⢷⢔♫⣰♫⢥⢹⢨⢰⢧⢕♫⢐⢖♫⢑♫⢘⢮⢸⢩♫⢥⢿♫⢻⢝⢬♫⢲⢛⢬♫⢚⢞⢒♫⣰⣰⣰⢐♫⢲⢨⢠⢞⢼⢽⢗⢖♫⢣⢤⢕♫⢓⢵⢾⢕⢷⢫♫⢙⢯♫⢢⢶⢳⢟♫⢚⢞⢒♫⣰⢑⢴⢜⣀⢦♫⢓⢵⢾⢕⣀⢦♫⢑⢴⢜⣀⢦⣷⣷⣷⣷⣷♫⣷⣷⣷⣷♫⣰⢓⢵⢾⢕⣀⢦♫⢚⢞⢒⣷⣷♫⣷⣷⣷⣷".replace(/⣷/g,'♫⣰⢓⢵⢾⢕⣀⢦♫⢚⢞⢒♫⢑⢴⢜⣀⢦').replace(/⣰/g,'⢱⢪⢭♫');
 
for(c = 0; c < structure.length; c++){
    var index = structure.charCodeAt(c) - 10384;
    if(index >= 0){
        var text = words[index] + ' '
        }
    if(structure[c] == '♫'){
        var text='<br>'
        }
    Platform.Response.Write(text)
    }
</script>

You can see here that the scripts consists of 3 parts:

  • the words variable (w in the minified version) telling us what words should be in the lyrics
  • the structure variable (s) which tells us when words should appear in the song
  • and the for loop that is combining the two variables to output the lyrics on the CloudPage

Words: a short-lived string

This variable contains all words found in the lyrics of the Daft Punk hit sorted in such manner that words with the longest character count.

In the submitted code we see this variable starting as a string, but it's immediately turned into an array using the String.split() method - essentially each space in the string serves as a breaking point marking where one array element ends and another one starts. This is done in the name of saving the character count as this way the word array has the length of 276 characters

w="Celebration Celebrate celebrate Music's dancing feeling tonight right, Don't Need, We're can't dance don't gonna right we're yeah, Come Hey! Just Mmm, free just know late more need stop time wait yeah I'm One You all and got on, the too you Oh We do it me no so".split(' ')

while the most compact way of writing the same set of words as an array would take 363 characters which is longer by 87 characters:

w=["Celebration","Celebrate","celebrate","Music's","dancing","feeling","tonight","right,","Don't","Need,","We're","can't","dance","don't","gonna","right","we're","yeah,","Come","Hey!","Just","Mmm,","free","just","know","late","more","need","stop","time","wait","yeah","I'm","One","You","all","and","got","on,","the","too","you","Oh","We","do","it","me","no","so"]

Wait, what's an array?

Arrays are objects in JavaScript that work like lists - they can contain multiple elements and each one of them can be accessed by calling their index (their location). To demonstrate this, let's take a fragment of the "words" array (which while being grammatically incorrect, represents my dancing skills quite accurately):

var words = ["We’re", "can't", "dance"];
// Index:       0        1        2

Indexes are zero-indexed which is to say that:

  • the index representing the very first element of an array is always a 0,
  • the second one element is accessed by 1, the third one by 2, etc.

We get values stored in arrays by using the name of the array and placing the location of the desired element in square brackets like so:

// Get values of individual array elements:
var firstElement  = words[0];   // Result: "We're"
var secondElement = words[1];   // Result: "Can't"
var thirdElement  = words[2];   // Result: "Dance"

What's up with all the dots?

We know the words now, but don't know when to sing them, so we need to break down the song structure.

The song has:

  • 434 words with the titular lyrics appearing 30 times

  • 117 lines in total (which means we need 116 line breaks

  • a chorus that's repeated 15 times:

      One more time
      Music's got me feeling so free
      We're gonna celebrate
      Celebrate and dance so free
    

which I managed to get represented in the script with a total of 266 characters.

s="⣰⣰♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢯♫⣰♫⣰⢚⢞⢒♫⢺⢡⢳⢟♫⢘⢬⢷⢔♫⣰⢚⢞⢒♫⢺⢯♫⢘⢬⢷⢔♫⣰♫⢥⢹⢨⢰⢧⢕♫⢐⢖♫⢑♫⢘⢮⢸⢩♫⢥⢿♫⢻⢝⢬♫⢲⢛⢬♫⢚⢞⢒♫⣰⣰⣰⢐♫⢲⢨⢠⢞⢼⢽⢗⢖♫⢣⢤⢕♫⢓⢵⢾⢕⢷⢫♫⢙⢯♫⢢⢶⢳⢟♫⢚⢞⢒♫⣰⢑⢴⢜⣀⢦♫⢓⢵⢾⢕⣀⢦♫⢑⢴⢜⣀⢦⣷⣷⣷⣷⣷♫⣷⣷⣷⣷♫⣰⢓⢵⢾⢕⣀⢦♫⢚⢞⢒⣷⣷♫⣷⣷⣷⣷".replace(/⣷/g,'♫⣰⢓⢵⢾⢕⣀⢦♫⢚⢞⢒♫⢑⢴⢜⣀⢦').replace(/⣰/g,'⢱⢪⢭♫');

You can see the structure is being stored in a string again and that's again done again to save the code length.

The String.split() method is not used here, because we can treat strings as arrays of characters. This allows us to access each of them with the syntax for accessing array elements, for example if we would want to get the second letter of the word "One" we would call the index [1] and this would give us the letter n. Just as with arrays, we can utilize loops to execute the same code on each element of our object or, as in our case, each character.

The Dots

There's a lot of to unpack here, so let's start small with just one character:

This is known as the Braille pattern dots-1568 and I'll admit I have chosen to use Braille because it simply looked cool in the script. This is the only place where I intentionally ignored the impact on the word count and probably increased the script size by a few characters, but with such a classic song, you need to have your style game on point.

If we use the string method String.charCodeAt() on this character we can learn that this Unicode-encoded character has a decimal value of 10417. You know now that the words are stored in an array and that we can access individual elements of them with a number, so you probably know where this is headed - is used to get the word "One". If we subtract 10384 from the decimal encoding value, we land at a value of 33 - this is the index of the word "One" in our word array.

CharacterCharCodeIndexwords[index]
1041733One
1041026more
1041329time

The Notes and Replacements

The song structure string contains characters which simply indicate line breaks in the code. The replace methods are used to compress the song structure by expressing parts that are often repeated by a single character in the original string:

CharacterCompressed stringResulting outputNumber of occurrences
⢱⢪⢭♫One more time <br>30
♫⣰⢓⢵⢾⢕⣀⢦♫⢚⢞⢒♫⢑⢴⢜⣀⢦<br>One more time <br>Music's got me feeling so free <br>We're gonna celebrate <br>Celebrate and dance so free15

The allows us to reduce the size needed to represent the structure from 555 to 266 and while I was writing this article I realized I totally missed an opportunity to compress the first chorus:

One more time
We're gonna celebrate
Oh yeah, all right
Don't stop the dancin

The Process

It's short, but it could be even shorter:

  • the two conditional if statements could be optimized to become just one if... else statement
  • and the index variable didn't really need to be declared

which would reduce the code length by 8 characters, but let's ignore that and explain how it works in the submitted shape:

for(c = 0; c < structure.length; c++){              //1
    var index = structure.charCodeAt(c) - 10384;    //
    if(index >= 0){
        var text = words[index] + ' '
        }
    if(structure[c] == '♫'){
        var text='<br>'
        }
    Platform.Response.Write(text)
    }

Here's how the submitted process works:

  • the for loop reads the characters of the structure string one by one
  • it calculates the index for the character as described previously
  • if the calculated value is above 0 (is not the line break character), temporarily assigns corresponding word and a space to the text variable (this way we can omit putting spaces into the structure string and have them added automatically)
  • if the code encounters the beamed eight-note (), the the <br> tag is assigned to the text variable
  • when both checks are done, the code writes the current text value to the body of the CloudPage

Platform vs Core library

Marketing Cloud developers have two libraries that they can choose, but in this case selecting the winner was quite simple when the function responsible for writing the output of the code to the page is used only once - it's was better to just use the default Platform.Response.Write() function which itself is rather long, but still shorter by 8 characters than the total length of the Write() function and the required process of loading the Core library:

Platform.Response.Write(t) // 26 characters
Platform.Load("core","1");Write(t) // 34 characters

Summary

It was a fun challenge and I feel I got lucky with it winning despite many missed opportunities for further optimization. Let's just hope that in the future we'll get a chance to compete in a challenge like this ⢱⢪⢭.

 

TL;DR for advanced developers:

I'm using decimal charcodes of Unicode characters to pull respective words from an array of words.

Recent Articles

Search Content
All Rights Reserved
Made with by your fellow SFMC users.