I am working on a project where I have strings with lots of brackets like ((A and B and (C or (D and E))) or F). I need to find a way to find the pairs and style or color them to show they are matching. For example, the brackets around "D and E" would be green, and the ones around "C or (D and E)" would be blue. For matching pairs I was using a stack but couldn't find a way to set colors, if theres a better way I'm open to try it. I'm working in asp.net and C#. Thanks!
Edit: here is the code that generates the string. terms is a list of values, innerConnector is either "and" or "or" based on user input, and child groups are groups within the larger group. (A and (B or C)) A would be a term, (B or C) would be a child group. I want to take the string this returns and apply the colors to the parentheses.
public string toString()
{
string str = "(";
if(terms.Count > 0)
{
for(int i = 0; i < terms.Count; i++)
{
if(i == 1)
{
str += terms[i];
}
else
{
str += " " + innerConnector + " " + terms[i];
}
}
}
if(children != null)
{
for(int i = 0; i < terms.Count; i++)
{
if(i == 1 && terms.Count == 0)
{
str += childGroups[i].toString();
}
else
{
str += " " + innerConnector + " " childGroups[i].toString();
}
}
}
str += ")";
}
I see you've removed javascript from your question tag. Disregard below then.
This was quite fun to have a play with actually. It's not the most elegant solution!
I've slightly commented the code because I'm such a lovely chap.
// List of colours we'll use.
var colors = ['red', 'blue', 'purple', 'orange', 'green'];
// Define the div and it's contents
var div = document.getElementById('colors')
var string = div.innerHTML;
// A function to return a span object with coloured text.
color_span = function(color, inner) {
return '<span style="color:' + color + '">' + inner + '</span>'
}
var color_count = 0;
var return_html = '';
// Cycle through each character in the string
for (i=0; i < string.length; i++) {
// If it's an open bracket, add a coloured span to the return_html and increment the colour counter
if ( string[i] == '(' ) {
return_html += color_span(colors[color_count], string[i]);
color_count++;
// If close bracket add coloured span and decrement the colour counter.
} else if ( string[i] == ')' ) {
color_count--;
return_html += color_span(colors[color_count], string[i]);
// If neither just add the character.
} else {
return_html += string[i];
}
}
// Change the div's html.
div.innerHTML = return_html
JSFiddle
Related
in my code I check for the special cases 'Z' 'z' and ' ' in a string to handle appropriately using conditional statements. In the first cases, if these characters appears I set them to 'A' 'a' in respect. If ' ' appears, I use continue with the intention of going to the next iteration and to preserve the white space. However, instead of preserving the white space, I get undefined om the string.
var result = document.getElementById('result');
var finalString = "";
// Take each character in a given String and shift one letter up in the alphabet
function shiftString() {
var userString;
var storeString = Array();
userString = document.getElementById('string').value;
if (typeof userString === 'string') { // JS must interpret user input as a string
for (var i = 0; i < userString.length; i++) { // Iterate through each character in given string
if (userString.charAt(i) == 'z') { // If we reach the end of the alphabet, start over at the beginning
userString.charAt[i] = 'a';
}
else if (userString.charAt(i) == 'Z') {
userString.charAt[i] = 'A';
}
else if (userString.charAt(i) == ' ') { // Keep spaces as they are
continue; // This results in a string such as 'HelloundefinedWorld'
}
else // Shift to the next character over
userString.charAt[i] = (String.fromCharCode(userString.charCodeAt(i) + 1));
}
console.log(typeof userString)
return displayResult(userString);
}
}
// Take the end result of the translated String and post it to the DOM
function displayResult(a) {
for (var i = 0; i < a.length; i++) {
finalString += a.charAt[i];
}
result.innerHTML = finalString;
}
function clearResult() {
result.innerHTML = "";
}
Simplified the code and corrected the mistakes including those mentioned in the comments. Also used substr() function for the character replacement. Seems to work now. Check it out:
var result = document.getElementById('result');
shiftString();
// Take each character in a given String and shift one letter up in the alphabet
function shiftString() {
var userString = document.getElementById('string').value;
if (typeof userString === 'string') { // JS must interpret user input as a string
for (var i = 0; i < userString.length; i++) { // Iterate through each character in given string
if (userString.charAt(i) == 'z') { // If we reach the end of the alphabet, start over at the beginning
userString = userString.substr(0, i) + 'a' + userString.substr(i + 1);
}
else if (userString.charAt(i) == 'Z') {
userString = userString.substr(0, i) + 'A' + userString.substr(i + 1);
}
else if (userString.charAt(i) == ' ') { // Keep spaces as they are
continue; // This results in a string such as 'HelloundefinedWorld'
}
else{ // Shift to the next character over
var newChar = String.fromCharCode(userString.charCodeAt(i) + 1);
userString = userString.substr(0, i) + newChar + userString.substr(i + 1);
}
}
result.innerHTML = userString;
}
}
<input id="string" type="text" value="aAzZ thisIsCool"/>
<div id="result"></div>
Write a program that creates a string that represents an 8×8 grid, using newline characters to separate lines. At each position of the grid there is either a space or a “#” character. The characters should form a chess board.
My code keeps creating an 8 x 8 structure with all hashes.
Can someone offer some advice to edit my code?
var size = 8;
var str = "";
var altern = false;
var line = 1;
while (line <= size) {
var character = 1;
while (character <= size) {
if (altern) {
if (character % 2 === 0) {
str += "#";
console.log(character);
console.log(str);
} else {
str += " ";
console.log(character);
console.log(str);
}
} else {
if (character % 2 === 0) {
str += " ";
console.log(character);
console.log(str);
} else {
str += "#";
console.log(character);
console.log(str);
}
}
altern = !altern;
character++;
}
str += "\n";
line++;
}
console.log(str);
By using both altern and character % 2 you select the branch with the # every iteration. Use only one of the two.
I couldn't figure out how to answer this myself until I found OP's code. Here is what I found would work:
var size = prompt("What is the size?");
var str = "";
var line = 0;
//Instead of using 1, use 0. It'll make sense in the next comment.
while (line < size) {
var character = 0; // Changed this to 0 as well.
while (character < size) {
if (line % 2 === 0){
/*Instead of using logic negate(altern = !altern), you could use one of the variables
you already have. Changing line = 1 to line = 0, we now can write the conditon above.
Where the first line holds true, because 0 % 2 === 0 is true.*/
if (character % 2 === 0) {
str += " "; // I switched the string values around, to get what is resembled in the book.
console.log(character);
console.log(str);
} else {
str += "#"; // Here
console.log(character);
console.log(str);
}
} else {
if (character % 2 === 0) {
str += "#"; // Here
console.log(character);
console.log(str);
} else {
str += " "; // Here
console.log(character);
console.log(str);
}
}
character++;
}
str += "\n";
line++;
}
alert(str);
//Changed this so the final result is easier to see, rather than in the jumbled mess of the console.
I suspect that you want to toggle altern with each new line, not with each square.
You have a loop inside a loop here. Move your altern toggle code from the inner loop to the outer loop.
while (line <= size) {
var character = 1;
while (character <= size) {
// inner loop code here
character++;
}
// Outer loop end code. HERE is where you toggle altern
str += "\n";
line++;
altern = !altern;
}
Below one works but I replaced spaces with Os (capital o's) and a little change in your code.
var size = 8;
var str = "";
var altern = false;
var line = 1;
while (line <= size) {
var character = 1;
while (character <= size) {
console.log('altern: ' + altern + 'character: ' + character);
if (altern) {
if (character % 2 === 0) {
str += "O";
console.log(character);
console.log(str);
} else {
str += "#";
console.log(character);
console.log(str);
}
} else {
if (character % 2 === 0) {
str += "O";
console.log(character);
console.log(str);
} else {
str += "#";
console.log(character);
console.log(str);
}
}
altern = !altern;
character++;
}
str += "\n";
line++;
}
// console.log(str);
alert(str);
This one works, but not, I suggest you to try to re-write this code in a better way. Hint: pay attention to what #koenpeters said.
Instead of using all those loops you could do this:
var width = 8,
height = 8,
str = new Array(1 + (width * height + height) / 2).join('# ').replace(new RegExp('(.{' + width + '}).', 'g'), '$1\n');
Works as long as width isn't even while at the same time height is odd.
If you just need it for this one specific case you could also get rid of a bit of the overhead and just use this:
var str = new Array(37).join('# ').replace(/(.{8})./g, '$1\n')
Instead of a while loop and over-repetition of your cases based on location (i.e. even vs odd) use two for loops and one case statement for whether a location needs a # vs " ". Store them to a var, then print the var once it is complete.
var board = "";
var countX = 0;
var countY = 0;
var size = 8;
for(var i = 0; i < size; i++) {
for(var j = 0; j < size; j++) {
if((countX + countY) % 2 == 0) {
board += " ";
}
else {
board += "#";
}
countX++;
}
board += "\n";
countY++;
}
console.log(board);
board output:
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
i would have tackle this problem by first using a while loop to printing out a line of 8 harsh (########) symbol , then repeat it 8 times vertically using another loop, write a test condition that changes the value of y when the value of both iteration are even numbers.
const size = 8
for(let i = 0; i < size; i++){
let y = " "
let cols = 0;
if(i % 2 == 0){
y = "";
}else{
y = " ";
}
while(cols < size){
if( cols % 2 == 0){
y = y + "#"}
else{
y = y + " "
}
rows++
}
console.log(y)
}
Nested For Loop will work the best for this solution as below ---
//to get the input from the user for any size of the array
var charSize=prompt('Enter Number');
var boardChar = "";
//outer loop
for (let i = 1; i <= charSize; i++) {
//inner loop
for (let j = 1; j <= charSize; j++) {
//Check for even column
let evenCol = (i + j) % 2;
if (evenCol == 0) {
boardChar += " ";
} else {
boardChar += "#";
}
}
boardChar += "\n";
}
console.log(boardChar);
//OUTPUT
[Output Image][1]
The essential thing to realise is that given the N th row, its first square will be black if N is odd, and white otherwise.
Also, if the first square of a given row is black, then for a given column M, the square will be black if M is odd, and white if M is even.
Similarly, if the first square is white, then for a column M, the square will be white if M is odd, and black otherwise.
Hope that helps.
EDIT:
try this if you’re a fan of unreadable code:
for i in range(8):
s = ''
for j in range(8):
if (i - j%2) % 2 == 0:
s = s + "#"
else: s = s + 'O'
print s
I also learn JavaScript currently. I was stuck on that for one day. The only thing, that I realize, that if you want to do something useful in JavaScript use loops.
I don't have an idea about complicated coding, but loops could easily do things, that seems at first to be complicated.
Here is my version:
let b = "" //**just create an empty string, because if you won't do that, loop will print out symbols, numbers etc in a single column, but if you use empty string you can in future write symbols inside that string, which allows you to expand string horisontally
let size = 8 //**since loops start at 0 to infinity, you must take it into account,
for (let i = 0; i < size; i++) //**create first loop --> (; ; ). As you can see inside body of loop (the expression, that will be executed until loop is valid) I have just b = b + "#", which means, that my first "for" loop will do looping :) 8 times and will store inside "b" variable THE LAST VALUE (it will be ########), you can check this out in a single sheet (and you will see, that this looping is still going vertically, but the point is that it stores the LAST VALUE)
{ b = b + "#"} //**that is the body of first loop which is described clearly above
for (let a = 0; a < size; a++) //**inside second loop, we create the same routine, and proceed inside that loop with value of "b" from first loop. Notice, that first loop is enclosed {}, so it act independantly.
{
if (a % 2 == 0) //**just condition, which allows us to distribute different strings (rows) of code (I hope you understand what is inside parenthesis
{console.log (" " + b)} //**Since we want to see our chessboard we should print this out onto screen, for that we use "console.log" but again, notice, that here WE DON'T change value of variable "b", we just operate with it, but it will stay the same "########"
else{
console.log (b)} //** And if "if" fails, we will proceed with "########" value, which is NEW origin of "b" variable
}
This is my code:
function pars(str) {
var p = [str.split("(").length - 1, str.split(")").length - 1];
if (p[0] > p[1]) {
for (var i = 0; i < (p[0] - p[1]); i++) {
str += ")";
}
}
return str;
}
It adds parentheses in the end of the string if it's missing.
Examples:
"((asd)s" -> "((asd)s)"
"(((ss)123" -> "(((ss)123))"
How can I make this work for beginning parentheses aswell?
Like:
"))" -> "(())"
")123))" -> "((()123))"
Here is a simple stack-based approach. The full JSFiddle is below as well as list of confirmed test cases.
function pars(s) {
var missedOpen = 0, stack = new Array();
for (i = 0; i < s.length; i++) {
if (s[i] == '(') {
stack.push(s[i]);
} else if (s[i] == ')') {
if (!stack.pop())
missedOpen++;
}
}
return Array(missedOpen + 1).join('(') + s + Array(stack.length + 1).join(')');
}
Confirmed Test cases:
// Target: Expected
var cases = {
'()': '()',
')(': '()()',
'(': '()',
')': '()',
'This)(is))a((test)': '((This)(is))a((test))',
'(A)': '(A)',
')A(': '()A()'
};
See the complete JSFiddle is here.
As noted by a comment, here's a version without the array at all. This should be the most efficient method. All the test cases passed.
function pars(s) {
var missedOpen = 0, missedClosed = 0;
for (i = 0; i < s.length; i++) {
if (s[i] == '(') {
missedClosed++;
} else if (s[i] == ')') {
if (missedClosed > 0)
missedClosed--;
else
missedOpen++;
}
}
return Array(missedOpen + 1).join('(') + s + Array(missedClosed + 1).join(')');
}
You need both the number of unmatched beginning parenthesis and the number of unmatched end parenthesis. Here is a rough solution:
function pars(str) {
var p = 0;
var minp = 0;
for (var i = 0; i < str.length; i++) {
if (str[i] == "(") p++;
if (str[i] == ")") {
p--;
if (p<minp) minp = p;
}
}
for (i = 0; i > minp; i--) {
str = "(" + str;
}
p = p - minp; // If we added any starting parenthesis, we need to end those as well.
for (i = 0; i < p; i++) {
str = str + ")";
}
return str;
}
This one seems to work:
function pars(str){
var pars = [].reduce.call(str, function(acc, letter){
if(letter === '(') { acc.right++;}
else if(letter === ')') {
if(acc.right) {acc.right--;}
else {acc.left++;}//no starting one
}
return acc;
}, {left: 0, right: 0}),
left = pars.left,
right = pars.right;
if(left) { str = new Array(left+1).join('(') + str;}
if(right) { str += new Array(right+1).join(')');}
return str
}
var str = ')))(((fdfd)fd)('
$("#out").html(str + " - " + pars(str))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="out"/>
This is an extremely dirty solution (which works in Firefox for the time being due to repeat function):
function pars(str) {
var t = str;
var n;
while ((n = t.replace(/\([^()]*\)/g, "")) != t) {
t = n;
}
var open = t.match(/\)/g);
var close = t.match(/\(/g);
return "(".repeat(open.length) + str + ")".repeat(close.length);
}
Basically, it matches all pairs of (), then count the number of ( and ), and append ) and ( accordingly.
A clean solution should use a counter to count the number of opening unmatched parentheses. It will discard and count the number of unmatched ). For the number of unmatched (, do as per normal. It will be a one-pass solution, instead of multi-pass solution like the one above.
You can use a variation on the famous stack based bracket matching algorithm here.
The general idea is that you scan the code and push an opening parenthesis onto the stack when you see one, then when you see a closing one you pop the top value from the stack and continue. This will ensure that you have the correct balance.
(123())
// ( - push -> ['(']
// 1 - nothing
// 2 - nothing
// 3 - nothing
// ( - push -> ['(', '(']
// ) - pop -> ['(']
// ) - pop -> []
However, we want to bend the rules slightly.
If we push a closing paren onto the stack, and the stack is empty: we need to add an opening paren to the start of the string
If we arrive at the end of the string and there are still open parens on the stack, then we need to close them.
So the code would look something like this:
function parse(str) {
var stack = []
out = str,
idx = 0,
chr = '';
for(idx = 0; idx < str.length; idx++) {
chr = str[idx];
if(chr === '(') {
stack.push(chr);
}
else if(chr === ')') {
if(stack.length > 0) {
stack.pop();
} else {
out = '(' + out;
}
}
}
for(idx = 0; idx < stack.length; idx++) {
out = out + ')';
}
return out;
}
Bonus: Because of the iterative stack based nature of this algorithm, it will generally be faster than RegEx alternatives.
Just scan the string, counting parens. +1 for (, -1 for ). If the number goes negative, you're missing a ( at the beginning. If, when you are finished, the number is positive, then that's how many )s you need to add at the end.
var addmissingparens = function(s){
var n = 0;
Array.prototype.forEach.call(s, function(c){
if(c === '('){
n += 1;
}
if(c === ')'){
if(n === 0){
s = '(' + s;
}else{
n -= 1;
}
}
});
for(; n>0; n-=1){
s += ')';
}
return s;
};
I have a string with repeated letters. I want letters that are repeated more than once to show only once.
Example input: aaabbbccc
Expected output: abc
I've tried to create the code myself, but so far my function has the following problems:
if the letter doesn't repeat, it's not shown (it should be)
if it's repeated once, it's show only once (i.e. aa shows a - correct)
if it's repeated twice, shows all (i.e. aaa shows aaa - should be a)
if it's repeated 3 times, it shows 6 (if aaaa it shows aaaaaa - should be a)
function unique_char(string) {
var unique = '';
var count = 0;
for (var i = 0; i < string.length; i++) {
for (var j = i+1; j < string.length; j++) {
if (string[i] == string[j]) {
count++;
unique += string[i];
}
}
}
return unique;
}
document.write(unique_char('aaabbbccc'));
The function must be with loop inside a loop; that's why the second for is inside the first.
Fill a Set with the characters and concatenate its unique entries:
function unique(str) {
return String.prototype.concat.call(...new Set(str));
}
console.log(unique('abc')); // "abc"
console.log(unique('abcabc')); // "abc"
Convert it to an array first, then use Josh Mc’s answer at How to get unique values in an array, and rejoin, like so:
var nonUnique = "ababdefegg";
var unique = Array.from(nonUnique).filter(function(item, i, ar){ return ar.indexOf(item) === i; }).join('');
All in one line. :-)
Too late may be but still my version of answer to this post:
function extractUniqCharacters(str){
var temp = {};
for(var oindex=0;oindex<str.length;oindex++){
temp[str.charAt(oindex)] = 0; //Assign any value
}
return Object.keys(temp).join("");
}
You can use a regular expression with a custom replacement function:
function unique_char(string) {
return string.replace(/(.)\1*/g, function(sequence, char) {
if (sequence.length == 1) // if the letter doesn't repeat
return ""; // its not shown
if (sequence.length == 2) // if its repeated once
return char; // its show only once (if aa shows a)
if (sequence.length == 3) // if its repeated twice
return sequence; // shows all(if aaa shows aaa)
if (sequence.length == 4) // if its repeated 3 times
return Array(7).join(char); // it shows 6( if aaaa shows aaaaaa)
// else ???
return sequence;
});
}
Using lodash:
_.uniq('aaabbbccc').join(''); // gives 'abc'
Per the actual question: "if the letter doesn't repeat its not shown"
function unique_char(str)
{
var obj = new Object();
for (var i = 0; i < str.length; i++)
{
var chr = str[i];
if (chr in obj)
{
obj[chr] += 1;
}
else
{
obj[chr] = 1;
}
}
var multiples = [];
for (key in obj)
{
// Remove this test if you just want unique chars
// But still keep the multiples.push(key)
if (obj[key] > 1)
{
multiples.push(key);
}
}
return multiples.join("");
}
var str = "aaabbbccc";
document.write(unique_char(str));
Your problem is that you are adding to unique every time you find the character in string. Really you should probably do something like this (since you specified the answer must be a nested for loop):
function unique_char(string){
var str_length=string.length;
var unique='';
for(var i=0; i<str_length; i++){
var foundIt = false;
for(var j=0; j<unique.length; j++){
if(string[i]==unique[j]){
foundIt = true;
break;
}
}
if(!foundIt){
unique+=string[i];
}
}
return unique;
}
document.write( unique_char('aaabbbccc'))
In this we only add the character found in string to unique if it isn't already there. This is really not an efficient way to do this at all ... but based on your requirements it should work.
I can't run this since I don't have anything handy to run JavaScript in ... but the theory in this method should work.
Try this if duplicate characters have to be displayed once, i.e.,
for i/p: aaabbbccc o/p: abc
var str="aaabbbccc";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 ){
return obj;
}
}
).join("");
//output: "abc"
And try this if only unique characters(String Bombarding Algo) have to be displayed, add another "and" condition to remove the characters which came more than once and display only unique characters, i.e.,
for i/p: aabbbkaha o/p: kh
var str="aabbbkaha";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 && str.lastIndexOf(obj,i-1)==-1){ // another and condition
return obj;
}
}
).join("");
//output: "kh"
<script>
uniqueString = "";
alert("Displays the number of a specific character in user entered string and then finds the number of unique characters:");
function countChar(testString, lookFor) {
var charCounter = 0;
document.write("Looking at this string:<br>");
for (pos = 0; pos < testString.length; pos++) {
if (testString.charAt(pos) == lookFor) {
charCounter += 1;
document.write("<B>" + lookFor + "</B>");
} else
document.write(testString.charAt(pos));
}
document.write("<br><br>");
return charCounter;
}
function findNumberOfUniqueChar(testString) {
var numChar = 0,
uniqueChar = 0;
for (pos = 0; pos < testString.length; pos++) {
var newLookFor = "";
for (pos2 = 0; pos2 <= pos; pos2++) {
if (testString.charAt(pos) == testString.charAt(pos2)) {
numChar += 1;
}
}
if (numChar == 1) {
uniqueChar += 1;
uniqueString = uniqueString + " " + testString.charAt(pos)
}
numChar = 0;
}
return uniqueChar;
}
var testString = prompt("Give me a string of characters to check", "");
var lookFor = "startvalue";
while (lookFor.length > 1) {
if (lookFor != "startvalue")
alert("Please select only one character");
lookFor = prompt(testString + "\n\nWhat should character should I look for?", "");
}
document.write("I found " + countChar(testString, lookFor) + " of the<b> " + lookFor + "</B> character");
document.write("<br><br>I counted the following " + findNumberOfUniqueChar(testString) + " unique character(s):");
document.write("<br>" + uniqueString)
</script>
Here is the simplest function to do that
function remove(text)
{
var unique= "";
for(var i = 0; i < text.length; i++)
{
if(unique.indexOf(text.charAt(i)) < 0)
{
unique += text.charAt(i);
}
}
return unique;
}
The one line solution will be to use Set. const chars = [...new Set(s.split(''))];
If you want to return values in an array, you can use this function below.
const getUniqueChar = (str) => Array.from(str)
.filter((item, index, arr) => arr.slice(index + 1).indexOf(item) === -1);
console.log(getUniqueChar("aaabbbccc"));
Alternatively, you can use the Set constructor.
const getUniqueChar = (str) => new Set(str);
console.log(getUniqueChar("aaabbbccc"));
Here is the simplest function to do that pt. 2
const showUniqChars = (text) => {
let uniqChars = "";
for (const char of text) {
if (!uniqChars.includes(char))
uniqChars += char;
}
return uniqChars;
};
const countUnique = (s1, s2) => new Set(s1 + s2).size
a shorter way based on #le_m answer
let unique=myArray.filter((item,index,array)=>array.indexOf(item)===index)
<script type = "text/javascript">
//Add spaces between menu links
//Placement: Global Header
//Coded by Game
var spaces = "2"; //Edit number of spaces between menu links (1,2 or 3)
var a = document.getElementsByTagName("a");
for (i = 0; i < a.length; i++) {
if (a[i].parentNode.parentNode.className == "menubg" && a[i].innerHTML.match(/Home|new topics|help|search|members|calendar|admin|profile|logout|register|login/i)) {
if (spaces == "1") {
a[i].innerHTML += " ";
}
if (spaces == "2") {
a[i].innerHTML += " ";
}
if (spaces == "3") {
a[i].innerHTML += " ";
}
}
}
</script>
The code above is meant to let the useer add spaces between their menu items. It works fine. But how do I make it to where they can add as many spaces as they would like, instead of limiting them to 3? Maybe somehow they would add their number in the var 'spaces' and the code would multiply   by that numvber?
Just use a loop:
var spaces = 2;
[..]
for(var i = 0; i < spaces; ++ i)
a[i].innerHTML += " ";
I would generate the string in a separate method, like:
function getSpaces(count) {
var spaces = "";
for(var i = 0; i < count; i++) {
spaces += " ";
}
return spaces;
}
and then
a[i].innerHTML = getSpaces(2); //etc
This way you set innerHTML and access the array only one time, and also don't have repeated code.
Avoid innerHTML if you can, since it deletes and recreates the entire content of the element. Prefer appendChild and createTextNode instead. For instance:
a[i].appendChild(document.createTextNode(new Array(spaces + 1).join("\u00A0")));
Why don't you just create a loop inside your if clause that adds an every time you go through the loop?