Skip to content

Instantly share code, notes, and snippets.

@RobAWilkinson
Created August 10, 2015 23:08
Show Gist options
  • Save RobAWilkinson/9bd5e3d8359fc335c4d0 to your computer and use it in GitHub Desktop.
Save RobAWilkinson/9bd5e3d8359fc335c4d0 to your computer and use it in GitHub Desktop.

Processing Materials

This exercise is all about passing the output of one function into the input of another function, over, and over again. This is a core concept in javascript

Imagine that we have a a piece of iron and we need to refine it and convert it to steel, lets define an object to represent this material

var product =  {
  material: 'iron',
  carbon: false,
  temperature: 20
};

imagine we have a whole bunch of functions

function heatUp(product) {
  product.temperature += 500
  return product;
}

Then we define another function that adds carbon!


function addCarbon(product) {
  product.carbon = true;
  return product;
}

Then lastly, we define a function, isSteel that converts our iron to steel if it is at 1500 degrees and has carbon

function isSteel(product) {
 if(product.carbon && product.temperature >= 1500) {
    product.material = 'steel';
 } 
 return product;
}

Your job is to define a function applyAndEmpty that takes two inputs, an inital object and array of functions. It should pass this input into one function, and then pass the output of the function to the next and on and on

var processToSteel = [
  heatUp,
  heatUp,
  heatUp,
  addCarbon,
  isSteel
];
var product =  {
  material: 'iron',
  carbon: false,
  temperature: 20
};
applyAndEmpty(product, processToSteel);
/* this returns 
var product =  {
  material: 'steel',
  carbon: tru,
  temperature: 1500
};
*/

As a blacksmith we need to know how to replicate a tool we have already built. In this case we have a box full of nails, drills, and hammers:

var box = [
	{ nails: 5 },
	{ drills: 2 },
	{ hammers: 1 }
	];

The numbers resemble the amounts of each tool available in the box. We are now going to clone the tools to make the exact number of copies of each item.

var clonedBox = clone(box) // returns a copy of the box;

clonedBox[0] === box[0]  //this should return be true

Before we built a clone function that made a copy of an array of tools, however it had a slight error, it wouldnt work if your tools were made of other tools. For example, a blacksmith's bellows is made of two objects, a valve and two handles, our box would now look like this

In javascript objects are passed by reference, what this means is that if you just copy an object it only copys the memory location of that object. In our case, we actually want to copy the values not just the objects themselves

var box = [
	{ nails: 5 },
	{ drills: 1 },
  { bellows: {
      nozzle: 1,
      handles: 2
    }
  }
];

Your function cloneDeep should clone the values, not just make a copy of the objects!

var deepClone = cloneDeep(box)
deepClone === box // false
deepClone[0] === box[0] // false 
deepClone[0].nails === box[0].nails // true

As a blacksmith we need to be able to filter out specific ores from a bunch of different ones based on instructions. In this case we have a bin of six different ores:

var bin_of_ores = ['iron', 'coal', 'bronze', 'copper', 'granite', 'cobalt'];

We have a function that has the instructions of which ores need to be filtered out - element refers to each ore, index refer to the position of that ore in the collection, and collection refers to the entire bin of ores.

When we call our filter function we want to filter out every ore in the bin based on a set of instructions:

var instruction = function(element, index, collection){
	return element % 2 === 0;
};

filter(bin_of_ores, instruction(element, index, collection)); 
// returns ['coal', 'copper', 'cobalt']

#Flattens a nested array.

flattenDeep([1, [2, 3, [4]]]); // returns  [1, 2, 3, [4]]

Iterates over elements of an array invoking callback for each element. The callback should be passed the element, the current index, and the entire array.

var callback = function(element, index, array) {
 console.log(element +"," +index +"," +array);
}
forEach(['a','b','c'], callback); // prints a,0,[1,2,3] b,1,[1,2,3] c,2,[1,2,3]

For each element in the array, the callback we passed is called. The callback can be customized, but in the above example, the callback prints out the element, index, and entire array. Iterates over elements of array in reverse invoking callback for each element. Callback(element/value, index/key, collection)

var callback = function(element, index, array) {
 console.log(element +"," +index +"," +array);
}
forEach(['a','b','c'], callback); // prints c,2,[1,2,3] b,1,[1,2,3] a,0,[1,2,3]

Getting started

##Welcome to Smithy CLI And Congratulations on taking your first steps on learning the hard parts of Javascript!

       __
      /  |_____________
      |  ______________]
      |  |
      `--'

  .-------..___
  '-._ CS  :_.-'
   .- ) _ ( --.
  :  '-' '-'  ;.
 /'-.._____.-' |
 |   |     \   |
 \   |     /   \
 |   \     )_.-'
 '-._/__..-'

Let's do a little housekeeping first, remember you can always type smithy in your terminal to come back to the menu.

You're going to want to move to directory where you can play around and write a new file. We recommend that you have one file that you use to run all your exercises.

Why don't you make a new directory to hold all the code we're going to be be writing. In there we need to make a new file ( you can call it anything you want, it just needs to have a .js ending. )

We recommend that you start at the Forge Exercise and work your way through them step by step.

To pass this lesson just run smithy verify and then the name of your file #Cleaning your materials

A lot of your time as a smith will be cleaning out garbage materials and only returning the stuff that you need. We built our pluck function earlier to do this but it had a key error, it would only return an array of a single key. Imagine we are giving a bunch of bins like this

bin1 = {
  iron: 10,
  copper: 5,
}
bin2 =  {
 iron: 4,
 copper: 4,
 granite: 5
}

If we were to call our pluck function with 'iron' we would only get the iron and we would throw all the copper away.

What if we could loop through this array of bins and run a function on every single one? We need to call this function map. Heres a quick example

We create a function goldAndSilver that returns a new object with only the gold and silver in the bin.


function goldAndSilver(bin) {
  var output = {
    gold: bin.gold,
    silver: bin.silver
  };
  return output;
}


Then we pass this function, into our new function map. When you pass a function into another function, it us called a callback function. Remember this, its something that we're going to use over and over again.

map(arrayofBind, goldAndSilver) === [{ gold: 5, silver: 3}, {gold: 2, silver: 3}]

As a blacksmith we need to keep track of our blueprints and know what items we have already created a blueprint for. We do not want to create duplicate blueprints of the same item. The memoize function can help us with this issue. Let's say we have a helmet function:

var helmet = function(){
	console.log('blueprint of helmet is finished');
}

If the helmet function gets run already, we don't want to run it again because that would mean we have created the blueprint of the helmet twice. So, if we pass this helmet function as the input of the memoize function:

memoize(helmet)(); // run helmet only once
memoize(helmet)(); // do not run helmet because it ran already

The memoize function ensures that a function runs only once. When passed to the memoize function, will not run again if it already ran. Otherwise, it will run but won't run ever again even if called through the memoize function. # As a blacksmith we need to make sure we have quality materials In this case we're going to be given a bunch of of different bins of various ores. They will be objects that look like this:

var bin = {
  iron: 20,
  granite: 5,
  diamond: 1
}

We probably don't want to use all these materials, usually we just want one thing. Our job is to write a pluck function that can return an array of all the different values.

var bins = [
  { iron: 20, granite: 5 }, 
  { iron: 10, copper: 3}
  ];

pluck(bins, 'iron');
// this should return
[ 20, 10]

#Smelting materials

Sometimes a blacksmith has a ton of useless iron ingots lying around near the furnace and they need to combine them into one large ingot to make it eaasier to handle.

We need to write a function reduce that takes an array of ingots like this:

  var ingot1 = {
    weight: 12
  };
  var ingot2 = {
    weight: 5
  };

Our functions job is to take this array of ingots and smelt it down into one giant ingot. To do this, we need to sum up the weights of all the different elements in the array.

we need to create a function reduce that takes an array, a callback function, and an initial value.

We need to pass that callback function 4 parameters

  1. the previous value aka whatever the last callback function returned
  2. the current value aka the element that we are currently on
  3. the index of the current element
  4. the array as a whole

Heres a example of using reduce to multiply all the elements of an array together

var arr = [3,6,9];

function reducer(prevValue, currentValue, index, array) {
  return prevValue + currentValue;
}
reduce(arr, reducer, 1);

this callback will be called 3 times, with prevValue increasing every time

Write stuff about REJECT here# For This challenge we're going to be covering some javascript fundamentals.

You all are probably familiar with javascript in the browser, but this may be your first time playing with javascript in the console.

##Creating Variables

Before we can really get started on making things we have to learn how to create variables, these are the building blocks we're going to use to create everything later on.

Its pretty easy in Javascript there are 2 parts to any variable creation, you declare the variable, and then you say what it is equal too. We're going to create a variable iron and set it equal to the string "iron"

var iron = "iron"

In your code, create two variables copper and zinc equal to the strings "copper" and "zinc".

##Smelting metals

Now that we have our variables created we are going to create functions, you can think of functions as a smelter that can take variables and output(return) something different. You create functions and then call them later down the line.

function add(x, y) {
  return x + y;

I want you to create a function smelter that takes two inputs. When you call that function with copper and zinc it should return "bronze"

Blacksmith lvl 2

The great thing about functions is that you can use them again and again. If you give them different inputs, sometimes called parameters, they can return different outputs. If we take our smelter function and pass it two new variables carbon and iron equal to "carbon" and "iron" your function should return steel. Do this without breaking the bronze functionality you did earlier! #Sorting things

As a blacksmith we're sometimes given the challenge of dealing with all the useless gemstones we find while sorting ore bins.

What if we need to sort these gemstones by hardness in order to add them to a piece of armor.

Each gem is a javascript object that looks like this

var gem = {
  name: 'ruby',
  hardness: 9.0
}

Your job as a smith is to create a function sortBy that takes two parameters:

  • the first is an array of gems.
  • the second can be either a function, or a property name.

Your function needs to go through the array of bins, pass them into the callback function, and based on what that callback function returns, place it in the array.

Heres a quick example:

var gems = [
  {
    name: 'ruby',
    hardness: 9.0
  }, 
  {
    name: 'diamond',
    hardness: 10.0
  },
  {
    name: 'jade',
    hardness: 7.0
  }
];
pluck(sortBy(gems, 'hardness'), 'name') // ['jade', 'ruby', 'diamond']

It should also work when you pass a function rather than a property name

var arr = [1, 2, 3];
sortBy(arr, function(n) {
  return Math.sin(n);
}); //  returns [3, 1, 2]

As a blacksmith we need to be able to follow instructions when creating a tool. We are given an array of elements that we can use to make a tool:

var nail = ['iron', 'granite', 'copper'];

We only use the elements that the instruction tells us to. So, we need to create a slice of the given array of elements (taken from the beginning) to resemble only the elements we are using. If the instruction doesn't say anything, we only take the first element.

var hammer = ['iron', 'granite', 'copper'];
var spear = ['iron', 'granite', 'copper'];
var pans = ['iron', 'granite', 'copper'];

take(hammer); // returns ['iron']
take(spear, 2); // returns ['iron', 'granite']
take(pans, 3); // return ['iron', 'granite', 'copper']

If the instruction says to use more than the elements listed, we use all the elements in the array. If the instruction says to use no elements, we return an empty array.

var plate = ['iron', 'granite', 'copper'];
take(plate, 0); // returns []

Creates an array without duplicate values. The order of the array is preserved.

uniq([1,2,1]); → [1,2]

#Combining armor

After a battle you are given a ton of excess armor that you need to go through to discover what can be salvedged and what cant. We have to go through each package, grab only the object we need and put it in another array

each array is made up of a helmet object, a chest piece and a sword,

  var package1 = [
    {
      type: 'helmet',
      style: 'japanese',
      quality: 'High'
    },
    {
      type: 'chest',
      style: 'viking',
      quality: 'poor'
    },
    {
      type: 'sword',
      style: 'japanese',
      quality: 'high'
    }
  ];

  var package2 = [
    {
      type: 'helmet',
      style: 'english',
      quality: 'medium'
    },
    {
      type: 'chest',
      style: 'viking',
      quality: 'poor'
    },
    {
      type: 'sword',
      style: 'german',
      quality: 'high'
    }
  ];

After a battle you're given an array of a ton of these packages and you have to write a zip function that seperates all the helmets into a certain bin, all the swords etc etc.

zip([package1, package2])
/* This returns 3 arrays, one of all the helmets, one of all the chestpieces, and one of all the swords */

heres another example, we are zipping up an array of competing smiths

zip(['fred', 'barney'], [30, 40], [true, false]); 
// returns  [['fred', 30, true], ['barney', 40, false]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment