Should this be happening? - Algorithm Scripting

I am relatively new to coding and JavaScript , and currently on the intermediate algorithm scripting. Starting off the algorithms (basic included) i have sometimes noticed my code is way too over complicated and lengthy. Is this normal?

Just recently, i did the Roman Numeral conversion challenge. Here was my solution --> https://repl.it/@John_Nicole/Intermediate-Algorithm-Scripting-Roman-Numeral-Converter

I felt very confidant of myself when i finally manged to do it. It may be 86 lines, but it does do 1 to 1 million conversion. To check out what other people did, i went to freeCodeCamp Algorithm Challenge Guide: Roman Numeral Converter. Then their it was, a 10 line solution that i had no idea how it works. It may only do up until 4,999 until it just repeats 1,000 a ton of times until it reaches your number, but its still very compact. Should i feel disappointed that i spent 2 days on this for it being over complicated?

Did everyone else write compact code like that made by professionals when they first started FCC? Should i be worried?

I am using ES5, which is just bigger in general compared to ES6. So is this a optical illusion?

Thanks for any feedback

Oh, good god no!

I teach music, when I’m lucky, jazz. Of course improvising solos is big thing. And one of the things I always tell my students is, “If you want to play good solos, first you’ve got to play a lot of bad ones.”

I’d say the same of coding, “If you want to write good code, first you’ve got to write a lot of bad code.”

But that’s part of the process. After you’ve written your version, I’d recommend seeking out some other solutions and see what they came up with. See if you can understand it.

As you get more experienced, your sixths sense about the best algorithmic approach is will improve.

Just put in the time.

So, to answer your question, “Yes” you should be concerned about writing clumsy code, but only in the sense that you want to be aware of it and keep improving, not in the sense that there is anything abnormal about you.

3 Likes

Wow thanks so much, that really helped! :smiley:


I sometimes see people be like:

"Simple solution"


One thing i do is not make use of keywords. I go out and right a 20 line function that is the same as one keyword. Ill just look out for keywords and shortcuts


My worry was that yes you right bad code and get better, yet is my code too over complicated for my level (basically too bad). Am i starting off too low? I can’t wait to learn ES6 (i know the new beta site has it) since its more compact.

Thanks!

Again, one of the cool things is that after you finish the Roman Numeral problem, go search google and find how others solved it. There are people writing about it in blogs, people writing about it here, people posting youtube videos…

Go see what they did. How did they approach it? There’s usually more than one approach, sometimes many.

And be wary of worshiping at the altar of concision. Just because code is more compact does not mean that it’s better - it may be more difficult to read and in some cases may actually be slower.

Just keep learning. You’ll learn more built in methods, learn some ES6 tricks, get some algorithmic experience, and things will get better.

1 Like

One of the constants of coding:

Or in other words: don’t worry too much… your code will always looks like garbage 6 months after writing it

and if not

start worrying because it means that you’ve stopped improving!

2 Likes

@ksjazzguitar

Thanks, ill remember that for compact code. Simple if statements/ slicing are easier to run then a keyword your using might be a 1,000 lines of code vs your 10 line if statement that only 3 of those lines are being used at once. I see people use only keywords and built in functions.

I would rather write that 10 lines then use a complicated keyword because it teaches you to logically think. What happened’s when your keywords don’t apply and you need to think of something totally new?

I say “complicated” because i’m not talking about split() or slice, i’m talking about indexOf(), etc. Those keywords are designed to work with any program or input (that is desired), so they aren’t as simple as looping through a array.

My thing is, its mainly if statements and arrays i’m using, so it naturally takes up space. Roads have a simple function yet take up a lot of space. Ill pay attention more to shortcuts and try to eliminate excess arrays or variables i don’t need. I wanted my conversion to work with any number until a million, not just 4,999.


@Marmiz

I have the logic down, sometimes its just takes up space. I need to set limits too myself, for instance, limiting myself on how many lines i can use just to push myself for better learning.

function findRoman(zero) {
        if (zero === 6) {
            findRomanArray = roman.slice(0, 1);
        } else if (zero === 5) {
            findRomanArray = roman.slice(0, 3);
        } else if (zero === 4) {
            findRomanArray = roman.slice(2, 5);
        } else if (zero === 3) {
            findRomanArray = roman.slice(4, 7);
        } else if (zero === 2) {
            findRomanArray = roman.slice(6, 9);
        } else if (zero === 1) {
            findRomanArray = roman.slice(8, 11);
        } else if (zero === 0) {
            findRomanArray = roman.slice(10, 13);
        }
        return findRomanArray;
    }

This is 17 lines, yet its as simple as can be. Just slices a different part of a array based on a input. Only once is it activated in a 9 intervals of a simple loop. I feel like their is little i can do about this, and its just apart of coding. Thanks!


Thanks to everyone who has replied so far, very helpful!!!

First off, those aren’t “keywords”. Keywords are like “if” and “typeof” and “for”. Those (slice, indexOf, etc.) are built in methods of Array and Object prototypes.

Are they better than a for loop? That’s debatable. Sometimes a humble for loop is just what is needed. But often a prototype method will be clearer. Yes, they took me a while to get used to, but once you do, they can be quite handy and efficient. Yes, to the uninitiated they can appear cryptic, but with practice you’ll learn them and their power. Sometimes their just more compact, but sometimes they’re faster. Also, once you know what they all do, it’s more clear looking at the code than having to figure out what each for loop does.

But even still, sometimes a for loop is going to be best. But don’t assume it’s best because it’s the most comfortable. Whenever I have to iterated through an array, my first thought is, “Is this a chance to learn one of the Array.prototype methods?” The more I use them, the more comfortable they become.

I think you are limiting yourself if you avoid them and will make it more difficult for you to work with other coders. Just think of them as abstractions of for loops. Unless you’re soldering transistors, everything in programming is different layers of abstraction.


OK, your example …

function findRoman(zero) {
        if (zero === 6) {
            findRomanArray = roman.slice(0, 1);
        } else if (zero === 5) {
            findRomanArray = roman.slice(0, 3);
        } else if (zero === 4) {
            findRomanArray = roman.slice(2, 5);
        } else if (zero === 3) {
            findRomanArray = roman.slice(4, 7);
        } else if (zero === 2) {
            findRomanArray = roman.slice(6, 9);
        } else if (zero === 1) {
            findRomanArray = roman.slice(8, 11);
        } else if (zero === 0) {
            findRomanArray = roman.slice(10, 13);
        }
        return findRomanArray;
    }

is an example of something that could be improved upon with a switch statement (another keyword):

function findRoman(zero) {
  switch (zero) {
    case 6:
      return roman.slice(0, 1);
    case 5:
      return roman.slice(0, 3);
    case 4:
      return roman.slice(2, 5);
    case 3:
      return roman.slice(4, 7);
    case 2:
      return roman.slice(6, 9);
    case 1:
      return roman.slice(8, 11);
    case 0:
    default:
      return roman.slice(10, 13);
  }
}

To me, that’s easier to read. Any time you have a chain of if/else statements checking the equality of the same variable, that’s probably a good case for a switch statement.

Again, don’t assume that something is better just because you are comfortable with certain tools.

Yes, I agree that you can get carried away in the opposite direction too. For example, in C, you can build ridiculously hard to read code that is compact and fast, the the point of being tortuous to read. But also don’t be afraid to expand your knowledge of tools.

And of course, using some ES6 and some math, I think it could all be replaced with:

const findRoman = (zero) => roman.slice(Math.max(0, 10-(zero*2)), 13-(zero*2));

Is that better? It’s more compact. It may be a tad faster, but the speed probably won’t matter. It’s a tad less readable. One could build the argument that the switch statement is better because it’s more readable.

2 Likes

Besides all the great suggestions that @ksjazzguitar just gave, in the example provided you have repeated yourself many times.

There’s a popular paradigm when writing softwares that states: Don’t Repeat Yourself!

Just to give you a different approach as the one that @ksjazzguitar already provided, you could have simply created a data collection of key - values.
That way you don’t need to check all the cases, but only if the value is in the collection.

I’m gonna hard code the values here for sake of simplicity, but the “optimal” approach would be to dynamically create this collection based on the current case ( again don’t repeat yourself).

/*
* @param {array} arr - the array we want to slice
* @param {integer} i - the index we are receiving - you called it 'zero'
* @returns {array} - a new sliced array.
*/

function f(arr, i){
 // let's hard code index and values for now
  const map = {
    6: [0,1],
    5: [0,3],
    4: [2,5],
    3: [4,7],
    2: [6,9],
    1: [8, 11],
    0: [10,13],
  };
  
  // basic check - i is not in our map: something's wrong.
  if (!map[i]) {
    return 'give me a valid index'
  }
  
  // return the sliced version.
  return arr.slice(map[i][0], map[i][1]);
}

But just to don’t go too much off topic:

  • have I ever wrote code like this? - no
  • is it the best code ever written? - also no
  • does it work? - yes (hopefully)
  • is it properly commented? yes

Then I’m good to go.
As the comics above tried to express with humor is that perfection is an idea, but in practice you also have to make things works.

Just keep on practicing and you’ll get better :slight_smile:

1 Like

Yes, there are many solutions.

When I first started learning coding (when dinosaurs roamed the Earth) it was all about balancing speed and memory usage. Now that computers are so fast and memory is cheap, it’s more about readability/maintainability/security/UI/UX/etc. It’s all a balance. As my music theory teacher used to say, “There is more than one right answer. There’s also an infinite number of wrong answers, but there is more than one right answer.” And which one of those answers is “best” can be a little subjective, depending on what is more important to you. But there are some that are “objectively” less good.

@ksjazzguitar

Ill remember that for doing if statements. I’ll also look for better keywords, but not go too far out of my league on what i can do. I never really understood prototype. Whats the difference between regular and prototype? How can i learn prototype besides massive articles that make no sense.

How did you learn ES6? I feel like i’m missing out.


@Marmiz

Still a little confuse don what that code does. Ill remember not to repeat myself in coding. How do i know what new keywords to use? Both of you guys kind of mentioned built in functions that might make it easier, but how do i know? You usually use multiple to complete a task, and i wouldn’t know where to start.


[quote=“John-freeCodeCamp, post:11, topic:160432”]
I never really understood prototype. Whats the difference between regular and prototype? How can i learn prototype besides massive articles that make no sense.[/quote]

It means that they are built into the parent class and are inherited by their children. There’s a more complicated explanation, but for now don’t worry about it. Just think of them as things that are built into objects. (Remember that everything that isn’t a simple data type is an object, including strings and arrays.)

You use these all the time. Objects have built in properties and methods (functions). For example, When you do myString.length, that .length property is a built in property, inherited from the prototype. The same with myArr.sort(), you don’t have to define the .sort() function, it just comes along for the ride when you create an array.

Later on you can learn about OOP and learn how this is happening, but for now just accept that these properties and methods are inherited whenever you create an object. Sometimes partial understanding is “good enough for now”.

I just learned in piece by piece. I kept getting exposed to it in React and found it convenient.

Are you missing out? Maybe a little. But you’ll pick it up. I’d just hit up some youtube videos.

Arrow functions are very common in ES6, so I’d take a look at those. Their a little weird at first but you get the hang of it. Spread operators and destructuring come in handy. Default properties and string literals come in handy too. Getting to undestand const and let is pretty important.

There’s probably nothing you can do in ES6 that you can’t do in ES5, it just will look different and may take more lines. It would be like going golfing with just a five iron. Can you do it? Sure. Can you get the ball in the hole? Sure. Are you going to be able to do it as easily as a guy with a full club set? Probably not.

There’s a reason why programmers fought for these features - because they are very useful. But don’t feel like you have to stop doing what you’re doing now and learn ES6. I just go and look up things when I saw them in code. Gradually they stuck. I still have some ES6 things I need to figure out, but I’m getting there.

But if I had to make a short ES6 list to learn, it would be:

  1. arrow functions (coders have practically fetishized these - they are everywhere)
  2. let and const (just different ways to declare variables but with some minor but important differences)
  3. spread operator (not vital by very handy)
  4. destructuring (not vital by very handy)
  5. default properties (not vital but very handy)
  6. shorthand property names (easy to understand but confusing if you don’t know what you’re looking at the first time)
  7. string literals (I don’t know how important it is, but they’ll look weird when you first see them)

That’s my list anyway. There’s a lot more in ES6, but those are the things I keep running into. And as you work with other programmers and get onto more advanced topics, you’ll run into them more and more. Just start chipping away at it. It might me good to read through all of the ES6 ideas just to get an idea of what is in there, even if you don’t understand them - that way you can recognize them when you come across them.

But don’t panic. Just learn. Little by little we get there.

If you can solve the challenges you should be proud. Afterwards, go through the solutions and don’t move on until you understand them. This will greatly help teach you the more sophisticated solutions and way of thinking. If you can solve them then the way you went about getting the answer is correct, there might be a better way but the challenge is to see whether or not you can cross the finish line not whether you implemented the most advanced solution.

  • Everything in JavaScript is an object*.
  • Objects are collections of key/value pairs. There are some special rules to help make the language work, but basically everything in JavaScript is a collection of those key/value pairs.
  • These values can be functions (which in JS are just another type of object, but anyway). They are generally called methods. For example, Math.max is a function called max on an object called Math.
  • To avoid you needing to write methods yourself every time you needed them (for example, having to write a function to get the length of an array for every array you ever created that you needed the length of), all objects automatically come witha property called prototype, which has a reference to another object which has a set of values which are common to all objects of that type. For example, Array.prototype has properties like length, indexOf, forEach. Every array you create will point to that prototype, so you.get access to all those methods. Array.prototype.length is a property called length in an object called prototype referenced in an object called Array

This concept is central to how JavaScript works. The way it works under the hood is a little more complex than described (not much more though). You don’t generally ever have to touch the prototype on built-in objects like Object, Array, etc, the language is designed to make the process fairly easy so you can avoid a bit of the magic stuff that makes it work.

* strings, numbers booleans etc are primitives (not objects), but anytime you manipulate them like myString.toUppercase(), JS wraps them in an object to do the work.
Also there is a highly optimised version of JS that doesn’t use objects (WebAssembly, which lets you compile code written in C to JS), but that’s a bit different.

1 Like

Thanks guys for your help. Still having trouble understanding prototype. I need a visual, something i can see instead of read (no syntax).

I just never have the built in functions off the top of my head. I never remember “oh i can use those 5 functions to do this.”

If a program doesn’t work, you don’t know why sometimes. You could be close, but delete and try again not releasing your mistake.

Ill look up more ES6, see if i can know the basics.

Again, if you really want to understand it, I think you need to dive into object oriented programming. But that is more than you want to bite off right now. Instead, just think of them as functions that are built into the object (or array, which is also a type of object in JS). Really, that’s all you need to understand.

I would just take them one at a time. Learn how sort works. Then tackle map. Then filter. There are plenty of great blog posts and youtube videos to show you how they work. Again, anytime you have to iterate through an array, there is probably a built in function to do it easier.

I can’t remember them all either. If I can’t figure out which one to use, I look up Array.prototype on MDN and read the descriptions. After you get to know a few of them, the others start to make more sense.

Again, most good JS coders are going to use these functions so if you avoid them, you’re putting yourself at a disadvantage.

thanks, i have started to look up some es6 and it seems interesting. I already started using the Conditional (ternary) Operator and its pretty cool and efficient. I was also looking at const, let and for in/ for of loops.

I’m having trouble with the Wherefore art thou challenge.

function whatIsInAName(collection, source) {
    var array = [];
    var names = [];
    names.push(Object.getOwnPropertyNames(source));
    for (var i = 0; i < collection.length; i++) {
        for (var x = 0; x < names.length; x++) {
            collection[i][names[x]] === source[names[x]] ? array.push(collection[i]) : null;
        }
    }
    return array;
}

whatIsInAName([{ a: 1, b: 2 }, { a: 1 }, { a: 1, b: 2, c: 2 }], { a: 1, b: 2 });

It compares all the names, but not in groups. It compares them for the a, and then b. Not just directly a and b.

This thread has gone on a while and most people are probably ignoring it now. I would suggest starting a new thread for this new problem.

1 Like

@John-freeCodeCamp I don’t know if you’re meaning for this to happen but your names array length is only one because you stored another array in it at index 0. So anytime you reference names[x] you’re referencing another array, not an individual value.

In case it’s not clear why that happens, the getOwnPropertyNames method returns an array. So you’re pushing that array into your names value. That could be why your loops aren’t working like you intended them.

Okay. Since i posted that i did change my code a lot too this.

function whatIsInAName(collection, source) {
    var array = [];
    var sourceNames = Object.getOwnPropertyNames(source);
  for (var i = 0; i < collection.length; i++) {
         var collectionNames = Object.getOwnPropertyNames(collection[i])
        JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ?  array.push(collection[i]) : null
      }
      return array
}

whatIsInAName([{ a: 1, b: 2 }, { a: 1 }, { a: 1, b: 2, c: 2 }], { a: 1, b: 2 });

Now i’m trying to check if the object partially contains another. Like { a: 1, b: 2, c: 2 } containg { a: 1, b: 2 }

–> https://repl.it/@John_Nicole/contains-objects