How to do two symmetric rectangular triangles in JavaScript - javascript

I would like to do something like this with JavaScript. This is my code for creating the first half:
<script>
var numberOfLines = 10;
var str = '*';
var space = '&nbsp';
for (var i = 0; i < numberOfLines; i++){
document.write(str + '<br>');
str = str + "*";
}
</script>
How can I finish it?

You can use Array.join to create your repeated characters. Use a monospaced font to preserve the space width.
document.addEventListener("DOMContentLoaded", function(event) {
var output = "";
var numberOfLines = 10;
for (lineNum = 0; lineNum < numberOfLines; lineNum++) {
output += Array(lineNum + 2).join("*") + Array(((numberOfLines * 2) - (2 * (lineNum))) -1).join(" ") + Array(lineNum + 2).join("*") + "<br>";
}
document.getElementById("result").innerHTML = output;
});
#result {font-family: monospace;}
<div id="result"></div>

This is not perfect but very close:
var numberOfLines = 10;
var str = '*';
var arr = [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "];
var spaces = arr.join("");
for (var i = 0; i < numberOfLines; i++) {
document.write(str + spaces + str + '<br>');
str = str + "*";
arr.splice(-1,1);
arr.splice(-1,1);
spaces = arr.join("");
}

While simple in concept, there's actually a lot to consider when doing this, so lets analyze your code and build from there.
for (var i = 0; i < numberOfLines; i++) {
document.write(str + '<br');
str = str + "*";
}
this will loop through numberOfLines times. It will also output str numberOfLines times. Each loop, you're printing to the document; however, you would like to add a lot of spaces to str as well as a dynamic number of * characters before printing, and each time it will be a different number of spaces. Therefore, you either need to re-build str on each iteration of the loop, or build the entire string str prior to using document.write()
There are many different ways you can accomplish this, I'll go through two:
With a function
You can create a function to build each line. To do this, your function will need to know a few things:
How many lines will there be?
Which line are we currently on?
What character should you use for the visible parts of the triangle?
What character should you use for the invisible parts of the triangle?
So we can start by creating a function, we'll call it generateTriangleLine.
To generate a line, we will want to look at how many of the visible character we want to show, and how many of the invisible. Because there are two sides to this, we will want to output twice as many characters as the current line number:
function generateTriangleLine(visible, invisible, numberOfLines, currentLine) {
// Let's initialize the line so that it has no characters:
var line = '';
// We want to output twice as many characters as there are lines
// So we will loop from 0 to (but not including) numberOfLines * 2
for (var i=0; i<numberOfLines*2; i++) {
if (i<=currentLine || i>=(2*numberOfLines - currentLine - 1)) {
// If we are at the beginning, or the end of the line, we want to output characters.
// We want to add as many visible characters as the line number we are on!
// At the end of the line, 2*numberOfLines = 20. If currentLine starts at 0,
// we will want to draw one visible character, so we need to subtract one from this.
line += visible;
} else {
// If we aren't at the beginning or end, just add the invisible character.
line += invisible;
}
}
// And we want to return the line:
return line;
}
In our code, we can then loop through numberOfLines times, generating each line using our function:
for (var i=0; i<numberOfLines; i++) {
// We'll add a <br> to each line, so that it is drawn appropriately.
document.write(generateTriangleLine('*', '&nbsp', numberOfLines, i) + '<br>');
}
If we run this, we'll get the appropriate output, but it won't necessarily be formatted correctly. This is because most fonts that you read on a daily basis have different widths for each character. The easiest way we can fix this is by wrapping our output in <pre> tags:
document.write('<pre>');
for (var i=0; i<numberOfLines; i++) {
// We'll add a <br> to each line, so that it is drawn appropriately.
document.write(generateTriangleLine('*', '&nbsp', numberOfLines, i) + '<br>');
}
document.write('</pre>');
With a nested for loop to generate the entire output
The other approach we can take is exactly the same as with the function above, but instead of calling a function to generate each line, we generate each line within for loops, and then output everything at the end altogether:
// The first loop will be for each line.
for (var i = 0; i < numberOfLines; i++) {
// The nested for loop will be for each character on each line
// Remember, we have twice as many characters as we do lines
for (var x = 0; x < numberOfLines * 2; x++) {
// Just like we did in the function, we want to check
// if we're at the beginning or the end of the line
// Again, we subtract one from the end so that we still output at least one * on
// the first line.
if (x <= i || x >= (numberOfLines*2) - i - 1) {
// If we are at the beginning or end, output the *
str += "*";
} else {
// Otherwise, output the space
str += space;
}
}
str += '<br>';
}
Once again, we will get the correct output; however, we need to adjust for the letter widths so we can wrap our text in <pre> tags.
Keep in mind, there are numerous ways to solve problems with programming. I've only provided a couple of examples. I would highly encourage you to practice by coming up with your own way of doing this using the skills you learn from the various responses!

Related

Looking for a way to break up a string with multiple \n and turn it into innerHTML

I have been writing JavaScript since yesterday and am brand new at it.
I have a string that I am breaking up and turning into input for a table. The entries are separated by '\n' like 'a\nb', which indicates the need for a new row between a and b.
The current code that I have works for a single instance of '\n', but it quit working when it was back to back entries, specifically "1.1\n2.1\n3.1\n4.1\n".
It has worked with other examples that are comma separated, such as "a,b,c\n1,2,3", "1.1,1.2,1.3,1.4,1.5\n", and "1.1,1.2,1.3,1.4,1.5\n2.1,2.2,2.3,2.4,2.5\n3.1,3.2,3.3,3.4,3.5\n4.1,4.2,4.3,4.4,4.5\n". Because some inputs are comma separated, it must work with those as well as with the input that is separated by '\n'.
My method up to this point has been to split the string into an array, and then search the index of the array to see if it contains the '\n'. If it does, I split the array at the '\n', and splice it with two entries instead of one. I then set a variable indicating that I need to go to the next row, which moves into an if else if right below.
var functionCreate = function (strInput) {
var array = strInput.split(",");
var html = "<table border=1><tr>";
for (var i = 0; i < array.length; i++) {
var newL = false;
if (array[i].indexOf("\n") >= 0) {
newL = true;
newStr = array[i].split("\n");
array.splice(i, 1, newStr[0]);
array.splice(i + 1, 0, newStr[1]);
}
if (newL === true) {
html += "<td>" + array[i] + "</td></tr>";
}
else if (array[i]) {
html += "<td>" + array[i] + "</td>"
}
}
html += "</table>"
document.getElementById('output').innerHTML = html;
What I output currently is:
output: "<table border=\"1\"><tbody><tr><td>1.1</td></tr><tr><td>2.1</td></tr></tbody></table>"
And my expected is:
"<table border=\"1\"><tbody><tr><td>1.1</td></tr><tr><td>2.1</td></tr><tr><td>3.1</td></tr><tr><td>4.1</td></tr></tbody></table>"
The 3.1 and 4.1 are getting cut off, which is understandable because I believe everything trailing the 2.1 is in i + 1 of newStr.
Does anyone have any idea how to get past this? Is there a way to split it at only the first '\n' and run the through the loop again until there are no more newlines?
Change
var array = strInput.split(",");
to
var array = strInput.split("\n");

Insert random string into each instance of whitespace

I'm trying to insert a randomly selected string into each instance of whitespace within another string.
var boom = 'hey there buddy roe';
var space = ' ';
var words = ['cool','rad','tubular','woah', 'noice'];
var random_words = words[Math.floor(Math.random()*words.length)];
for(var i=0; i<boom.length; i++) {
boom.split(' ').join(space + random_words + space);
}
Output comes to:
=> 'hey woah there woah buddy woah roe'
I am randomly selecting an item from the array, but it uses the same word for each instance of whitespace. I want a word randomly generated each time the loop encounters whitespace.
What I want is more like:
=> 'hey cool there noice buddy tubular roe'
Thanks for taking a look.
(This is beta for a Boomhauer twitter bot, excuse the variables / strings 😅)
Maybe you can use regex instead however, you are not seeing the result you desire because you are randomly selecting one word and then replacing all occurrences of a space with it.
The regular expression below replaces occurrences of a space with a dynamic value returned by a callback. You could compare this callback to your for-loop but instead, it's iterating over the spaces found and by doing so you can replace each occurrence with a 'unique' random word.
const boom = 'hey there buddy roe';
const words = ['cool', 'rad', 'tubular', 'woah', 'noice'];
const random = () => Math.floor(Math.random() * words.length);
let replace = boom.replace(/ /g, () => ` ${words[random()]} `);
console.log(replace);
The problem is, that random_words is set to a single word.
Try this instead:
var boom = 'hey there buddy roe';
var words = ['cool','rad','tubular','woah', 'noice'];
boom.replace(/ /g, (space)=> space + words[Math.floor(Math.random()*words.length)] + space);
To get the effect you desire, you need to do the word selecting inside the loop, not outside of it.
for(var i=0; i<boom.length; i++) {
// get a new number every loop
var random_words = words[Math.floor(Math.random()*words.length)];
boom.split(' ').join(space + random_words + space);
}
What is wrong with OP's code: random_words is initialized once only, with a random word. Intention there is, however, to select random word for every whitespace encountered instead.
You can either go with:
for(var i=0; i<boom.length; i++) {
boom.split(' ').join(space + words[Math.floor(Math.random()*words.length)] + space);
}
... or make random_words a function that returns a random word, then call it in your 'boom' loop. With every call, a new word selection will occur.
You need to recalculate the random word on each loop. Right now you have picked out a single random word, stored it in the random_words variable, and you reuse it each time. You could modify your code like this:
var boom = 'hey there buddy roe';
var space = ' ';
var words = ['cool','rad','tubular','woah', 'noice'];
function getRandomWord() {
return words[Math.floor(Math.random()*words.length)];
}
// Uses the same because the value given to join is not recalculated each time:
console.log(boom.split(' ').join(space + getRandomWord() + space));
// You could do this with a standard for loop:
let result = "";
let split = boom.split(' ')
for(var i=0; i<split.length; i++) {
result += split[i] + space;
if (i === split.length - 1) break;
result += getRandomWord() + space;
}
console.log(result);
// Or you can use a reduce:
let otherResult = boom.split(' ').reduce((res, word, index, split) => {
if (index === split.length - 1) return res + space + word;
return res + space + word + space + getRandomWord();
});
console.log(otherResult)

javascript replace string/html from array

I try to create a system replacement for ToolTip.
I already create a version but its not quite optimal (search a better way to do it)
here's a fiddle : http://jsfiddle.net/forX/Lwgrug24/
I create a dictionary (array[key]->value). the array is order by length of the key.
each key is a word or an expression, the value is the definition of the expression.
So, I replace the expression by a span (could/should be a div). The span is used for the tooltip (I use the data-title as tooltip text).
because some word is reused in expression, I need to remove expression already with tooltip (in real life think of father/grandfather, you dont want the definition of father inside grandfather). For replacement I use a ramdom value. That's the worst of this code.
You could make comment or post a new way to do it. maybe someone already did it.
Clarification :
I think my way to do it is wrong by using a string for replacement. Or it could be more secure. How should I do it?
html :
<div class="container">
one two three four five six seven eight nine ten
</div>
javascript :
$(function() {
var list = [
{'k':'one two three four five','v':'First five number.'},
{'k':'four five six seven','v':'middle number.'},
{'k':'six seven eight','v':'second middle number.'},
{'k':'two','v':'number two.'},
{'k':'six','v':'number six.'},
{'k':'ten','v':'number ten.'}
];
$(".container").each(function(){
var replacement = new Array();
for (i = 0; i < list.length; i++) {
var val = list[i];
var rString = randomString(32, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
replacement[rString + "_k"] = htmlEncode(val["k"]);
replacement[rString + "_v"] = htmlEncode(val["v"]);
var re = new RegExp("(" + val["k"] + ")","g");
$(":contains('" + val["k"] + "')",$(this).parent()).html(function(_, html) {
var newItem = '<span class="itemWithDescription" '
+ 'data-title="' + rString + "_v" + '">'
+ rString + "_k"
+ '</span>';
return html.replace(re, newItem);
});
}
for (var k in replacement){
$(this).html($(this).html().replace(k,replacement[k]));
console.log("Key is " + k + ", value is : " + replacement[k]);
}
});
$(document).tooltip({
items:'.itemWithDescription',
tooltipClass:'Tip',
content: function(){
var title = $(this).attr("data-title");
if (title == ""){
title = $(this).attr("title"); //custom tooltips
}
return title;
}
});
});
function randomString(length, chars) {
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))];
return result;
}
function htmlEncode(value){
//create a in-memory div, set it's inner text(which jQuery automatically encodes)
//then grab the encoded contents back out. The div never exists on the page.
return $('<div/>').text(value).html();
}
I added a little thing. on the random function, I put a | and } for every char, its bigger but there's not much chance to have a conflic with an expression.
for (var i = length; i > 0; --i) result += '|' + ( chars[Math.round(Math.random() * (chars.length - 1))] ) + '}' ;
http://jsfiddle.net/forX/Lwgrug24/3/

Splitting string 2 times with javascript

I am trying to break up this string by first splitting it into sections divided by ';'. Then I want to split those sections divided by ','. It is not working though and I am about to break my computer. Could someone please help me figure this out.
You can play around with my jsfiddle if you want... http://jsfiddle.net/ChaZz/
var myString = "Call 1-877-968-7762 to initiate your leave.,-30,0,through;You are eligible to receive 50% pay.,0,365,through;Your leave will be unpaid.,365,0,After;";
var mySplitResult = myString.split(";");
for(i = 0; i < mySplitResult.length -1; i++){
var mySplitResult2 = i.split(",");
for(z = 0; z < mySplitResult2.length -1; i++) {
//document.write("<br /> Element " + i + " = " + mySplitResult[i]);
document.write("<br/>Element" + z + " = " + mySplitResult[z]);
}
}
i is a number, as that's how you defined it.
To split the string, you need to access the i member of the Array.
var mySplitResult2 = mySplitResult[i].split(",");
If I may, if you have to split with character a then character b, the simplest would be :
string.split('a').join('b').split('b')

How do arrays work, behind the scenes?

I'm trying to use basic operators to create my own custom array in JavaScript, I guess.
This book I'm reading, "Eloquent JavaScript", has an exercise in Chapter 1 that asks me to make a pyramid using the "print" function. There's no print function in any of my interpreters, and it doesn't say how to make a print function. So, I don't have a print function, and I'm using alerts.
Here's the code.
var line = "";
var counter = 0;
while (counter < 10) {
line = line + "#";
print(line);
counter = counter + 1;
}
So, I was trying to use alerts, instead:
var line = "";
var counter = 0;
while (counter < 10) {
line = line + "#";
alert(line);
counter = counter + 1;
}
But the alert isn't a triangle. It's a bunch of boxes where the number of pound signs grows each time.
I want to create a string concatenation and then print out the entire result.
This is what I came up with:
string = "";
counter = 0;
signs = "#";
while (counter < 10){
string = string + signs + "\n";
signs = signs + "#";
counter = counter + 1;
}
alert(string);
So, I am just wondering, is there a better way to create arrays without knowing how to create array variable?
Your first pound-sign (tip of pyramid) should be spaced half the length of your base of your pyramid. So, if your base is 10 # signs long, then the top of your pyramid should be spaced out to 4 spaces then print the # sign.
Second, to make a true pyramid, you'll need to print top to bottom so your second row is progressively getting larger. Think in odd numbers:
// Example
Tip: 1 char
2nd row: 3 chars
3rd row: 5 chars
4th row: 7 chars
5th row: 9 chars
6th row: 11 chars
etc
Your newline character is wrong. It should be a \n. If printing to HTML, then use <BR>.
Alternatively, you can use console.log to print your characters.
The newline character is "\n" not "/n". (The "escape" character in general is backslash not forward slash.)
Also, you have a typo that you said sings = ... instead of signs = ...
EDIT: OK, so you've updated your question to correct both of those problems. Regarding your new question:
So, I am just wondering, is there a better way to create arrays
without knowing how to create array variable?
It sounds like you don't really understand what an array variable is: an array is a data structure that allows you to store data items that are selected by indices. Why do you think you need an array for this "pyramid" functionality?
As an aside, your code could be improved using += and ++:
a = a + b; can be abbreviated as a += b;
a = a + 1; can be abbreviated as a++;
This should work
var stringBuilder = "";
counter = 0;
signs = "#";
while (counter < 10){
stringBuilder = stringBuilder + signs + "\n";
signs = signs + "#";
counter = counter + 1;
}
alert(stringBuilder);
Newline is backslash and "n"
You need only one newline character that is within the loop
The following code should work:
string = "";
counter = 0;
signs = "#";
while (counter < 10){
string = string + signs + "\n";
signs = signs + "#";
counter = counter + 1;
}
alert(string);
The major differences are as follows:
You can't include the newline character in the string you are building, otherwise newlines from previous iterations will still be included in subsequent iterations.
The newline character is \n and not /n.
string can start off as being empty, since you will be appending a "#" each time.
This would be another way to do it:
<script>
string = ""; height = 10;
for(i = 1; i <= height; i++){
string += Array(i).join('#') + '<br>';
}
document.write(string);
</script>
Output:
#
##
###
####
#####
######
#######
########
#########
Now with some more modification:
<script>
string = ""; height = 10;
for(i = 1; i <= height; i++){
string += Array(height-i+1).join(' ') + Array(2*i).join('#') + '<br>';
}
document.write(string);
</script>
<style>body{font-family:monospace;}</style>
You get this:
#
###
#####
#######
#########
###########
#############
###############
#################
###################

Categories