How would I rewrite this JavaScript loop in Ruby? - javascript

Code:
var some_var = [/*.......*/];
var compare_var;
for (var i = 0; i < some_var.length - 1; i++){
if (some_var[i] <= compare_var && compare_var < some_var[i + 1]){
return some_var[i];
}
}
One value of some_var is 30 and the next one is 40 and the next one is 50 and compare_var is 42.
It wouldn't return 30 even though it's less-than 42, because 42 isn't less-than 40. Which also means that it would return 40 because it's less-than 42 and 42 is less-than 50.
Edit:
As someone mentioned code translation is not exactly great for SE.so. Just to make it clear: I did try several different things in ruby. I have way more experience in javascript though, so the best way I could think of to phrase my question was to write what I needed out in javascript so that I could see how it translated into ruby. Thanks for the answers

I would use the neato Enumerable#each_cons(n) method:
def foo(arr, x)
arr.each_cons(2) do |a,b|
return a if (a <= x) && (x < b)
end
nil # Not found
end
foo([30,40,50], 42) # => 40
This basically creates a "sliding window" of each pair and then you can just return the first item of the pair when you find the pair that encloses the target value (x).

This is a one-liner:
some_var.select{|v| v < compare_var}.max

Get rid of var key word, change for loop into some_var.each, and you get a working code in Ruby.
PS. Code translation is not proper in StackOverflow

Related

Bitwise OR ( | ) and Bitwise Operator ( ~ ) - Javascript

The challenge: Given integers N and K (where 2 <= K <= N), find the highest value of A & B (i.e. A bitwise-AND B) such that 0 <= A < B <= N and (A & B) < K.
I've made my code and it runs perfect with visible cases but it fails with the hidden cases.
My Code:
function bitwiseAnd(N, K) {
// Write your code here
let arr = []
N = parseInt(N,10)
K = parseInt(K,10)
for(let a=1; a<N; a++){
for(let b=a+1; b<=N ; b++){
if(K>=0 && parseInt(a&b,10) < K && parseInt(a&b,10)>=0) arr.push(parseInt(a&b,10))
}
}
return Math.max(...arr)
}
i searched for a solution and i found this one.
Solution:
function bitwiseAnd(N, K) {
// Write your code here
var n = parseInt(N);
var k = parseInt(K);
var a = k - 1;
var b = (~a) & -(~a);
if ( (a | b) > n )
return(a - 1);
else
return(a);
}
However the solution's code is working good with all hidden test, i cannot understand how it works, as i'm not familiar with Bitwise operators.
is there any chance to get an explanation of this operators and how to use ?
Thanks in advance.
Here is a variant of your code that works:
function bitwiseAnd(N, K) {
let r = 0;
for(let a=1; a<N; a++) {
for(let b=a+1; b<=N; b++) {
if((a&b) < K) r = Math.max(r, a&b)
}
}
return r
}
console.log(bitwiseAnd(5,2)) // 1
console.log(bitwiseAnd(8,5)) // 4
console.log(bitwiseAnd(2,2)) // 0
I've removed unnecessary parseInts and result checks. However, the only thing that was actually wrong with your code was the line Math.max(...arr).
The problem with that line is that it is not passing a reference to arr to the Math.max method. Instead, it is actually including all members of arr as arguments which will appear on the Javascript call stack. Normally, this would be fine. However, if you have hundreds of thousands of values in the array, the maximum call stack size will be exceeded and your code will fail to execute. This is why a hidden test case, which must have resulted in huge numbers of array members, caused hackerrank to reject your solution.
You've also posted a very interesting solution which does not use loops at all.
I've cleaned it up a little, and included it below:
function bitwiseAnd(n, k) {
let a = k-1
return (a | ~a & a+1) <= n ? a : a-1
}
console.log(bitwiseAnd(5,2)) // 1
console.log(bitwiseAnd(8,5)) // 4
console.log(bitwiseAnd(2,2)) // 0
Note that the original code said & -(~a) instead of & a+1. The Two's complement method of negating a number is to flip all bits and add one to the result. Since the bitwise not ~ also means to flip all bits, the original code flips all bits, flips all bits again, and then adds one. This is therefore an obfuscation of simply doing a+1.
Here is an explanation of the thinking that must be behind that code:
Since the result of A & B must be less than K, the maximum number that might be the result will be K-1.
When we do the bitwise A & B, the result can only switch certain bits off, and cannot switch any bits on. Since A must be a smaller number than B, and since we can only switch bits of A off, the result of A & B thus cannot exceed the value of A.
Combining the two conclusions above, we can conclude:
The choice of A cannot exceed K-1 if our choice of B will preserve all bits of A.
So, let's see if we can set A to K-1 and find a value of B which will preserve all bits in A.
The first value greater than A that will preserve all bits of A will be the result of setting the least significant bit that is currently unset.
For example, if A = 101, the next value of B that will preserve all bits of A after doing A & B is 111.
In order to locate the position of the least significant unset bit, we can do ~A & A+1. For the example where A is 101, ~A & A+1 is 010. Essentially, ~A & A+1, no matter what the value of A, will always return a binary sequence containing exactly one set bit.
The reason this works is that ~A acts as a mask that will only allow the result of ~A & A+1 to contain bits which were unset in A. When we do A+1, the first bit that will be set for the first time in A will be the least significant unset bit, and no other bits will be set for the first time.
For example: if A = 101, ~A = 010, A+1 = 110, and so ~A & A+1 = 010 & 110 = 010. That 1 in the answer is the position of the least significant unset bit in A.
If we do a bitwise OR, we can use this result to calculate the first higher value of B which will preserve all bits of A. Thus B = A | ~A & A+1. Therefore, we can see in the runnable code snippet above that if we find that (a | ~a & a+1) <= n, we know that the value of a = k-1 will work and we can return this as the answer.
But, what if that value of B that exceeds N? We will need to find the next-best answer.
Since we tried A = K-1, and since the question states K <= N, this means A must have been an odd number (i.e. the least significant bit was set). This is because if A was even, we'd have attempted the value B = A + 1, and B could not have exceeded N since K <= N and A = K-1.
So, since our earlier attempt failed when we tried A = K-1, we know we can't go higher than A to find a value of B that works when A = K-1.
But, if we set A = K-2, and since we know K-1 was odd, this means K-2 is even. This means that we can have A = K-2 and B = K-1, and A & B = K-2. The result of the function is therefore K-2.
The code could therefore perhaps be more clearly written as:
function bitwiseAnd(n, k) {
let a = k-1
return (a | ~a & a+1) <= n ? k-1 : k-2
}
console.log(bitwiseAnd(5,2)) // 1
console.log(bitwiseAnd(8,5)) // 4
console.log(bitwiseAnd(2,2)) // 0
The bottom line is that we don't need any loops, because there is always an answer where A = K-1 and B is more than one higher than A, or where A = K-2 and B = K-1.
But, there is an improvement we can make...
So far, we've explained the thinking behind the solution you posted. That solution, however, is more complicated than it needs to be.
If we want to take A and set the least-significant unset bit, we can simply do A | A+1.
This means a simpler solution would be:
function bitwiseAnd(n, k) {
let a = k-1
return (a | a+1) <= n ? k-1 : k-2
}
console.log(bitwiseAnd(5,2)) // 1
console.log(bitwiseAnd(8,5)) // 4
console.log(bitwiseAnd(2,2)) // 0
And, if we really want to code-golf the solution, we can substitute out the variable a, and take advantage of Javascript coercing true/false to 1/0 and do:
function bitwiseAnd(n, k) {
return --k-((k++|k)>n)
}
console.log(bitwiseAnd(5,2)) // 1
console.log(bitwiseAnd(8,5)) // 4
console.log(bitwiseAnd(2,2)) // 0

CTCI Ch.1.2 Check Permutation

Greetings and happy holidays,
My question involves problem "1.2 Check Permutation" from "Cracking The Coding Interview" 6th Ed.
When we compare the two strings, we check for any values in the array that are less than 0. This would indicate different char counts of our two strings. However, shouldn't the comparison be !== 0 instead of < 0? This would catch both over and undercounts of the chars. I didn't see this in the books Errata nor on any related search results.
Below is the provided code solution. (I mainly work in JS, so perhaps I'm reading the code incorrectly)
Many thanks in advance.
boolean permutation(String s, String t) {
if (s.length() != t.length()) {
return false;
}
int[] letters = new int[128];
char[] s_array = s.toCharArray();
for (char c : s_array) {
letters[c]++;
}
for (int i = 0; i < t.length(); i++) {
int c = (int) t.charAt(i);
letters[c]--;
if (letters[c] < 0) { // this is the line in question
return false;
}
}
return true;
}
The comparison for != 0 only makes sense after all the differences are computed. The way the code is structured allows an early detection.
The very first test is for s.length() != t.length(). Once the code passed it, we know that there are equal number of characters. It means that - if the strings are not permutations - there is a character which appears more in t than in s. As soon as such character is found, we conclude that t is not a permutation.

A task in JavaScript

I need to create a sequence of numbers using while or for that consists of the sum of the symbols of the number.
For example, I have a sequence from 1 to 10. In console (if I've already written a code) will go just 1, 2,3,4,5,6,7,8,9,1. If I take it from 30 to 40 in the console would be 3,4,5,6,7,8,9,10,11,12,13.
I need to create a code that displays a sum that goes from 1 to 100. I don't know how to do it but in console I need to see:
1
2
3
4
5
5
6
7
8
9
1
2
3
4
etc.
I've got some code but I got only NaN. I don't know why. Could you explain this to me?
for (let i = '1'; i <= 99; i++) {
let a = Number(i[0]);
let b = Number(i[1])
let b1 = Boolean(b)
if (b1 == false) {
console.log ('b false', a)
}
else {
console.log ('b true', a + b)
}
}
I hope you get what I was speaking about.
Although I like the accepted answer however from question I gather you were asking something else, that is;
30 become 3+0=3
31 become 3+1=4
37 becomes 3+7=10
Why are we checking for boolean is beyond the scope of the question
Here is simple snnipet does exactly what you ask for
for (let i = 30; i <= 40; i++) {
let x=i.toString();
console.log( 'numbers from ' +i + ' are added together to become '+ (Number(x[0])+Number((x[1])||0)))
}
what er are doing is exactly what Maskin stated begin with for loop then in each increment convert it to string so we can split it, this takes care of NAN issue.
you don't need to call to string just do it once as in let x then simply call the split as x[0] and so on.
within second number we have created a self computation (x[1])||0) that is if there is second value if not then zero. following would work like charm
for (let i = 1; i <= 10; i++) {
let x=i.toString();
console.log( 'numbers from ' +i + ' are added together to become '+ (Number(x[0])+Number((x[1])||0)))
}
Did you observe what happens to ten
here is my real question and solution what if you Don't know the length of the digits in number or for what ever reason you are to go about staring from 100 on wards. We need some form of AI into the code
for (let i = 110; i <= 120; i++) {
let x= Array.from(String(i), Number);
console.log(
x.reduce(function(a, b){ return a + b;})
);
};
You simply make an array with Array.from function then use simple Array.reduce function to run custom functions that adds up all the values as sum, finally run that in console.
Nice, simple and AI
You got NaN because of "i[0]". You need to add toString() call.
for (let i = '1'; i <= 99; i++) {
let a = Number(i.toString()[0]);
let b = Number(i.toString()[1])
let b1 = Boolean(b)
if (b1 == false) {
console.log('b false', a)
} else {
console.log('b true', a + b)
}
}
So the way a for loop works is that you declare a variable to loop, then state the loop condition and then you ask what happens at the end of the loop, normally you increment (which means take the variable and add one to it).
When you say let i = '1', what you're actually doing, is creating a new string, which when you ask for i[0], it gives you the first character in the string.
You should look up the modulo operator. You want to add the number of units, which you can get by dividing by 10 and then casting to an int, to the number in the tens, which you get with the modulo.
As an aside, when you ask a question on StackOverflow, you should ask in a way that means people who have similar questions to you can find their answers.

As per my pattern, the output is not a meaningful word. Can anyone identify a different pattern to output a meaningful word

As per my pattern, the output is not a meaningful word. Can anyone identify a different pattern to output a meaningful word.
Consider the following pattern:
A → D; M → P; X → A;
a → d; m → p; x → a;
Solve the following message
Vrphwklqj phdqlqjixo
Hint: The answer is something meaningful.
I am considering that there should be a difference of two alphabets; which outputs: Yuskznotm.....(not meaningful at all).
Can anyone see a different pattern and help me out.
The question is wrong
The pattern should be D->A,P->M,X->U
That is Caesar cipher using -3 or +23 (NOT +3)
READ THE QUESTION PROPERLY
USE THIS TO CHECK
import java.io.*;
class CaesarCipher
{
public static void main(String s)throws IOException
{
for(int i=1;i<27;i++)
{
int l=s.length();
for(int j=0;j<l;j++)
if(Character.isLetter(s.charAt(j)))
{
if(((s.charAt(j))+i)>122)
System.out.print((char)((s.charAt(j))+i-26));
else
System.out.print((char)((s.charAt(j))+i));
}
else
System.out.print((char)s.charAt(j));
System.out.println();
}
}
}
ONLY LOWERCASE LETTERS
It adds a new shift every time to create a new string
1,2,3,......,26
You can see the answer for your question when adding 23 or by also subtracting 3 which should be the real question which you mistook
IT WILL DISPLAY ALL POSSIBLE CAESAR DECRYPTIONS LOOK WHAT'S MEANINGFUL
Thanks Paulsam. You got it right. There was a discrepancy in the assignment question. I figured it and wrote a javascript for it.
<!doctype html>
<html>
<head>
<title>Ceaser-Cipher-Convertion</title>
</head>
<body>
<script>
//This function takes the input and defines the logic for conversion
function convert()
{
//The input to be converted to the message is provided here
var input = "Vrphwklqj phdqlqjixo";
/* The convertion logic is based on Ceaser-Cipher method. We retrieve the ASCII values of the characters one be one from the string.
As per formulae; m = c + d mod 26. However we are using ASCII values, we have to replace mod 26 by - 26.
The decryption key from the pattern is 23. Hence m = c + 23-26 => m = c - 23. However for the ASCII values; a-c; the formulae returns
non-alphabetic ASCII values. As an exception to these three alphabets; m = c + 23;
The ASCII value thus attained are to be converted back to characters */
for(var i=0; i<input.length; i++)
{
var asc_code = input.charCodeAt(i);
var conv_code;
//Conversion of alphabets (a-c)
if((asc_code >= 65 && asc_code <= 67) || (asc_code >= 97 && asc_code <= 99))
{
conv_code = asc_code+23;
}
//Conversion of rest of the alphabets
else if((asc_code >= 68 && asc_code <= 90) || (asc_code >= 100 && asc_code <= 122))
{
conv_code = asc_code-3;
}
//Conversion of non alphabetic characters
else conv_code = asc_code;
//Output the message
var message = String.fromCharCode(conv_code);
document.write(message);
}
}
convert();
</script>
</body>
</html>

How do I fix this syntax error?

The code is:
function roundAmount(theDecimal) {
var s = "" + Math.round(theDecimal * 100) / 100
var i = s.indexOf('.')
if (i < 0) {
return s + ".00"
}
var t = s.substring(0, i + 1) + s.substring(i + 1, i + 3)
if (i + 2 == s.length)
t += "0"
return t
}
The line with the error:
if (i < 0) return s + ".00"
The error is:
error: expected (;)
does anyone know how to fix this?
About your script:
The problem in the script above is that last if statement which does some operations followed by a return. You need a semi-colon after the operation.
In the future, as good practice, make sure to put a semi-colon after every valid statement. That way this won't bother you.
Think of each line as a thought, and curly braces as ways to "group" and "relate" thoughts together.
The below is a full thought that says "give me a variable "i" and give it the value 1 + 2;
var i = 1 + 2;
The below is a full thought about a condition that says "If i is 3 then add 1 to i". The thought "add 1 to i" is its own thought, so it needs a semicolon. Since the curlybraces for the IF statement are special in that they don't need a semi-colon after their "full thought" as long as you put a "block" (which is what curlybraces really make) after it, to enclose the thought.
This means the following is valid:
if( i == 3 ) {
i = i + 1;
}
The following is not valid because the semi-colon after the if ends the "thought" before the if knows what to do if i equals 3:
if( i == 3 ) ; {
i = i + 1;
}
For a basic JavaScript tutorial, check out W3Schools.
"There must be a better way?"
Any time you find yourself doing a lot of string operations on decmials, it's a good idea to ask yourself "is there a better way to do this?".
It looks like you're writing a function to round a number to the nearest hundredths while displaying two decimal points. There's a much easier way to do this. You can just round to the nearest hundredths and have javascript output the fixed point number.
Example:
function roundAmount( theDecimal ) {
//first round to the nearest hundredth
//then return the value with two decimal places as a string
return theDecimal.toFixed( 2 );
}
if (i < 0) return s + ".00";
Note the ; at the end of the statement. Personally, I prefer surrounding almost all my ifs in {} such as
if (i < 0)
{
return s + ".00";
}
Which helps in debugging and stepping though code.
It's expecting a semicolon, so add a semicolon.
if (i < 0)
return s + ".00";
Add a semicolon at the end of the line! Like this:
if (i < 0) return s + ".00";
I don't see anything particularly wrong with the code you posted in the earlier comments, but may I suggest always adding a semi-colon to the end of your statements. Though they are not required, it usually makes it easier to debug problems such as these.

Categories

Resources