Related
Map Characters & Sum Ended
Description
You are given a number stored in a variable with the nameN
You are also, given a string, whose length is stored in a variable with the nameK, and the string is stored in a variable with the namestr
You have to map all lower case English characters, starting from the value stored inN.
For example, if the value stored inN = 30, then the mapping of the characters will be as follows
a-30
b-31
c-32
d-33
e-34
f-35
g-36
h-37
i-38
j-39
k-40
l-41
m-42
n-43
o-44
p-45
q-46
r-47
s-48
t-49
u-50
v-51
w-52
x-53
y-54
z-55
Finally, you have to print the sum of all the characters, present in the stringstr, according to the values mapped above
For example, if the value stored instr = "abc", then the required output will be
30 + 31 + 32 = 93, which is the required output
Input
The first line of the input contains the value stored inN
The second line of the input contains the value stored inK
The last line of the input contains the value stored in thestr
Output
Print the sum of characters, according to the values mapped, as shown in the problem statement
Sample Input 1
30
3
abc
Sample Output 1
93
Hint
In the sample test case, the value stored inN = 30, then the mapping of the characters will be as follows
a-30
b-31
c-32
d-33
e-34
f-35
g-36
h-37
i-38
j-39
k-40
l-41
m-42
n-43
o-44
p-45
q-46
r-47
s-48
t-49
u-50
v-51
w-52
x-53
y-54
z-55
Finally, you have to print the sum of all the characters, present in the stringstr, according to the values mapped above
For example, if the value stored instr = "abc", then the required output will be
30 + 31 + 32 = 93, which is the required output
code in image
function mapCharAndSum(n, str) {
let alphabet = [ ...Array(26).keys() ]
let alphabetWithValues = alphabet.map(num => [ String.fromCharCode(97 + num), n + num ])
let values = Array.from(str).map(char => alphabetWithValues.find(item => item[0] === char)[1])
return values.join(' + ') + ' = ' + values.reduce((sum, value) => sum + value)
}
console.log(mapCharAndSum(30, 'abc'))
// Output: 30 + 31 + 32 = 93
console.log(mapCharAndSum(0, 'stackoverflow'))
// Output: 18 + 19 + 0 + 2 + 10 + 14 + 21 + 4 + 17 + 5 + 11 + 14 + 22 = 157
console.log(mapCharAndSum(15, 'stack overflow'))
// Crashes, because ' ' is not part of the alphabet and there is no error handling
I recently made a simple program that can take any letters defined in the map, and replace them with whatever they are assigned to, and vise-versa. For example if you enter welcome to my code it would output as: ˆ´®¬∆©´ ˙∆ ©œ ¬∆≈´
The code is:
<html>
<head>
<script type="text/javascript">
var map = {
"a" : "π",
"b" : "∫",
"c" : "¬",
"d" : "≈",
"e" : "´",
"f" : "Ω",
"g" : "å",
"h" : "√",
"i" : "ç",
"j" : "∂",
"k" : "˚",
"l" : "®",
"m" : "©",
"n" : "†",
"o" : "∆",
"p" : "ø",
"q" : "¨",
"r" : "µ",
"s" : "ƒ",
"t" : "˙",
"u" : "¥",
"v" : "ß",
"w" : "ˆ",
"x" : "∑",
"y" : "œ",
"z" : "˜",
" " : " "
}
function main() {
var input = prompt("Enter a string!");
var encrypted = "";
for(var i = 0; i < input.length; i++){
if(map[input[i]]){
encrypted += map[input[i]];
}
}
document.write(encrypted);
}
main()
</script>
</head>
<body>
</body>
</html>
It can output as long as a string as I want, but it can only output a, b, c... x, y, and z.
Ideally, in order to make it easier, I want to make it detect longer random strings like Mfdshs so I do not have to worry about repeating letters. How can I get it to detect for the capitol letter then all the lowercase letters, and find what letter that is assigned to? Not just the one letter replacement.
What I mean is, is the map would look like this:
var map = {
"a" : "Wgbf",
"b" : "Gvhs",
"c" : "Bgty",
"d" : "Dafd",
"e" : "Ihkj",
"f" : "Hjuk",
"g" : "Byfg",
"h" : "Hynk",
"i" : "Afds",
"j" : "Njio",
"k" : "Yipl",
"l" : "Wetv",
"m" : "Obth",
"n" : "Cbhg",
"o" : "Kolp",
"p" : "Pnya",
"q" : "Fnpd",
"r" : "Buip",
"s" : "Gknp",
"t" : "Lnug",
"u" : "Fuih",
"v" : "Vylp",
"w" : "Fnng",
"x" : "Bhyh",
"y" : "Kkgh",
"z" : "Xnvx",
" " : "Rgyb"
}
And vise-versa.
Simplest solution is shown in code below but it is a bit slow. To make it work values of object map (key) can not include one another. Secret strings with differerent lengths should also work correctly.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript">
var map = {
"a": "Wgbf",
"b": "Gvhs",
"c": "Bgty",
"d": "Dafd",
"e": "Ihkj",
"f": "Hjuk",
"g": "Byfg",
"h": "Hynk",
"i": "Afds",
"j": "Njio",
"k": "Yipl",
"l": "Wetv",
"m": "Obth",
"n": "Cbhg",
"o": "Kolp",
"p": "Pnya",
"q": "Fnpd",
"r": "Buip",
"s": "Gknp",
"t": "Lnug",
"u": "Fuih",
"v": "Vylp",
"w": "Fnng",
"x": "Bhyh",
"y": "Kkgh",
"z": "Xnvx",
" ": "Rgyb"
}
function encode(input){
var encrypted = "";
for(var i = 0; i < input.length; i++){
if(map[input[i]]){
encrypted += map[input[i]];
}
}
return encrypted;
}
function decode(input) {
var enc = ''+input;
var result = '';
do {
for (const key of Object.keys(map)) {
var value = map[key];
if (enc.startsWith(value)) {
result += key;
enc = enc.substr(value.length);
break;
}
}
} while (enc.length > 0);
return result;
}
function encClick(){
var e = encode(document.getElementById("plain").value);
document.getElementById("encodedRes").innerHTML = e;
}
function decClick(){
var e = decode(document.getElementById("encoded").value);
document.getElementById("decodedRes").innerHTML = e;
}
function encPrompt(){
var input = prompt("Enter text", "work ing");
var e = encode(input);
document.getElementById("promptResult").innerHTML = e;
}
function decPrompt(){
var input = prompt("Enter cipher", "FnngKolpBuipYiplRgybAfdsCbhgByfg");
var e = decode(input);
document.getElementById("promptResult").innerHTML = e;
}
</script>
</head>
<body>
<span id="promptResult"></span><br>
<button onclick="encPrompt()">Prompt encode</button><button onclick="decPrompt()">Prompt decode</button><br><br><br>
<input id="plain" type="text" name="" value="work ing" />
<button onclick="encClick()">Encode</button><span id="encodedRes"></span><br><br>
<input id="encoded" type="text" name="" value="FnngKolpBuipYiplRgybAfdsCbhgByfg" />
<button onclick="decClick()">Decode</button><span id="decodedRes"></span>
</body>
</html>
I've edited this answer and added html gui.
If the substitutions are all the same length, you could split the string into 4-character substrings and loop through the resulting array. Finding an implementation on StackOverflow is left as an exercise to the reader. I promise it's out there.
You could also turn the string into an ArrayBuffer and manipulate it as binary data (which is what all real crypto functions do), which would allow you to read 4 bytes as a single Number:
cypherInput = "IhkjBhyhWgbfObthPnyaWetvIhkj"
buffer = new TextEncoder().encode(cypherInput).buffer
words = new Uint32Array(buffer) // reinterpret the buffer
cleartext = words.map(word => /* map each possible 32-bit word to a character */)
If the substitutions are not always 4-character words, you would ideally do this with something a like a Finite-state transducer. JavaScript only does finite state automata for you (i.e. RegEx) so let's work with that (assuming you're only using ASCII letters in your code words):
cypherInput.match(/[A-Z][a-z]+/g)
that will return an array with all the code words. Then there are several ways to produce the cleartext, one of which would be to use replace with a mapping function as the second argument instead of explicitly looping over the matches:
cypherInput.replace(/[A-Z][a-z]+/g, word => /* your mapping function */)
If you want to use non-ASCII in your code, expressing the set of initial letters in a RegEx may become a lot of work rather quickly.
The Problem:
I am willing to get a child element called optionName (you may have a look at the JSON array below to have a clearer idea on what's happening), which requires from me a nested for loop in order to get it. So far, I can get; however, the issue appears when I try to assign the value of that child element to a variable (line 5 in the code section), while I am doing the following additions += i.optionName which makes the value of i.optionName to be ordered (one after the other, similar to an array), the child elements get accumulated which makes the following appear:
Meal : Big Mac
Options :
Normal Ou Maxi ? : Maxi
Choix du boisson : Fanta Orange
Choix des frites : Frites steak house
Category : Menus
Qty : 1
Price : 49
Meal : Chicken McNuggets X6
Options :
//The first block is repeated again which is normal as I used additions +=**
Normal OR Big ? : Big
Choix du boisson : Fanta Orange
Choix des frites : Steak house
Normal OR Big ? : Normal
Choix du boisson : Sprite
Choix des frites : Steak house**
Category : Menus
Qty : 1
Price : 45
In short it's getting worse as much as the parent elements are more than that. You may say why I am doing that, the answer is because the below variable dishes it needs to be a string in this special case!
The current code:
let dishes = '';
let additions = '';
var msg = MessageContent.orderedDishes.forEach(function(element) {
for(var i of element.selectedAdditions){
additions += i.optionName +
' : '
+ i.Name + '\n';
}
dishes +=
'Meal : ' + element.dishName + '\n' +
'Options : \n' + additions + '\n' +
'Category : ' + element.categoryName + '\n' +
'Qty : ' + element.qty+ '\n' +
'Price : ' + element.price + '\n\n';
});
Here is the JSON array I am trying to iterate through:
[{
"objectId": "Kakao0MiRE",
"price": 49,
"dishName": "Big Mac",
"categoryName": "Menus",
"selectedAdditions": [{
"optionName": "Normal Ou Big ?",
"Name": "Big",
"Price": 5
}, {
"optionName": "Drink",
"Name": "Fanta Orange",
"Price": 0
}, {
"optionName": "Fries",
"Name": "Steak house",
"Price": 0
}],
"additionalPrice": 5,
"qty": 1
}, {
"objectId": "kOP90Ld8b9",
"price": 45,
"dishName": "Chicken McNuggets X6",
"categoryName": "Menus",
"selectedAdditions": [{
"optionName": "Normal Ou Maxi ?",
"Name": "Normal",
"Price": 0
}, {
"optionName": "Drink",
"Name": "Sprite",
"Price": 0
}, {
"optionName": "Fries",
"Name": "Frites steak house",
"Price": 0
}],
"additionalPrice": 0,
"qty": 1 }]
Your additions variable is defined declared outside of the call to forEach.
When forEach iterates, you concatenate values to the existing value of additions but never reset it to an empty string for each iteration. This is why your data builds up.
You can resolve this by setting the value of additions to an empty string at the beginning of your forEach callback, or by declaring it inside the forEach so that it starts with an empty array for each iteration. I'd suggest the latter:
let dishes = '';
var msg = MessageContent.orderedDishes.forEach(function(element) {
// declaring your variable here ensures that
// it is empty at the beginning of the iteration
// rather than accumulating over all of them:
let additions = '';
for(var i of element.selectedAdditions){
additions += i.optionName + ' : ' + i.Name + '\n';
}
dishes += 'Meal : ' + element.dishName + '\n'
+ 'Options : \n' + additions + '\n'
+ 'Category : ' + element.categoryName + '\n'
+ 'Qty : ' + element.qty+ '\n'
+ 'Price : ' + element.price + '\n\n';
});
I have a pentagon graph made up with SVG coding. So I made the pentagon with codes like so:
<svg><path cs="100,100" d="M0.5,-62.5 L60.5,-18.5 L37.5,51.5 L-36.5,51.5 L-59.5,-18.5 L0.5,-62.5 M0,0 L0,0"></svg>
Right now, on a graph perspective, the pentagon is showing values of 30 for each side. I am trying to find a way to change the values without always having to go inside PATH CS to change the degree values.
Anyone have an idea, I have been looking it up and found that connecting it with a javascript would be the best case but I have no idea how to write the proper javascript. Could anyone help?
I'm not sure it answers your question. I don't understand what is cs property neither what you really want to modify.
But, here is a way (maybe not the best) to access all your polygon's points by javascript :
You can set all your d points into an array of array, then access each point by modifying it
var p = document.querySelector('path');
var a = [
[ ["M"],[0.5, -62.5] ],
[ ["L"],[60.5, -18.5] ],
[ ["L"],[37.5, 51.5] ],
[ ["L"],[-36.5, 51.5] ],
[ ["L"],[-59.5, -18.5] ],
[ ["L"],[0.5, -62.5] ],
[ ["M"],[0, 0] ],
[ ["L"],[0, 0] ]
];
function draw() {
//loop through the array to join path descriptions with their values
var d = function(){var r = '';for (var i = 0; i < a.length; i++) r += a[i].join('') + " "; return r;};
p.setAttribute('d', d());
}
//EXAMPLes
//Change each value manually then redraw
p.addEventListener('click', function() {
a[1][1][0] ++;
a[2][1][1] --;
draw();
}, false);
//a simple function to change values of set points
function move(point, xy, newValue) {
a[point][1][xy] = newValue;
draw();
}
window.onclick = function() {
move(2, 0, 75);
};
<svg>
<path cs="100,100" d="M0.5,-62.5 L60.5,-18.5 L37.5,51.5 L-36.5,51.5 L-59.5,-18.5 L0.5,-62.5 M0,0 L0,0">
</svg>
If you won't change the structure (number of points) of your polygon, then you can use a simpler structure :
var p = document.querySelector('path');
var a = [
[0.5, -62.5],
[60.5, -18.5],
[37.5, 51.5],
[-36.5, 51.5],
[-59.5, -18.5],
[0.5, -62.5],
[0, 0],
[0, 0]
];
function draw() {
//HardWrite the path descriptions
p.setAttribute('d', "M" + a[0] + " " + "L" + a[1] + " " + "L" + a[2] + " " + "L" + a[3] + " " + "L" + a[4] + " " + "L" + a[5] + " " + "M" + a[6] + " " + "L" + a[7]);
}
//Change each value manually then redraw
p.addEventListener('click', function() {
a[1][0] ++;
draw();
}, false);
//a simple function to change values of set points
function move(point, xy, newValue) {
a[point][xy] = newValue;
draw();
}
window.onclick = function(){ move(2, 0, 75);};
<svg>
<path cs="100,100" d="M0.5,-62.5 L60.5,-18.5 L37.5,51.5 L-36.5,51.5 L-59.5,-18.5 L0.5,-62.5 M0,0 L0,0">
</svg>
I am getting -1 from myarray.indexOf(element) even when element appears to be in myarray.
Here's some code snippets:
function createChangeRecord( old_array, new_array ) {
var nds = new_array.slice(0,new_array.length);
var el, idx;
if (...) {
...
} else if ( old_array.length==new_array.length ) {
for ( var i=0; i<old_array.length; i++ ) {
el = old_array[i];
idx = nds.indexOf(el);
if ( idx!=(-1) ) {
...
} else {
var a = "el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + nds.indexOf(el);
alert( a );
...
}
}
...
}
...
}
The alert shows me that nds does indeed contain el but the alert should only fire when idx==-1, which should only be true when nds does not contain el.
I know I haven't given enough information to determine the specific issue in my case, but maybe someone can tell me some general reasons which might cause this behavior?
Responses to a similar question suggested using jQuery inArray() instead of indexOf, but I want to know why indexOf doesn't work. Others suggested that indexOf is for strings, not arrays, but that's not true from the online docs I can find.
Use
nds.indexOf(parseInt(el,10))
where nds is an array and el is a number (or supposed to be a number)
Edit:
From msdn:
JavaScript is a loosely typed language, which means you do not declare
the data types of variables explicitly. In many cases JavaScript
performs conversions automatically when they are needed. For example,
if you add a number to an item that consists of text (a string), the
number is converted to text.
And I guess such conversion was the reason of indexOf returning -1 because one of your array contained number and other contained string.
For example:
old_array = ["10", "20", "30"];
new_array = [10, 20, 30];
Below is my attempt to answer your questions:
Why indexOf() does not work?
It does work and I guess it worked in your case too.
It returned -1 when el string, e.g "100", was not found in an array of numbers, e.g. nds=[100,200] which is true. Because "100" string is not same as 100 number.
Does indexOf() work with strings, array, etc?
Yes, indexOf() works with array (of number, string, or any object), as well as with string. But you have to make sure to check with same types.
What does parseInt() do?
To avoid unintended comparison of a number with a string, we can use parseInt(), for example parseInt("123", 10) returns the number 123.
The second argument 10 is called radix. A number (from 2 to 36) that represents the numeral system to be used.
Summary:
> "javascript is awesome".indexOf('v')
2
> [10, 20, 30].indexOf("20")
-1
> [10, 20, 30].indexOf(20)
1
> [10, 20, 30].indexOf( parseInt("20", 10) )
1
> typeof (100)
number
> typeof ("100")
string
> typeof( parseInt( "100", 10))
number
> parseInt( "100", 10)
100
> parseInt("100", 2)
4
> parseInt(11.3, 10)
11
> parseInt(11.3, 2)
3
> [10.3, 11.3, 12.3, 11].indexOf( parseInt(11.3, 10) )
3
To see all of above in action:
check the below code snippet but be aware of alert(); and console.log(); when you run it.
function createChangeRecord( old_array, new_array ) {
var nds = new_array.slice( 0, new_array.length ); // this seems to be redundant
var el, idx, msg;
if ( old_array.length == new_array.length ) {
for ( var i=0; i<old_array.length; i++ ) {
el = old_array[i];
idx = nds.indexOf(el);
if ( idx != -1 ) {
msg = "Found: el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + idx + "\n typeof el: " + (typeof el) + "; typepf nds[" + i + "]: " + (typeof nds[i]);
} else {
msg = "Not Found: el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + idx + "\n typeof el: " + (typeof el) + "; typepf nds[" + i + "]: " + (typeof nds[i]);
}
console.log( msg );
alert( msg );
}
}
else {
var err = 'Array lengths are not same';
console.log( err );
alert( err );
}
}
// this will work
var old_array_g = [ 10, 20 ];
var new_array_g = [ 10, 20 ];
createChangeRecord( old_array_g, new_array_g );
// this will not work
var old_array_g = [ "10", "20" ];
var new_array_g = [ 10, 20 ];
createChangeRecord( old_array_g, new_array_g );
// Yes: indesOf works with strings too
var withStrings = "'javascript is awesome'.indexOf('v'): " + "javascript is awesome".indexOf('v');
console.log( withStrings );
alert( withStrings );
// parseInt() returns a number or say integer
var usingParse = "typeof(123): " + typeof( 123 ) + "; typeof( parseInt('123', 10) ): " + typeof ( parseInt('123', 10) ) + "; typeof ('123'): " + typeof('123');
console.log( usingParse );
alert( usingParse );
// parseInt() with base 2
var parseBase2 = "parseInt( '100', 2 ): " + parseInt('100', 2) + "; parseInt( '100' , 10): " + parseInt('100', 10);
console.log( parseBase2 );
alert( parseBase2 );
indexOf does work and does do what you say it does.
For example (to demonstrate from a console):
> a = [1,2,3,4,5,6,7,8];
[1, 2, 3, 4, 5, 6, 7, 8]
> b = a.slice(0,a.length);
[1, 2, 3, 4, 5, 6, 7, 8]
> b.indexOf(a[4])
4
If you're getting this error, it might mean you've mixed up source and destination (the array before the dot is the one being searched), or you have another subtle programming error (like you aren't comparing the array you think you're comparing).
When you use indexOf(value) on an Array, it returns you the index of the value in the array.
> var testArray = ["a","b","c"];
> testArray.indexOf(1)
-1
> testArray.indexOf("b")
1
> testArray.indexOf("c")
2
> testArray = [10,12,3];
> testArray.indexOf(12)
1
You should check what you get from el with a typeof(el)
Taking the top example:
where you have idx=nds.indexOf(el)
replace it with idx=nds.indexOf(''+el+'')
It solved a similar problem for me within the thing I'm working on, but I stumbled on it messing around looking for a solution.
Whether it's stable in all circumstances is something I can't answer.
If your search array contained numbers, and you want to search for items like 2 or "2"
nds = [1, 2, 3, 4, 5];
This works (Add plus)
nds.indexOf(+el)