Shifting Strings in Javascript - javascript

I'm very new to programming and have been a bit shy when it comes to asking for help....to be honest, I get intimidated by how fast others can figure something out, so for those of you that are in the category, I was hoping you could help me out with a homework question. I Don't know where to begin or write the pseudocode, but if you can guide me or give me a response with details of the why and how, I'd owe you a huge debt. Here's the problem:
we define the following operations on a string:
left shifts: a single circular rotation of the string in which the first character becomes the last
character and all other characters are shifted one index to the left. For example, bcdea becomes
cdeab after a left shift.
right shifts: same as above but in reverse, the last character becomes the first.
the following parameters:
s: string to shift
left shift: integer
right shift: integer
constraints:
1 <= s <= 10^5
0 <= leftshifts, rightshifts <= 10^9
function getShiftedString(s, leftShifts, rightShifts) {
}

function getShiftedString(s, leftShifts, rightShifts) {
s = leftShifting(s, leftShifts);
return rightShifting(s, rightShifts);
}
function leftShifting(s, leftShifts) {
return s.substring(leftShifts) + s.substring(0, leftShifts);
}
function rightShifting(s, rightShifts) {
let l = s.length - rightShifts;
return leftShifting(s, l);
}
try this

Try writing it out in psudo code, that'll help you plan your function.
Think about what you need this function to do, you need it to:
accept a string
shift it to the right x number of times,
shift it to the left y number of times
so maybe your psudo code would look a little like this
s = string, x = left, y = right
convert s to array
for (x times)
q = first element in array
remove first element from array
add q to end of array
for (y times)
q = last element in array
remove last element from array
add q to the beginning of the array
make s string again
return s
Then it's just a simple matter of converting that to code.
Keep in mind, that's just one solution, and there are far better ones out there. definitely do what Neil Lunn said though, and look up string shifting.

Related

Removing a String from an Array, but adding the Number amount back in Javascript

I am trying to create a FEN notation converter for chess. I've decided the best way to go about this is to remove any unnecessary values from the string that I don't need. Here is what it looks like.
rnbqkbnr/pppppppp/8/
These are all strings in my code. I've already found solutions for the end of each file which is represented by the / in the string. But my new problem is taking away the number values and adding back in blank squares to cover them.
When you see a number in FEN, that is essentially how many empty squares on the Chess table there are until another piece. My idea once again, to dumb it down for myself, was to convert these numbers like 8 into this 11111111 a series of numbers representing each square that would have to be empty.
While in practice, I assumed that I would just be able to splice the 8 out and just start filling up that index onwards with 1, this seems to be viable option, but unfortunately is quite buggy when moving the number around to different places.
Would anyone have a better option for this? Yes I know that there is already libraries that accomplish this, but what's the fun of coding if you don't attempt to reinvent the wheel a couple times.
correctFen function - maps over the string looking for any numbers
const correctFen = () => {
newFen.map((pos, index) => {
if (Number(pos) && pos !== '/'){
for (let i = 0; i < Number(pos); i++) {
console.log('firing')
setNewFen(addAfter(newFen, index + i, '1'))
}
}
})
console.log(newFen)
figureOutPos()
}
after looking at this, it's not really removing the index that I'm wanting, could be a problem here, it's adding the 1s after the last /
function addAfter(array, index, newItem) {
return [
...array.slice(0, index),
newItem,
...array.slice(index)
];
}
Looks like you're modifying newFen from the map callback. This would indeed mess up indices because everything after the current index shifts around.
Instead, return the new character(s) from the map callback. In most cases this will be the original character, but if it's a digit, you'll return a string of multiple characters. Then join the array together into a string again.
Something like this:
// Assuming newFen is a string in some outer scope.
const correctFen = () => {
const correctedFen = newFen
// Split the string into an array of single characters.
.split('')
// Apply a function to each character and gather the results in an array.
.map((char, _index) => {
// Try to parse `char` as an integer.
const number = parseInt(char)
if (isNaN(number)) {
// `char` is not a digit. Return the character itself.
return char
} else {
// `char` is a digit. Return a string of that many 1s.
return '1'.repeat(number)
}
})
// Join the array back into a string.
.join('')
setNewFen(correctedFen)
}

How do I replace a letter that is 15 chars ahead of each other?

I am trying to replace each character a user inputs that is 15 letters ahead in the alphabet. For example, if a user inputs the word A, then it would output "P".
the word "AB" would output "PQ" and so on with every word.
I've tried the following code but it is not working. I am thinking a loop may be the answer, but if anyone can think of some better ideas let me know.
alphabetArray = ["abcdefghijklmnopqrstuvwyxz"];
function jumpAhead15(aString){
aString.replace(alphabetArray[0][aString + 15]);
}
jumpAhead15("hi");
You could take the string as iterable and get an array of characters and replace any character by getting the index and the offset, adjusted by the remainder of the length of the alphabet.
The reminder operator % returns the rest of a division:
The remainder operator returns the remainder left over when one operand is divided by a second operand. It always takes the sign of the dividend.
The function is here to keep the index for the getting the character of alphabet in a valid range. For example by taking index 20 and the wanted shift of 15, you get 35 which is not an index of alphabet. by using the remainder operator you get the value of 9 which is the rest of 35 / 26 = 1 rest 9
Then return the character and join the array to a final string.
Method used:
Array.from, which takes two arguments, one iterable or an object with a length property and a mappring function, which is called for every element of the new array. (c is the first parameter of the callback and denotes here a single character)
arrow function as callback for Array.from
function jumpAhead15(aString) {
var alphabet = "abcdefghijklmnopqrstuvwyxz";
return Array
.from(
aString,
c => alphabet[(alphabet.indexOf(c) + 15) % alphabet.length]
)
.join('');
}
console.log(jumpAhead15("hi"));
console.log(jumpAhead15("ab"));
With alphabetArray as above, try:
aString.split("").map(letter => alphabetArray[(alphabetArray.indexOf(letter) + 15) % 26]).join("");
That is: convert the string to an array of 1-letter strings, replace each letter by the one 15 places further along (wrapping if necessary, hence the modulus operator %), then join the letters back together into one string.
If you find the answer from Nina hard to understand, then this one may not be for you either, but here is a function that is built on a more generic letter rotation scheme. It also handles differences in case:
const rotate = (configs) => (str) => str.split('').map(
c => configs.reduce(
(s, [letters, offset]) => {
const idx = letters.indexOf(s);
return idx < 0 ? s : letters[(idx + offset) % letters.length]
},
c
)
).join('')
const by15 = rotate([
[[...'abcdefghijklmnopqrstuvwxyz'], 15],
[[...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'], 15]
])
console.log(by15('ab')) //~> 'pq'
console.log(by15('aB')) //~> 'pQ'
console.log(by15('Hello, world!')) //~> 'Wtaad, ldgas!'
This uses the same basic technique with the modulus operator, modified slightly to return the original character if it's not in our list. We do this for each alphabet supplied, in this case, the upper- and lower-case letters. This only works if the different alphabets have no overlap. We pass the offset together with each alphabet, in case you want to, for instance, rotate digits by 3 and letters by 15. If you didn't want to do this, you could move the offset out of the configs parameter (in which case it might be called alphabets) and make the single offset a second parameter for rotate.
Note the structure: rotate is an arrow function which returns an arrow function. So to get a useful function out of it, you need to call it with the alphabet configuration. The function returned just takes a string and returns the rotated string.
This is not the most efficient solution, as you have to loop through each alphabet, even once you've found it. Since I wouldn't expect it to be used with many alphabets, this seems a good tradeoff for relatively clean code. But one could easily write a version which searched through until it found an alphabet that contained your character and then worked on that one. This is left as an exercise for the reader.

How to determine the time and space complexity of this algorithm?

As I am preparing for an upcoming interview I worked on the string permutations problem. -
Problem statement - Write a function for generating all permutations of an input string.
Here's the solution that I feel is pretty good.
function getPermutations(string) {
// base case
if (string.length <= 1) {
return new Set(string);
}
var allCharsExceptLast = string.slice(0, -1);
var lastChar = string[string.length - 1];
// recursive call: get all possible permutations for all chars except last
var permutationsOfAllCharsExceptLast = getPermutations(allCharsExceptLast);
// put the last char in all possible positions for each of the above permutations
var permutations = new Set();
permutationsOfAllCharsExceptLast.forEach(function(permutationOfAllCharsExceptLast) {
for (var position = 0; position <= allCharsExceptLast.length; position++) {
var permutation = permutationOfAllCharsExceptLast.slice(0, position) + lastChar + permutationOfAllCharsExceptLast.slice(position);
permutations.add(permutation);
}
});
return permutations;
}
Even though I understand the solution (took me a few tries and about a million console logs), recursion confuses the crap out of me. Would someone please break down time and space complexity for me?
Let's think about the process. Say our String is n characters long. First, we must pass over each character in the string (n operations), and then for each character, recursively generate a permutation of the other n-1 characters in the string, from which we will for each 2nd character, recursively generate a permuation of n-2 chars in the string, and so on... until there is only 1 char left. To calculate the total time complexity, we multiply all these terms together (n * (n-1) * (n-2) * ... * 1 = n!), getting a time complexity in Big-O notation of O(n!).
To think about why we multiply them, we can think of the much simpler problem as follows: How many different permutations are there of clothes to wear if we have 2 pairs of pants and 3 shirts. The answer is clearly six, and we get this by noting that for each shirt, we have two choices for pants, so we take the number of shirts and multiply by the number of pants.
We can translate this example to a easy string, say the word "cat". To get every permutation, your code first chooses a character (it does not matter what order you choose the characters in, so I will first choose the 'c'), and then find the permutations in the remaining string, in this case "at". It is trivial that the only two permuations of this are "at" and "ta", so we add the strings "atc" and "tac" to overall permutations. Next, we take out 'a', and the remaining String is "ct", from which the permutations are "ct" and "tc". Thus, we add "cta" and "tca" to our overall permutations. Finally, doing the same thing when we take out 't', we end up with "ca" and "ac" as our remaining permutations, so we add "cat" and "act" to our overall permuations, and we are done. Notice that in this case they are all unique, but if a letter had been duplicated, (such as in "wow"), then your algorithm will double count, which is okay, as this not really necessary to account for.
Anyway, hope this helps, please leave a comment if you have an additional question.

Finding an element in an array

4,5,6,7];
pin=3;
We got to search pin in hay.
Conventionally we loop through hay and check for pin( assume there is no native function called array.indexOf ).
How about,
hay=hay.join(",");
pin=","+pin+",";
index=hay.indexOf(pin);
Any Suggestions please?
Consider hay of [2,3,4] and a pin of 2... you'll be looking for ",2," in a string "2,3,4". Now you could add commas to the start and end of hay as well, but it's a bit ugly, isn't it?
There's then the problem of strings having variable lengths: consider an array of [1,222222,3,4]. When you look for 3, you'll end up with an inappropriate index because of the length of "222222". (Even in the case of only single digit values, you'll need to divide by 3.)
You've then potentially got problems when you start moving from integers to decimal values, which may be formatted differently in different cultures - possibly using a comma as the decimal separator. I don't know whether JavaScript uses the culture-specific separator by default, but that's part of the problem - you're suddenly having to consider aspects of the language/platform which have nothing to do with the task at hand.
Generally speaking, converting data into a string format in order to do something which doesn't really depend on the string format is a bad idea. It would be better to write a general-purpose indexOf method to perform the looping for you. (I'd be surprised if such a method didn't already exist, to be honest, but it's easy enough to write once and reuse if you need to.)
Heck, assume there is no string indexOf, either.
var A=[11,7,9,1,17,13,19,18,10,6,3,8,2,5,4,14,20,15,16,12],
L=A.length, n=3;
while(L>-1 && A[--L]!==n);
alert(L)
You don't need to use string in the middle, you can just loop through your array, if I understand your question right.
var hay = [1, 2, 3, 'Whoa', 'wheee', 5, 'needle'], needle = 'needle';
for ( var i = 0, len = hay.length; i < len; i += 1 ) {
if ( hay[ i ] === needle ) {
alert( "hay’s element number " + i + " is the needle!" );
break;
}
}

Chunk a string every odd and even position

I know nothing about javascript.
Assuming the string "3005600008000", I need to find a way to multiply all the digits in the odd numbered positions by 2 and the digits in the even numbered positions by 1.
This pseudo code I wrote outputs (I think) TRUE for the odd numbers (i.e. "0"),
var camid;
var LN= camid.length;
var mychar = camid.charAt(LN%2);
var arr = new Array(camid);
for(var i=0; i<arr.length; i++) {
var value = arr[i]%2;
Alert(i =" "+value);
}
I am not sure this is right: I don't believe it's chunking/splitting the string at odd (And later even) positions.
How do I that? Can you please provide some hints?
/=================================================/
My goal is to implement in a web page a validation routine for a smartcard id number.
The logic I am trying to implement is as follows:
· 1) Starting from the left, multiply all the digits in the odd numbered positions by 2 and the digits in the even numbered positions by 1.
· 2) If the result of a multiplication of a single digit by 2 results in a two-digit number (say "7 x 2 = 14"), add the digits of the result together to produce a new single-digit result ("1+4=5").
· 3) Add all single-digit results together.
· 4) The check digit is the amount you must add to this result in order to reach the next highest multiple of ten. For instance, if the sum in step #3 is 22, to reach the next highest multiple of 10 (which is 30) you must add 8 to 22. Thus the check digit is 8.
That is the whole idea. Google searches on smartcard id validation returned nothing and I am beginning to think this is overkill to do this in Javascript...
Any input welcome.
var theArray = camid.split(''); // create an array entry for each digit in camid
var size = theArray.length, i, eachValue;
for(i = 0; i < size; i++) { // iterate over each digit
eachValue = parseInt(theArray[i], 10); // test each string digit for an integer
if(!isNaN(eachValue)) {
alert((eachValue % 2) ? eachValue * 2 : eachValue); // if mod outputs 1 / true (due to odd number) multiply the value by 2. If mod outputs 0 / false output value
}
}
I discovered that what I am trying to do is called a Luhn validation.
I found an algorithm right here.
http://sites.google.com/site/abapexamples/javascript/luhn-validation
Thanks for taking the time to help me out. Much appreciated.
It looks like you might be building to a Luhn validation. If so, notice that you need to count odd/even from the RIGHT not the left of the string.

Categories

Resources