CoDEVIANT #7 (3/27/19)

Problem 1: Help the bookseller!

If this little bastard only knew how much time this took me, I’d be helping that bookseller to several servings of knuckle sandwich for a day or two straight.

Instructions:

A bookseller has lots of books classified in 26 categories labeled A, B, … Z. Each book has a code c of 3, 4, 5 or more capitals letters. The 1st letter of a code is the capital letter of the book category. In the bookseller’s stocklist each code c is followed by a space and by a positive integer n (int n >= 0) which indicates the quantity of books of this code in stock.

For example an extract of one of the stocklists could be:

L = {“ABART 20”, “CDXEF 50”, “BKWRK 25”, “BTSQZ 89”, “DRTYM 60”}.

or

L = [“ABART 20”, “CDXEF 50”, “BKWRK 25”, “BTSQZ 89”, “DRTYM 60”]

or

You will be given a stocklist (e.g. : L) and a list of categories in capital letters e.g :

M = {“A”, “B”, “C”, “W”}

or

M = [“A”, “B”, “C”, “W”] or …

and your task is to find all the books of L with codes belonging to each category of M and to sum their quantity according to each category.

For the lists L and M of example you have to return the string (in Haskell/Clojure a list of pairs):

(A : 20) — (B : 114) — (C : 50) — (W : 0)

where A, B, C, W are the categories, 20 is the sum of the unique book of category A, 114 the sum corresponding to “BKWRK” and “BTSQZ”, 50 corresponding to “CDXEF” and 0 to category ‘W’ since there are no code beginning with W.

If L or M are empty return string is “” (Clojure should return an empty array instead).

Note:

In the result codes and their values are in the same order as in M.

What we start out with

function stockList(listOfArt, listOfCat){// …}

How Adrian Solved It!

This was a doozy of a problem for me. It really kicked my ass, but I had some fun with it too.

So the deal is we get a list of categories that outline the types of books we want to report on.

  • So we’re going to make a variable called answer that we will eventually return.
  • It will be an empty string
let answer = ‘’;

Well the next easiest thing, to me at least, was to

  • Make an object that would hold the capitalized first letter of the category as keys.
let object = {};
  • Then do some magic to get the vaules of the listOfCat array to become keys for the object we just made
  • We create a for loop where we iterate over the listOfCat array’s length and create object key/value pairs with the key being set with object[listOfCat[i]] (where i represents the index of the array element we are on) and the value being hardcoded at zero.
for (var i=0; i < listOfCat.length; i++) {object[listOfCat[i]] = 0;};
  • If we were to console.log our object variable right now and we had started with a listOfCat argument of [“A”, “B”, “Z”], we would have the following
console.log(object); // returns{“A”: 0,“B”: 0,“Z”: 0}
  • Next we use a for-loop inside of another for-loop, pretty grainy, I know so that we can assign the number values we need that pertain to the amount of books we have for each category
  • We iterate over the length of the listOfArt argument’s length until our special counter x is less than-or-equal-to listOfArt’s length — 1. Each time we finish a pass of the code block we increase x by 1.
  • Inside that for-loop, we iterate over the length of our object variable being turned into an array (at run time, not in any permanent way) minus 1, and each time we complete the code block we increment this for-loop’s special counter, k, by 1
  • If the first character of the whatever value x indicates the index of for listOfArt is equal to the particular key of object that we are focusing on at that moment inside the inner for loop…

(if yes)

  • then we create a variable called letter and in that moment it will equal the key of object
  • we also create a variable called value that seeks an integer, via parseInt being used on the creating of an array out of the value of whatever index x stands for in listOfArt, with the temporary array being separated by the space that is between the long letter code and the number of books that we want.
  • we refer to that number of books with the [1] index value
  • Then we say that the value for the object key that is equal to letter is equal to the variable we created and gave a value to called value
for(let x=0; x<=listOfArt.length — 1; x++){   for(let k = 0; k < Object.keys(object).length; k++){      if(listOfArt[x][0] == Object.keys(object)[k]){      let letter = Object.keys(object)[k];      let value = parseInt(listOfArt[x].split(‘ ‘)[1]);      object[letter] += value;      }   }}
You don’t hate me, I hate me. #alwaysmad

At this point, besides losing all faith in humanity or yourself (both are acceptable). If you were to console.log our object, you’d get something like this:

//assume thatlistOfArt = [“ABAR 200”, “CDXE 500”, “BKWR 250”, “BTSQ 890”, “DRTY 600”]listOfCat = [“A”, “B”]console.log(object) //{A: 200,B: 1140}

So we’re almost there!

But we have to return our answer as a string in a weird way:

(CategoryLetter : Number)*space*-*space*

UNLESS it’s the last one in which case you’ll want to return

(CategoryLetter : Number)

Which will result in answers that should look like this:

‘(A : 0) — (B : 1290) — (C : 515) — (D : 600)’

So creep with me as we continue down. Remember how we created a variable called answer ? That will begin to come into play now.

We use a for-loop again over a temporary conversion of our object so that we can reference the keys and the values in the appropriate sentence format we have to return.

We use a special counter z and if z in a current looping in our for-loop is not the last one, we use Template Literals to :

  • place the name in our string: the first value of the temporary array element being made by our use of the Object-method .entries( ) *which takes our object variable as an argument*
  • place the regular text parts in our string
  • place the the value that is currently the second value in our temporary array made by the aforementioned means

to get answer to equal whatever it has been assigned through the constant looping plus whatever iteration it is of this process like so:

answer += `(${Object.entries(object)[z][0]} : ${Object.entries(object)[z][1]}) — `;

and if it is the last one, we make answer equal everything else it has been up to this point through this process but with the final entry lacking the spaces and the hyphen

answer += `(${Object.entries(object)[z][0]} : ${Object.entries(object)[z][1]})`

Then you can return answer.

Unless of course it is expected, and apparently it was when I did it, that if the listOfArt is empty, then you have to return a pair of empty strings.

So I just said fuck it and made an if statement right before the final command of returning ‘answer’ saying that if listOfArt[0] equalled undefined then answer equals ‘’.

if(listOfArt[0] == undefined){answer = ‘’;}

et voila!

Adrian’s Final Code

function stockList(listOfArt, listOfCat){let answer = ‘’;let object = {};   for (var i=0; i < listOfCat.length; i++) {      object[listOfCat[i]] = 0;   };   for(let x=0; x<=listOfArt.length — 1; x++){      for(let k = 0; k < Object.keys(object).length; k++){         if(listOfArt[x][0] == Object.keys(object)[k]){              let letter = Object.keys(object)[k];              let value = parseInt(listOfArt[x].split(‘ ‘)[1]);              object[letter] += value;          }     }   }   for(let z = 0; z <= Object.entries(object).length — 1; z ++ ){     if(z !== Object.entries(object).length — 1){
answer += `(${Object.entries(object)[z][0]} : ${Object.entries(object)[z][1]}) — `;
} else {
answer += `(${Object.entries(object)[z][0]} : ${Object.entries(object)[z][1]})`
} } if(listOfArt[0] == undefined){ answer = ‘’; }return answer;}

So how did the guys with IQs bigger than their shoe sizes do it?

function stockList(listOfArt, listOfCat) {var qs = {};if (!listOfArt.length) return ‘’;   listOfArt.forEach(function(art) {      var cat = art[0];      qs[cat] = (qs[cat] | 0) + +art.split(‘ ‘)[1];   });   return listOfCat.map(function(c) {      return ‘(‘ + c + ‘ : ‘ + (qs[c] | 0) + ‘)’;      }).join(‘ — ‘);   }
}

So we create a variable called qs that’s an object…cool.

Then we outrightly state that if there is no length to listOfArt then we should return ‘’

Well that was smart.

Then we create a variable inside of the use of a .forEach( ) array method being used on listOfArt in which during each iteration, the elements are temporary converted into a string with the temporary variable name of art.

Then we create a variable called cat that equals, due to string character access methods, the first letter of the string that art represents with

var cat = art[0];

After this we say that the object key equals whatever the variable cat evaluates to

You can dynamically create key/value pairs inside objects on the fly like this, it’s kinda groovy

You’re a CodeVenger now, keep up? #lol #onedayatatime

And the newly created key’s value is equal to what ever it currently has (if it has anything) || OR 0 PLUS the numeric-value of getting the temporary string variable of art being split into an array whose values are being separated by the space between them, and picking the second value (where the number lives);

the numeric value is attained by placing a + right on ‘art.split….etc’ cool huh?

listOfArt.forEach(function(art) {   var cat = art[0];   qs[cat] = (qs[cat] | 0) + +art.split(‘ ‘)[1];});

If you were to console.log qs at this time, it would look like this:

{ A: 200, C: 500, B: 1140, D: 600 }

Snazzy…my hat’s off.

Now comes the last part

We use the .map( ) array method on listOfCat to return a new array, but that method also takes a callback function and in it we return an array element that uses classic concatenation to return the value we want

return listOfCat.map(function(c) {   return ‘(‘ + c + ‘ : ‘ + (qs[c] | 0) + ‘)’;}).join(‘ — ‘);

BUT we don’t end up with an array, but we chain our array methods with .join( ) at the end, which if you’ll recall from previous entries, will create a string out of the array and separate them with it’s argument, and coincidentally enough when an array only has one item or it’s going through a mapping process and it runs out of items, it will return the array element without the separator, which in our case is a hyphen surrounded by two spaces.

This has got to be one of the most gangster fucking solutions to a problem like this that I’ve seen in a while.

God…damn. My solution was a Hemingway novel, these cats made a fuckin’ paragraph.

If we were rappers, these guys were Biggie and I was Silkk the Shocker.

— — — —

Problem 2: The Mexican Wave

(https://www.codewars.com/kata/mexican-wave/train/javascript)

Alas, I couldn’t actually figure this one out and after looking at the answer, feel kinda dumb. My ancestors are frowning on me from above while wearing their Jaguar Warrior armor and swinging swords at me.

Tenochtitlan (& Wakanda) FOREVER!!!

The wave (known as the Mexican wave in the English-speaking world outside North America) is an example of metachronal rhythm achieved in a packed stadium when successive groups of spectators briefly stand, yell, and raise their arms. Immediately upon stretching to full height, the spectator returns to the usual seated position.

The result is a wave of standing spectators that travels through the crowd, even though individual spectators never move away from their seats. In many large arenas the crowd is seated in a contiguous circuit all the way around the sport field, and so the wave is able to travel continuously around the arena; in discontiguous seating arrangements, the wave can instead reflect back and forth through the crowd. When the gap in seating is narrow, the wave can sometimes pass through it. Usually only one wave crest will be present at any given time in an arena, although simultaneous, counter-rotating waves have been produced. (Source Wikipedia)

Task

In this simple Kata your task is to create a function that turns a string into a Mexican Wave. You will be passed a string and you must return that string in an array where an uppercase letter is a person standing up.

Rules

1. The input string will always be lower case but maybe empty.

2. If the character in the string is whitespace then pass over it as if it was an empty seat.

Example

wave("hello") => ["Hello", "hEllo", "heLlo", "helLo", "hellO"]

How it’s done:

function wave(str){   let result = [];   str.split(“”).forEach((char, index) => {      if (/[a-z]/.test(char)) {      result.push(str.slice(0, index) + char.toUpperCase() +       str.slice(index + 1));      }   });return result;}
  • We create the variable result to hold our answer. It’s an empty array.
  • We use the string-method .split(“”) on our string to turn it into an array. Then we chain on .forEach( ) & pass in arguments to take the place of the current value char and the current value’s index index.
  • In the for loop implied by the use of .forEach( ) we use a RegEx expression to seek a letter and test if the value being iterated upon char matches any of those lowercase values
  • If they do, then we push a string into our results array
  • The string is constructed as follows:
  • We use the .slice( ) string-method to return a new string from an existing string, in our case we have three string chunks
  1. The portion of the string that is from the start to where our index from the .forEach( ) loop’s callback’s argument indicates
  2. The one character in the string that we want to be uppercase, referred to from the use of the .forEach( ) method as char (forEach’s argument referring to the value being iterated on) and then chained onto with toUpperCase( ), a string method that turns strings into…well…uppercase.
  3. The rest of the string that starts from whatever value index means plus 1 added to that, so that we get the rest of the string after where we stopped to use .upperCase( ).

The take aways:

-forEach is a really kickass array-method

-I don’t think I’ll ever be a regex master, but just 20% can get you 80% of what you want

-Really simple string methods can be really effective in making sure you don’t end up with “gum in your hair” levels of back tracking with regards to trying to lower case and upper case different parts of a given string. Slice is amazing, and I need to get used to using these methods more and more.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store