3
\$\begingroup\$

On Codewars, there is a challenge where the goal is to justify an str into a certain len. Here are the rules:

  • Use spaces to fill in the gaps between words.
  • Each line should contain as many words as possible.
  • Use '\n' to separate lines.
  • Gap between words can't differ by more than one space.
  • Lines should end with a word not a space.
  • '\n' is not included in the length of a line.
  • Large gaps go first, then smaller ones ('Lorem--ipsum--dolor--sit-amet,' (2, 2, 2, 1 spaces)).
  • Last line should not be justified, use only one space between words.
  • Last line should not contain '\n'
  • Strings with one word do not need gaps ('somelongword\n').

I have managed justify text correctly but there a few flaws that I am stumped on: a word that are too long for a length, and short length that causes nothing to happen. I would appreciate any possible solutions, feedback, advice, other flaws, etc. I am a beginner in JavaScript so code may seem messy.

function justify(str, len) {
   let splitStr = [];

   for (let i = 0; i < str.split(' ').length; i++) {
       if (str.split(' ')[i].length) {
           splitStr.push(str.split(' ')[i])
       }
   }

   let lines = [];
   let justified = [];

   while (true) {
       let line = [];
       let currentLine = true;

       while (currentLine) {
           if ((line.join(' ') + splitStr[0]).length < len) {
               line.push(splitStr.shift());

               if (splitStr.length === 0) {
                   break;
               }
           } else {
               break;
           }
       }

       lines.push(line.join(' '));

       if (splitStr.length === 0) {
           break;
       }
   }

   for (let i = 0; i < lines.length; i++) {
       line = lines[i].split('');

       if (line.length < len && i !== lines.length-1) {
           let neededSpaces = len - line.length;
           let spaces = [];

           for (let j = 0; j < line.length; j++) {
               if (line[j] === ' ') {
                   spaces.push(line[j]);
               }
           }

           while (neededSpaces > 0) {
               for (let k = 0; k < spaces.length; k++) {
                   spaces[k] = spaces[k] + ' ';
                   neededSpaces--;

                   if (neededSpaces === 0) {
                       break
                   }
               }
           }

           for (let j = 0; j < line.length; j++) {
               if (line[j] === ' ') {
                   line[j] = spaces.shift();
               }
           }

           justified.push(line.join(''));
        }
   }

   return justified.join('\n');
}
console.log(justify('Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making ' + 
'it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, '+
'from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections ' +
'1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ' +
'ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32. The standard \n\
\chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero \n\
are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.', 30)
\$\endgroup\$
1
\$\begingroup\$

Few improvements which can be seen right away are in this part

let splitStr = [];
for (let i = 0; i < str.split(' ').length; i++) {
  if (str.split(' ')[i].length) {
    splitStr.push(str.split(' ')[i])
  }
}

Can be re-written as:

const tempArray = str.split(' ')
let splitStr = tempArray.filter(data => data.length)
  • You can use Array.filter directly here.
  • Str.split(' ') is getting repeated at lot. So better save it in some variable and then re-use
  • Comparison inside if (length === 0) in other portions can be written as if(!length) since 0 is falsy
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.