Understanding a Javascript Decrypter - javascript

I'm looking at a codewars solution for decrypting a set of numbers.
For example,
012345 => 304152 => 135024
So the 012 would take on every other index starting from 1, and 345 would take on every other index starting from 0. The solution is written as...
const decrypt = (s, n) => {
if (!s) return s;
const l = Math.floor(s.length / 2);
for (let i = 0; i < n; i++) {
let x = s.slice(0, l), y = s.slice(l);
s = '';
for (let j = 0; j < l + 1; j++)
s += (y[j] ? y[j] : '') + (x[j] ? x[j] : '');
}
return s;
}
From my understanding, the coder sliced the number into two halves, and the for loop runs through the digits in the first half and also the last digits in the second half. I'm not sure why there needs to be a ternary operator there and what conditions it's looking for. I'd appreciate any help!
I tried doing the s+= y[j] + x[j] and thought it would decrypt. I get the right answer, but there's an extra undefined statement at the end of the solution.

Related

What is the difference between "hello".indexOf("") and "hello".indexOf("h")? [duplicate]

why this is happening in javascript?
'abc'.indexOf('a'); //0
'abc'.indexOf(''); //0
while in the other falsy values, the value is -1:
'abc'.indexOf(); //-1
'abc'.indexOf(false); //-1
'abc'.indexOf(undefined); //-1
i have seen also those questions:
Q1 didnt understand the answer in depth.
Q2 in java and not javascript.
The answer, fundamentally, is: Because that's how the function is specified to behave. And it makes sense, from a certain perspective.
The main bit related to returning 0 when you search for an empty string is this:
Return the smallest possible integer k not smaller than start such that k + searchLen is not greater than len, and for all nonnegative integers j less than searchLen, the code unit at index k + j within S is the same as the code unit at index j within searchStr; but if there is no such integer k, return the value -1.
Since the length of the search string is 0, both halves of that "and" are satisfied by k = 0: k + searchLen is not greater than the length of the string, and for all nonnegative integers less than the search length (there are zero), the code points match.
Or roughly speaking, in code:
function indexOf(searchString, position = 0) {
let s = String(this);
let searchStr = String(searchString);
let len = s.length;
let start = Math.min(Math.max(position, 0), len);
let searchLen = searchStr.length;
let k = 0;
while (k + searchLen <= len) {
if (s.substring(k, k + searchLen) === searchStr) {
break;
}
++k;
}
const found = k + searchLen <= len;
return found ? k : -1;
}
Since k + searchLen (0) is <= len (0), k (0)` is returned.
Live Example:
function indexOf(searchString, position = 0) {
let s = String(this);
let searchStr = String(searchString);
let len = s.length;
let start = Math.min(Math.max(position, 0), len);
let searchLen = searchStr.length;
let k = 0;
while (k + searchLen <= len) {
if (s.substring(k, k + searchLen) === searchStr) {
break;
}
++k;
}
const found = k + searchLen <= len;
return found ? k : -1;
}
console.log(indexOf.call("abcd", ""));
Another way to look at it is this answer related to Java...or to life in general.
Re your question passing in non-strings: One of the first steps is:
Let searchStr be ? ToString(searchString).
...which is let searchStr = String(searchString); in my rough code above. That means false becomes "false" and undefined becomes "undefined". "abc" doesn't contain either "false" or "undefined".

Result for passing empty string to indexOf() and lastIndexOf() for string containing text [duplicate]

why this is happening in javascript?
'abc'.indexOf('a'); //0
'abc'.indexOf(''); //0
while in the other falsy values, the value is -1:
'abc'.indexOf(); //-1
'abc'.indexOf(false); //-1
'abc'.indexOf(undefined); //-1
i have seen also those questions:
Q1 didnt understand the answer in depth.
Q2 in java and not javascript.
The answer, fundamentally, is: Because that's how the function is specified to behave. And it makes sense, from a certain perspective.
The main bit related to returning 0 when you search for an empty string is this:
Return the smallest possible integer k not smaller than start such that k + searchLen is not greater than len, and for all nonnegative integers j less than searchLen, the code unit at index k + j within S is the same as the code unit at index j within searchStr; but if there is no such integer k, return the value -1.
Since the length of the search string is 0, both halves of that "and" are satisfied by k = 0: k + searchLen is not greater than the length of the string, and for all nonnegative integers less than the search length (there are zero), the code points match.
Or roughly speaking, in code:
function indexOf(searchString, position = 0) {
let s = String(this);
let searchStr = String(searchString);
let len = s.length;
let start = Math.min(Math.max(position, 0), len);
let searchLen = searchStr.length;
let k = 0;
while (k + searchLen <= len) {
if (s.substring(k, k + searchLen) === searchStr) {
break;
}
++k;
}
const found = k + searchLen <= len;
return found ? k : -1;
}
Since k + searchLen (0) is <= len (0), k (0)` is returned.
Live Example:
function indexOf(searchString, position = 0) {
let s = String(this);
let searchStr = String(searchString);
let len = s.length;
let start = Math.min(Math.max(position, 0), len);
let searchLen = searchStr.length;
let k = 0;
while (k + searchLen <= len) {
if (s.substring(k, k + searchLen) === searchStr) {
break;
}
++k;
}
const found = k + searchLen <= len;
return found ? k : -1;
}
console.log(indexOf.call("abcd", ""));
Another way to look at it is this answer related to Java...or to life in general.
Re your question passing in non-strings: One of the first steps is:
Let searchStr be ? ToString(searchString).
...which is let searchStr = String(searchString); in my rough code above. That means false becomes "false" and undefined becomes "undefined". "abc" doesn't contain either "false" or "undefined".

Levenshtein distance from index 0

I've been working through "The Algorithm Design Manual" section 8.2.1 Edit Distance by Recursion. In this section Skiena writes, "We can define a recursive algorithm using the observation that the last character in the string must either be matched, substituted, inserted, or deleted." That got me wondering, why the last character? This is true for any character based on the problem definition alone. The actual Levenshtein distance algorithm makes recursive calls from the back of the strings. Why? There's no reason you couldn't do the opposite, right? Is it just a simpler, more elegant syntax?
I'm flipping the algorithm around, so it iterates from the front of the string. My attempt is below. I know my implementation doesn't work completely (ex: minDistance("industry", "interest") returns 5 instead of 6). I've spent a couple hours trying to figure out what I'm doing wrong, but I'm not seeing it. Any help would be much appreciated.
var matchChar = (c,d) => c === d ? 0 : 1;
var minDistance = function(word1, word2) {
var stringCompare = function(s, t, i, j) {
if(i === s.length) return Math.max(t.length-s.length-1,0)
if(j === t.length) return Math.max(s.length-t.length-1,0)
if(cache[i][j] !== undefined) {
return cache[i][j]
}
let match = stringCompare(s,t,i+1,j+1) + matchChar(s[i], t[j]);
let insert = stringCompare(s,t,i,j+1) + 1;
let del = stringCompare(s,t,i+1,j) + 1;
let lowestCost = Math.min(match, insert, del)
cache[i][j] = lowestCost
return lowestCost
};
let s = word1.split('')
s.push(' ')
s = s.join('')
let t = word2.split('')
t.push(' ')
t = t.join('')
var cache = []
for(let i = 0; i < s.length; i++) {
cache.push([])
for(let j = 0; j < t.length; j++) {
cache[i].push(undefined)
}
}
return stringCompare(s, t, 0, 0)
}
The lines
if(i === s.length) return Math.max(t.length-s.length-1,0)
if(j === t.length) return Math.max(s.length-t.length-1,0)
look wrong to me. I think they should be
if(i === s.length) return t.length-j
if(j === t.length) return s.length-i

A code wars challenge

I have been struggling with this challenge and can't seem to find where I'm failing at:
Some numbers have funny properties. For example:
89 --> 8¹ + 9² = 89 * 1
695 --> 6² + 9³ + 5⁴= 1390 = 695 * 2
46288 --> 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
Given a positive integer n written as abcd... (a, b, c, d... being digits) and a positive integer p we want to find a positive integer k, if it exists, such as the sum of the digits of n taken to the successive powers of p is equal to k * n. In other words:
Is there an integer k such as : (a ^ p + b ^ (p+1) + c ^(p+2) + d ^ (p+3) + ...) = n * k
If it is the case we will return k, if not return -1.
Note: n, p will always be given as strictly positive integers.
digPow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1
digPow(92, 1) should return -1 since there is no k such as 9¹ + 2² equals 92 * k
digPow(695, 2) should return 2 since 6² + 9³ + 5⁴= 1390 = 695 * 2
digPow(46288, 3) should return 51 since 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
I'm new with javascript so there may be something off with my code but I can't find it. My whole purpose with this was learning javascript properly but now I want to find out what I'm doing wrong.I tried to convert given integer into digits by getting its modulo with 10, and dividing it with 10 using trunc to get rid of decimal parts. I tried to fill the array with these digits with their respective powers. But the test result just says I'm returning only 0.The only thing returning 0 in my code is the first part, but when I tried commenting it out, I was still returning 0.
function digPow(n, p){
// ...
var i;
var sum;
var myArray= new Array();
if(n<0)
{
return 0;
}
var holder;
holder=n;
for(i=n.length-1;i>=0;i--)
{
if(holder<10)
{
myArray[i]=holder;
break;
}
myArray[i]=holder%10;
holder=math.trunc(holder/10);
myArray[i]=math.pow(myArray[i],p+i);
sum=myArray[i]+sum;
}
if(sum%n==0)
{
return sum/n;
}
else
{
return -1;
}}
Here is the another simple solution
function digPow(n, p){
// convert the number into string
let str = String(n);
let add = 0;
// convert string into array using split()
str.split('').forEach(num=>{
add += Math.pow(Number(num) , p);
p++;
});
return (add % n) ? -1 : add/n;
}
let result = digPow(46288, 3);
console.log(result);
Mistakes
There are a few problems with your code. Here are some mistakes you've made.
number.length is invalid. The easiest way to get the length of numbers in JS is by converting it to a string, like this: n.toString().length.
Check this too: Length of Number in JavaScript
the math object should be referenced as Math, not math. (Note the capital M) So math.pow and math.trunc should be Math.pow and Math.trunc.
sum is undefined when the for loop is iterated the first time in sum=myArray[i]+sum;. Using var sum = 0; instead of var sum;.
Fixed Code
I fixed those mistakes and updated your code. Some parts have been removed--such as validating n, (the question states its strictly positive)--and other parts have been rewritten. I did some stylistic changes to make the code more readable as well.
function digPow(n, p){
var sum = 0;
var myArray = [];
var holder = n;
for (var i = n.toString().length-1; i >= 0; i--) {
myArray[i] = holder % 10;
holder = Math.trunc(holder/10);
myArray[i] = Math.pow(myArray[i],p+i);
sum += myArray[i];
}
if(sum % n == 0) {
return sum/n;
} else {
return -1;
}
}
console.log(digPow(89, 1));
console.log(digPow(92, 1));
console.log(digPow(46288, 3));
My Code
This is what I did back when I answered this question. Hope this helps.
function digPow(n, p){
var digPowSum = 0;
var temp = n;
while (temp > 0) {
digPowSum += Math.pow(temp % 10, temp.toString().length + p - 1);
temp = Math.floor(temp / 10);
}
return (digPowSum % n === 0) ? digPowSum / n : -1;
}
console.log(digPow(89, 1));
console.log(digPow(92, 1));
console.log(digPow(46288, 3));
You have multiple problems:
If n is a number it is not going to have a length property. So i is going to be undefined and your loop never runs since undefined is not greater or equal to zero
for(i=n.length-1;i>=0;i--) //could be
for(i=(""+n).length;i>=0;i--) //""+n quick way of converting to string
You never initialize sum to 0 so it is undefined and when you add the result of the power calculation to sum you will continually get NaN
var sum; //should be
var sum=0;
You have if(holder<10)...break you do not need this as the loop will end after the iteration where holder is a less than 10. Also you never do a power for it or add it to the sum. Simply remove that if all together.
Your end code would look something like:
function digPow(n, p) {
var i;
var sum=0;
var myArray = new Array();
if (n < 0) {
return 0;
}
var holder;
holder = n;
for (i = (""+n).length - 1; i >= 0; i--) {
myArray[i] = holder % 10;
holder = Math.trunc(holder / 10);
myArray[i] = Math.pow(myArray[i], p + i);
sum = myArray[i] + sum;
}
if (sum % n == 0) {
return sum / n;
} else {
return -1;
}
}
Note you could slim it down to something like
function digPow(n,p){
if( isNaN(n) || (+n)<0 || n%1!=0) return -1;
var sum = (""+n).split("").reduce( (s,num,index)=>Math.pow(num,p+index)+s,0);
return sum%n ? -1 : sum/n;
}
(""+n) simply converts to string
.split("") splits the string into an array (no need to do %10 math to get each number
.reduce( function,0) call's the array's reduce function, which calls a function for each item in the array. The function is expected to return a value each time, second argument is the starting value
(s,num,index)=>Math.pow(num,p+index+1)+s Fat Arrow function for just calling Math.pow with the right arguments and then adding it to the sum s and returning it
I have created a code that does exactly what you are looking for.The problem in your code was explained in the comment so I will not focus on that.
FIDDLE
Here is the code.
function digPow(n, p) {
var m = n;
var i, sum = 0;
var j = 0;
var l = n.toString().length;
var digits = [];
while (n >= 10) {
digits.unshift(n % 10);
n = Math.floor(n / 10);
}
digits.unshift(n);
for (i = p; i < l + p; i++) {
sum += Math.pow(digits[j], i);
j++;
}
if (sum % m == 0) {
return sum / m;
} else
return -1;
}
alert(digPow(89, 1))
Just for a variety you may do the same job functionally as follows without using any string operations.
function digPow(n,p){
var d = ~~Math.log10(n)+1; // number of digits
r = Array(d).fill()
.map(function(_,i){
var t = Math.pow(10,d-i);
return Math.pow(~~((n%t)*10/t),p+i);
})
.reduce((p,c) => p+c);
return r%n ? -1 : r/n;
}
var res = digPow(46288,3);
console.log(res);

String Search Algorithm Implementation

I have implemented the string search algorithm using the naive method to count the number of times a substring occurs in a string. I did the implementation in javascript and python.
Algorithm (From Topcoder):
function brute_force(text[], pattern[])
{
// let n be the size of the text and m the size of the
// pattern
count = 0
for(i = 0; i < n; i++) {
for(j = 0; j < m && i + j < n; j++)
if(text[i + j] != pattern[j]) break;
// mismatch found, break the inner loop
if(j == m) // match found
count+=1
return count
}
}
Javascript Implementation:
a = "Rainbow";
b = "Rain";
count = 0;
function findSubStr(Str, SubStr){
for (i = 0; i<a.length; i++){
//document.write(i, '<br/>');
for (j = 0; j < b.length; j++)
//document.write('i = ',i, '<br/>');
//document.write(j, '<br/>');
if(a[i + j] != b[j]) break;
document.write('j = ', j, '<br/>')
//document.write('i = ',i, '<br/>');
if (j == b.length)
count+=1;
}
return count;
}
document.write("Count is ",findSubStr(a,b), '<br/>');
Python Implementation:
a = "Rainbow"
b = "Rain"
def SubStrInStr(Str, SubStr):
count = 0
for i in range(len(Str)):
for j in range(len(SubStr)):
print j
if (a[i + j] != b[j]):
break
if (j+1 == len(SubStr)):
count+=1
return count
print(SubStrInStr(a, b))
Now my question is for the line that implements if (j == b.length): It works well in javascript but for python I need to add 1 to the value of j or deduct 1 from the length of b. I don't know why this is happening.
for x in range(4)
Unlike Javascript in Python for loop is used for every element in the list. Last value x will take is the last element of the list [0, 1, 2, 3] which is 3.
for(x = 0; x < 4; x++)
In Javascript x will take value for 4 and the loop will end because x < 4 condition no longer can be applied. Last value x will take is 4.
You have this confusion because your code isn't identical. Executing for (j = 0; j < b.length; j++) the final value for j will be b.length (in case that b is a substring of a), but for Python, things are a little bit different. Running range(len("1234")) will result in [0, 1, 2, 3], so your for is more like a foreach, j storing the last value from the array and this is the reason why you have to add one. I hope that I was clear enough. If not, please ask for details.
I don't know about javascript , But I have implemented naive search in Python with all the cases with easiest way.
Take a glance on it as below.
It will return no of time pattern got found.
def naive_pattern_search(data,search):
n = len(data) #Finding length of data
m = len(search) #Finding length of pattern to be searched.
i = 0
count = c = 0 #Taking for counting pattern if exixts.
for j in range(m-1):#Loop continue till length of pattern to be Search.
while i <= (n-1):#Data loop
#if searched patten length reached highest index at that time again initilize with 0.
if j > (m-1):
j = 0
#Data and search have same element then both Index increment by 1.
if data[i]==search[j]:
#print(f"\n{ data[i] } { search[j] }")
#print(f"i : {i} {data[i]} j : {j} {search[j]}")
i+=1
j+=1
count+=1
#If one pattern compared and found Successfully then Its Counter for pattern.
if count== (m-1):
c = c + 1
#Initilise pattern again with 0 for searching with next element in data.
else:
j = 0 #Direct move to 0th index.
i+=1
count=0 #If data not found as per pattern continuously then it will start counting from 0 again.
#Searched pattern occurs more then 0 then its Simply means that pattern found.
if c > 0:
return c;
else:
return -1;
Input : abcabcabcabcabc
Output: Pattern Found : 5 Times
I find your python implementation has some problem. If you set the b = "raiy", the function will incorrectly return 1. You may misunderstand the edge condition.
Those two condition statements should be in the same level.
a = "Rainbow"
b = "Rain"
def SubStrInStr(Str, SubStr):
count = 0
for i in range(len(Str)):
for j in range(len(SubStr)):
# print (j)
if (a[i + j] != b[j]):
break
if (j+1 == len(SubStr)):
count+=1
return count
print(SubStrInStr(a, b))here

Categories

Resources