Reverse a string using two-pointer method in JS - javascript

I am trying to reverse a string. I am aware of .reverse function and other methods in Js to do so, but i wanted to do it this two-pointer method.
The problem is the string is not getting updated. Is there anything i am not aware of strings. Whats wrong here ?
function reverseString(s) {
let lengthOfStr = 0;
if ((s.length - 1) % 2 == 0) {
lengthOfStr = (s.length - 1) / 2
} else {
lengthOfStr = ((s.length - 1) / 2) + 1;
}
let strLengthLast = s.length - 1;
for (let i = 0; i <= lengthOfStr; i++) {
let pt1 = s[i];
let pt2 = s[strLengthLast];
s[i] = pt2;
s[strLengthLast] = pt1;
console.log('----', s[i], s[strLengthLast]);
strLengthLast--;
}
return s;
}
console.log(reverseString('hello'));

Unlike in C, strings in JavaScript are immutable, so you can't update them by indexing into them. Example:
let s = 'abc';
s[1] = 'd';
console.log(s); // prints abc, not adc
You'd need to do something more long-winded in place of s[i] = pt2;, like s = s.substring(0, i) + pt2 + s.substring(i + 1);, and similarly for s[strLengthLast] = pt1; (or combine them into one expression with 3 calls to substring).

I'm not sure why it doesnt update the string, but if you handle the replacement as an array/list it works as follows:
function reverseString(s) {
let lengthOfStr = 0;
sSplit = s.split("");
if ((s.length - 1) % 2 === 0) {
lengthOfStr = (s.length - 1) / 2
}
else {
lengthOfStr = ((s.length - 1) / 2) + 1;
}
let strLengthLast = s.length - 1;
for (let i = 0; i <= lengthOfStr; i++) {
let pt1 = sSplit[i];
let pt2 = sSplit[strLengthLast];
sSplit[i] = pt2;
sSplit[strLengthLast] = pt1;
console.log('----', sSplit[i], sSplit[strLengthLast],sSplit);
strLengthLast--;
}
return sSplit.join("");
}
console.log(reverseString('Hello'));
returns: Hello => olleH

As covered in comment, answers and documentation, strings are immutable in JavaScript.
The ability to apparently assign a property value to a primitive string value results from early JavaScript engine design that temporarily created a String object from primitive strings when calling a String.prototype method on the primitive. While assigning a property to the temporary object didn't error, it was useless since the object was discarded between calling the String method and resuming execution of user code.
The good news is that this has been fixed. Putting
"use strict";
at the beginning of a JavaScript file or function body causes the compiler to generate a syntax error that primitive string "properties" are read-only.
There are many ways of writing a function to reverse strings without calling String.prototype.reverse. Here's another example
function strReverse(str) {
"use strict";
let rev = [];
for( let i = str.length; i--;) {
rev.push(str[i]);
}
return rev.join('');
}
console.log( strReverse("Yellow") );
console.log( strReverse("").length);

I tried that way, hopefully might be helpful for someone.
const input = 'hello'; /*input data*/
const inputArray = [...input]; /*convert input data to char array*/
function reverseString(inputArray) {
let i = 0;
let j = inputArray.length -1 ;
while(i < j ) {
const temp = inputArray[i];
inputArray[i] = inputArray[j];
inputArray[j] = temp;
i++;
j--;
}
};
reverseString(inputArray);
console.log(inputArray)
const finalResult = inputArray.join("");
console.log(finalResult);
Thanks.

Related

Javascript program has something wrong ,I don't know why the length of log is not 10?

Javascript program has something wrong ,I don't know why the length of log is not 10?
the input s :
const s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
var findRepeatedDnaSequences = function(s) {
var set = new Set()
var seqSet = new Set()
for (let i = 0; i < s.length - 11; i++) {
let sub = s.substr(i, i + 10)
console.log(sub)
if (set.has(sub)) {
seqSet.add(sub)
} else {
set.add(sub)
}
}
return Array.from(set)
};
findRepeatedDnaSequences(s)
the console result:Javascript program has something wrong ,I don't know why the length of log is not 10?
AAAAACCCCC
AAAACCCCCAA
AAACCCCCAAAA
AACCCCCAAAAAC
ACCCCCAAAAACCC
CCCCCAAAAACCCCC
CCCCAAAAACCCCCCA
CCCAAAAACCCCCCAAA
CCAAAAACCCCCCAAAAA
CAAAAACCCCCCAAAAAGG
AAAAACCCCCCAAAAAGGGT
AAAACCCCCCAAAAAGGGTTT
AAACCCCCCAAAAAGGGTTT
AACCCCCCAAAAAGGGTTT
ACCCCCCAAAAAGGGTTT
CCCCCCAAAAAGGGTTT
CCCCCAAAAAGGGTTT
CCCCAAAAAGGGTTT
CCCAAAAAGGGTTT
CCAAAAAGGGTTT
CAAAAAGGGTTT
The arguments you're giving to substr() are appropriate for substring(). Since substr() is deprecated, you should just change to substring() and you'll get the results you want.
const s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
var findRepeatedDnaSequences = function(s) {
var set = new Set()
var seqSet = new Set()
for (let i = 0; i < s.length - 11; i++) {
let sub = s.substring(i, i + 10)
console.log(sub)
if (set.has(sub)) {
seqSet.add(sub)
} else {
set.add(sub)
}
}
return Array.from(set)
};
findRepeatedDnaSequences(s)
substr takes a starting offset and a length. You should call just .substr(i, 10).
const s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
var findRepeatedDnaSequences = function(s) {
var set = new Set()
var seqSet = new Set()
for (let i = 0; i < s.length - 11; i++) {
let sub = s.substr(i, 10)
console.log(sub)
if (set.has(sub)) {
seqSet.add(sub)
} else {
set.add(sub)
}
}
return Array.from(set)
};
findRepeatedDnaSequences(s)
in js there are 2 functions:
substr():
The substr() method returns a portion of the string, starting at the
specified index and extending for a given number of characters
afterwards.
substring().
The substring() method returns the part of the string between the
start and end indexes, or to the end of the string.
you are using the 1st one, and from your question, you are expecting the 2nd.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring.

Return multiple strings from function based on variable number

I have a string
var str = 'string'
I have a multiplier
var mult = 3
I want to return stringstringstring
The mult will change. Basically mult is kind of like a power but this is a string not a number. And I need to return multiple strings. I'm thinking of looping where mult = the number of times to loop and each would conceptually 'push' but I don't want an array or something like =+ but not a number. I'm thinking I could have the output push to an array the number of times = to mult, and then join the array - but I don't know if join is possible without a delimiter. I'm new at javascript and the below doesn't work but it's what I'm thinking. There's also no ability to input a function in the place I'm running javascript and also no libraries.
var loop = {
var str = 'string'
var arr = [];
var mult = 3;
var i = 0
for (i = 0, mult-1, i++) {
arr.push('string'[i]);
}
}
var finalString = arr.join(''); // I don't know how to get it out of an object first before joining
Not sure if what I want is ridiculous or if it's at all possible
You mean something like below,
var str = 'string'
var mult = 3
var str2 = ''
for(i = 0; i < mult; i++) {
str2 += str
}
console.log(str2)
var str = 'string'
var mult = 3;
var sol =""
while(mult--) {
sol +=str;
}
console.log(sol)
Using resusable function:
const concatStr= (str, mult)=>{
var sol =""
while(mult--) {
sol +=str;
}
console.log(sol)
}
concatStr("string",3)
Using the inbuilt Array.from method:
var str = "string"
var mult = 3
var sol = Array.from({length: mult}, ()=> str).join("")
console.log(sol)
function concatString(str, mult) {
var result = ''
for(i = 0; i < mult; i++) {
result = result.concat(str);
}
return result;
}
const value = concatString('string', 3);
console.log(value);
Also you can use array inbuilt methods,
const mult = 3, displayVal = 'str';
Array(mult).fill(displayVal).join('');
// the string object has a repeat method
console.log('string'.repeat(3));

function that randomly sorts through letters and changes them not working

I am making a javascript function that will input a string, and output a "spongebob mocking text"
basically, you input "Hello, this is a message to the world" and you would get "HeLlO, ThIS iS a MeSsAGe tO tHE wORlD"
basically, randomly decide wheather to capitalize a letter or not. I made a function which i thought would do that, but it didn't work. here is the code that I tested in the js console:
function memify(input) { // function called memify()
var il = input.length; // gets the length of the input
var newinput = input; // creates a new variable that will be changed from input.
for (var i=0;i>il;i++) {
var rng = Math.floor((Math.random()*2)); // random number between 0 and 1. 0 = upper 1 = lower
if (rng === 0) {
newinput.charAt(i).toUpperCase();
}
else {
newinput.charAt(i).toLowerCase();
}
}
return newinput;
}
var text = prompt();
var textmeme = memify(text);
alert(textmeme);
Why is this not working? Do I have an error in my code? Any help will be greatly appreciated.
When you do
newinput.charAt(i).toUpperCase();
you're creating a new uppercase character, but you aren't doing anything with it; it's just an unused expression, so there's no visible change. Primitives (including strings) are immutable - you should explicitly reassign a string to something else (eg newString += newinput.charAt(i).toUpperCase();) to see an effect.
You also need to use
for (var i = 0; i < il; i++) {
// ^
instead of
for (var i = 0; i > il; i++) {
// ^
else, no iterations will run at all.
function memify(input) { // function called memify()
var il = input.length; // gets the length of the input
let changedStr = '';
for (var i = 0; i < il; i++) {
var rng = Math.floor((Math.random() * 2)); // random number between 0 and 1. 0 = upper 1 = lower
if (rng === 0) {
changedStr += input.charAt(i).toUpperCase();
} else {
changedStr += input.charAt(i).toLowerCase();
}
}
return changedStr;
}
var text = prompt();
var textmeme = memify(text);
console.log(textmeme);
Another option, using .map, which looks much cleaner IMO:
const memify = input => [...input]
.map(char => Math.random() < 0.5 ? char.toUpperCase() : char.toLowerCase())
.join('');
console.log(memify(prompt()));
Or more concise, safer and generally better solution :). It does not require for loop, checking length of string and other error prone stuff.
function memify(input) {
var rng = () => Math.random() > 0.5;
var res = input.split('').map( letter =>
rng() ? letter.toUpperCase() : letter.toLowerCase()
).join('');
return res;
}
var textmeme = memify("Hello World");
console.log(textmeme);
Please up-vote if it was helpful :)

Find minimum concat number of two strings

Alice has two strings, initial and goal. She can remove some number of characters from initial, which will give her a subsequence of that string. A string with no deletions is still considered a subsequence of itself. Given these two strings, can you find the minimum number of subsequences of initial that, when appended together, will form goal?
Functions
minimumConcat() has two parameters:
initial: the source string that you will get subsequences from
goal: the target string that needs to be formed
Input Format
For some of our templates, we have handled parsing for you. If we do not provide you a parsing function, you will need to parse the input directly. In this problem, our input format is as follows:
The first line is the initial String that we will be generating subsequences from
The second line is the goal String to form
Here is an example of the raw input:
abc
bcbac
Expected Output
Return the number of minimum possible subsequences of initial that can be appended together to form goal.
If there are no possible solutions, return -1.
Example minimumConcat() Input #1
initial: "xyz"
goal: "xzyxz"
Output: 3
function minimumConcat(initial, goal) {
//Put your code here.
return 0;
}
Loop the initial string array to form the goal string array.
function minimumConcat(initial, goal) {
initial = initial.split('');
goal = goal.split('');
let res,count=0;
while(true){
if(goal.length > 0){
res = checkChar(initial,goal);
if(false === res){
return -1;
}
}else{
return count;
}
goal = res;
count++;
}
}
function checkChar(initial,goal){
let started = false;
let foundIndex = 0;
for(let i=0; i<initial.length; i++){
if(initial[i] == goal[foundIndex]){
started = true;
foundIndex++;
}
}
if(started){
return goal.slice(foundIndex);
}else{
return false;
}
}
console.log(minimumConcat('abc','bcbac'));
Here you go!
function minimumConcat(initial, goal) {
let result = 0;
let pattern = '';
let count1 = Array.apply(null, Array(26)).map(Number.prototype.valueOf, 0);
let count2 = Array.apply(null, Array(26)).map(Number.prototype.valueOf, 0);
initial.split('').forEach(c => {
pattern = pattern + c
});
pattern = "^[" + pattern + "]*$";
if (!RegExp(pattern).test(goal)) return -1;
for (let i = 0; i < initial.length; i++) {
count1[initial.charCodeAt(i) - 97]++;
}
for (let i = 0; i < goal.length; i++) {
count2[goal.charCodeAt(i) - 97]++;
}
for (let i = 0; i < 26; i++) {
result += Math.abs(count1[i] - count2[i]);
}
return result;
}
console.log(minimumConcat("abc", "bcbac"));
Since this looks like homework I won't give the solution right away, instead here is a suggestion on how to solve it:
I think the hardest part is finding all the sub-strings if you are using Python that's simplified by itertools as mentioned here.
Edit, I didn't notice the javascript tag, you can get the substring set, without a library, with a couple of for loops.
After having all combinations from initial you can sort them to have the longest first. And then go one by one removing them from goal. Counting every time you remove. If, after iterating over all sub-strings, goal is not an empty string then no subsequence of initial can construct goal.
This answers your question using Java
public static int minimumConcat(String initial, String goal) {
HashSet<Character> set = new HashSet<>();
for(char c : initial.toCharArray()) set.add(c);
for(char c : goal.toCharArray()) {
if(!set.contains(c)) return -1;
}
int j = 0, result = 0;
for(int i = 0; i < goal.length();) {
char c = goal.charAt(i);
while(j < initial.length() && initial.charAt(j) != c) j++;
if(j == initial.length()) {
j = 0;
result++;
} else {
j++;
i++;
}
}
result++;
return result;
}
Here is what I've done with python
def minimumConcat(initial, goal):
#verify that goal has all character of initial
res = 0
for i in goal:
if i in initial:
pass
else:
res=-1;
if res != -1:
while goal!="":
a = removefirstGreatestSubstring(initial,goal)
goal=a["goal"];
if a["has"] ==True :
res=res+1
#find the greatest concat
print(res)
def removefirstGreatestSubstring(initial,goal):
has_subtring = False
start = 0
for car in initial:
if car == goal[start]:
has_subtring= True
start = start+1
finalgoal=goal[start:]
return {"goal": finalgoal, "has":has_subtring}
initial = "abc"
goal = "bcbac"
b = minimumConcat(initial, goal)
I've made it using a different approach with regular expressions.
Here a clean version of the code:
"use strict";
// Solution:
function minimumConcat(initial, goal) {
let result = -1;
let goal_slice = goal;
let exp = "", sub = "";
let initial_concat = "";
let matches = 0, count = 0;
let initial_arr = initial.split('');
for(let i = 0 ; i<initial_arr.length; i++){
for(let j = initial_arr.length ; j>i+1; j--){
sub = initial.slice(i,j);
exp = new RegExp(sub,"ig");
matches = (goal_slice.match(exp) || []).length;
if(matches>=1) {
count +=matches;
initial_concat+=sub.repeat(matches);
goal_slice = goal_slice.slice((goal_slice.lastIndexOf(sub)+sub.length));
}
}
}
result = (initial_concat==goal)? count : result;
return result;
}
// Test cases:
let test_cases = [
{initial:"abc", goal: "abcbc"}, // expected result 2
{initial:"abc", goal: "acdbc"}, // expected result -1
{initial:"bcx", goal: "bcbcbc"}, // expected result 3
{initial:"xyz", goal: "xyyz"}, // expected result 2
]
// Running the tests:
test_cases.forEach(function(item,index){
console.log(minimumConcat(item.initial, item.goal));
});
Also, I've included a debug flag to turn on/off console.log messages in order to anybody could easily understand what is happening on each iteration cycle.
"use strict";
// Shwitch for debugging:
const debug = true;
// Solution:
function minimumConcat(initial, goal) {
let exp = "";
let sub = "";
let match = 0;
let count = 0;
let result = -1;
let goal_slice = goal;
let initial_concat = "";
let initial_arr = initial.split('');
for(let i = 0 ; i<initial_arr.length; i++){
for(let j = initial_arr.length ; j>i+1; j--){
sub = initial.slice(i,j);
exp = new RegExp(sub,"ig");
match = (goal_slice.match(exp) || []).length;
if(match>=1) {
count +=match;
initial_concat+=sub.repeat(match);
goal_slice = goal_slice.slice((goal_slice.lastIndexOf(sub)+sub.length));
}
if(debug){
console.log("-----------------------------");
console.log(" i:", i, " - j:", j);
console.log(" exp:", exp);
console.log(" goal:", goal);
console.log(" goal_slice:", goal_slice);
console.log(" match:",match);
}
}
}
result = (initial_concat==goal)? count : result;
if(debug){
console.log("---RESULTS:--------------------------");
console.log("count:",count);
console.log("goal vs initial_concat: ", goal, " - ", initial_concat);
console.log("result: ", result);
}
return result;
}
// Test cases:
let test_cases = [
{initial:"abc", goal: "abcbc"}, // expected result 2
{initial:"abc", goal: "acdbc"}, // expected result -1
{initial:"bcx", goal: "bcbcbc"}, // expected result 3
{initial:"xyz", goal: "xyyz"}, // expected result 2
]
// Running the tests:
test_cases.forEach(function(item,index){
if(debug){
console.log("-----------------------------");
console.log("TEST CASE #",index,":");
console.table(item);
}
minimumConcat(item.initial, item.goal);
});
here is in php
public function index()
{
$init="abc";
$goal="abacabacabacacb";
$res=$this->minimum($init,$goal);
}
public function check($inital,$goal){
$inital=str_split( $inital);
$goal=str_split( $goal);
for($i=0;$i<sizeof($goal);$i++){
if(!in_array($goal[$i],$inital)){
return -1;
}
}
return 0;
}
public function minimum($inital,$goal){
$res=$this->check($inital,$goal);
if($res==-1){
return -1;
}
$counter=0;
$c=0;
$inital=str_split( $inital);
$goal=str_split( $goal);
for($i=0;$i<sizeof($goal);$i++){
for($j=0;$j<sizeof($inital);$j++){
if(($i+$c)<sizeof($goal)){
echo " ".$i." > ".$j." > ".$c." /// ";
if($goal[$i+$c]==$inital[$j]){
$c+=1;
}
}
}
$counter+=1;
if(($i+$c)>=sizeof($goal)){
break;
}
$c=$c-1;
}
return $counter;
}
Here is my python solution
def check_char(initial, goal):
N = len(initial)
started = False
found_index = 0
for i in range(N):
if (initial[i] == goal[found_index]):
started = True
found_index += 1
if(started):
return goal[found_index:]
else:
return '-'
def minimumConcat(initial, goal):
res = 0
count = 0
while(True):
if( len(goal) > 0 ):
res = check_char(initial, goal)
if(res == '-'):
print(-1)
break;
else:
print(count)
break;
goal = res
count += 1
initial = input()
goal = input()
minimumConcat(initial, goal)

What is the equivalent of C++ std::unordered_map<char, int> in Javascript?

So I am trying to map the number of times a char appears in a string. I know that in C++ it would be.
std::string str = "AbBAaaaa";
std::unordered_map<char, int> myMap;
for(auto i = str)
{
++mymap[i];
}
How would I translate this to JavaScript?
I would reduce the string into an object indexed by character. The function passed to reduce is called for each element in the input, where the first argument (the a) is the accumulator, which is either the initial value ({} here) or what the last iteration returned. The second argument (the char) is the current character being iterated over.
const str = "AbBAaaaa";
const charCounts = Array.prototype.reduce.call(str, (a, char) => {
a[char] = (a[char] || 0) + 1;
return a;
}, {});
console.log(charCounts);
You could also use
const charCounts = [...str].reduce((a, char) => // ...
which is shorter and probably a bit easier to understand at a glance, but unnecessarily creates an intermediate array from the str.
The imperative version of this, with a for loop, would look like:
const str = "AbBAaaaa";
const charCounts = {};
for (let i = 0; i < str.length; i++) {
const char = str[i];
charCounts[char] = (charCounts[char] || 0) + 1;
}
console.log(charCounts);
Javascript already has map and you can achieve same result of your C++ app as shown in this snippet
function charOccurances(str) {
var myMap = {};
if(str.length!==0){
for (let i = 0; i < str.length; i++) {
myMap[str[i]] = (myMap[str[i]] || 0) + 1;
}
}
return myMap;
}
const str = "AbABaaaa";
console.log(charOccurances(str));

Categories