Logic is working fine in C++ but when same logic is Implemented in Javascript code leads to runtime error, why? - javascript

Input: Unordered consecutive integer array e.g. [6,4,3,1,2,5]
Output: Minimum number of swaps required to sort the array in ascending order [1,2,3,4,5,6]
For the same purpose the C++ implementation is:
int minimumSwaps(vector<int> arr) {
int i,c=0,n=arr.size();
for(i=0;i<n;i++)
{
if(arr[i]==(i+1))
continue;
swap(arr[i],arr[arr[i]-1]);
c++;
i--;
}
return c;
}
The C++ code is working fine!!
But when the same logic is implemented in JavaScript it is going into endless loop leading to runtime error.
JavaScript implementation:
function minimumSwaps(arr) {
let swaps=0,n=arr.length,i=0;
for(i=0; i<n; i++){
if(arr[i]===(i+1))
continue;
let temp= arr[i];
arr[i]= arr[arr[i]-1];
arr[arr[i]-1]=temp;
swaps++;
i--;
}
return swaps;
}
How to solve this issue and make the JavaScript code working?

function minimumSwaps(arr) {
let swaps = 0, n = arr.length, i = 0;
for (i = 0; i < n; i++) {
if (arr[i] === (i + 1)) {
let temp = arr[i];
arr[i] = arr[arr[i] - 1];
arr[arr[i] - 1] = temp;
swaps++;
}
}
return swaps;
}

Issue with swaping value between array's index. in c++ you used a method but in js you tried to write manually, but your written code is wrong
Instead use this code, it is optimized
function minimumSwaps(arr) {
let swaps=0,n=arr.length,j=0;
for(var i=0; i<n; i=j){
if(arr[i]!=(i+1)){
var temp = arr[i];
arr[i] = arr[temp-1];
arr[temp-1] = temp;
swaps++;
}else j++;
}
return swaps;
}
Or simply optimize your code
for(i=0; i<n; i++){
if(arr[i]===(i+1))
continue;
let temp= arr[i]; //temp is 6 as per your list
arr[i]= arr[arr[i]-1]; //just now you changed arr[i] into arr[arr[i]-1] , so it will become 5 as per your list,
arr[temp-1]=temp; //now temp-1 is 5 but if you use arr[arr[i]-1] it will become 4 bcoz arr[i] is 5 now
swaps++;
i--;
}
in your code the issue was,
first you set temp to arr[i] and arr[i] to arr[arr[i]-1]
so next time when you call arr[arr[i]-1] it become arr[arr[arr[i]-1]-1 as you previously set arr[i] as arr[arr[i]-1]

Related

How to stop random letter picking from doing duplicate letters [duplicate]

I need help with writing some code that will create a random number from an array of 12 numbers and print it 9 times without dupes. This has been tough for me to accomplish. Any ideas?
var nums = [1,2,3,4,5,6,7,8,9,10,11,12];
var gen_nums = [];
function in_array(array, el) {
for(var i = 0 ; i < array.length; i++)
if(array[i] == el) return true;
return false;
}
function get_rand(array) {
var rand = array[Math.floor(Math.random()*array.length)];
if(!in_array(gen_nums, rand)) {
gen_nums.push(rand);
return rand;
}
return get_rand(array);
}
for(var i = 0; i < 9; i++) {
console.log(get_rand(nums));
}
The most effective and efficient way to do this is to shuffle your numbers then print the first nine of them. Use a good shuffle algorithm.What Thilo suggested will give you poor results. See here.
Edit
Here's a brief Knuth Shuffle algorithm example:
void shuffle(vector<int> nums)
{
for (int i = nums.size()-1; i >= 0; i--)
{
// this line is really shorthand, but gets the point across, I hope.
swap(nums[i],nums[rand()%i]);
}
}
Try this once:
//Here o is the array;
var testArr = [6, 7, 12, 15, 17, 20, 21];
shuffle = function(o){ //v1.0
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
shuffle(testArr);
This is relatively simple to do, the theory behind it is creating another array which keeps track of which elements of the array you have used.
var tempArray = new Array(12),i,r;
for (i=0;i<9;i++)
{
r = Math.floor(Math.random()*12); // Get a random index
if (tempArray[r] === undefined) // If the index hasn't been used yet
{
document.write(numberArray[r]); // Display it
tempArray[r] = true; // Flag it as have been used
}
else // Otherwise
{
i--; // Try again
}
}
Other methods include shuffling the array, removing used elements from the array, or moving used elements to the end of the array.
If I understand you correctly, you want to shuffle your array.
Loop a couple of times (length of array should do), and in every iteration, get two random array indexes and swap the two elements there. (Update: if you are really serious about this, this may not be the best algorithm).
You can then print the first nine array elements, which will be in random order and not repeat.
Here is a generic way of getting random numbers between min and max without duplicates:
function inArray(arr, el) {
for(var i = 0 ; i < arr.length; i++)
if(arr[i] == el) return true;
return false;
}
function getRandomIntNoDuplicates(min, max, DuplicateArr) {
var RandomInt = Math.floor(Math.random() * (max - min + 1)) + min;
if (DuplicateArr.length > (max-min) ) return false; // break endless recursion
if(!inArray(DuplicateArr, RandomInt)) {
DuplicateArr.push(RandomInt);
return RandomInt;
}
return getRandomIntNoDuplicates(min, max, DuplicateArr); //recurse
}
call with:
var duplicates =[];
for (var i = 1; i <= 6 ; i++) {
console.log(getRandomIntNoDuplicates(1,10,duplicates));
}
const nums = [1,2,3,4,5,6,7,8,9,10,11,12];
for(var i = 1 ; i < 10; i++){
result = nums[Math.floor(Math.random()*nums.length)];
const index = nums.indexOf(result);
nums.splice(index, 1);
console.log(i+' - '+result);
}

What is return -1 in javascript?

What is the return -1 on the third to last line of the below code? How does it work and what is its use?
function findElement(arr) {
let right_sum = 0, left_sum = 0;
for (let i = 1; i < arr.length; i++) {
right_sum += arr[i];
for (let i = 0, j = 1; j < arr.length; i++, j++) {
right_sum -= arr[j];
left_sum += arr[i];
if (left_sum === right_sum) {
return arr[i + 1];
}
}
return -1; // what is this?
}
}
It looks like the developer of that piece of code decided to return -1 if the for loop failed to return a value for error checking.
Its common for people to do these kinds of returns as it helps with error handling.
The return operator is used to return a value from inside a function, so the code return -1; makes the findElement function return the value -1 (negative 1) if the for loop doesn't work. This is useful for debugging. If the for loop works, then the function will return arr[i + 1].
It seems to be simulation of native arrays indexOf method. It returns -1 too, if no matches found.

Codewars - Delete occurrences of an element if it occurs more than n times

I just completed this challenge on Codewars.
I have completed the question with my own method, but can someone explain to me the Best Practice answer. Can somehow explain how this code functions?
function deleteNth(arr,x) {
var cache = {};
return arr.filter(function(n) {
cache[n] = (cache[n]||0) + 1;
return cache[n] <= x;
});
}
I did this:
function deleteNth(arr,n){
var count = 0;
//loop backwards so it removes duplicates from the right
for(let i= arr.length; i > 0; i--){
for(let j=0; j < arr.length; j++){
if (arr[i] == arr[j]){
count += 1
}
}
if(count > n){
arr.splice(i,1);
i = arr.length;
}
count = 0;
}
return arr;
}
This is how the first code works. It is a quite nice solution and quite easy to read if you understand the filter function.
function deleteNth(arr, x) {
// Create an empty object to store how many times each object exists
var cache = {};
// Call the filter function, the delegate is called once for each item
// in the array and you return true or false depending on if it should
// be kept or not
return arr.filter(function(n) {
// Use the item as key and store the number of times the item has appeared.
// (cache[n]||0) fetches the current value of cache[n] or zero if it doesn't
// exist. Then add one to it and store it.
cache[n] =(cache[n]||0) + 1;
// If the number of times it has appeared in the array is less or equal to
// the limit then return true so the filter function keeps it.
return cache[n] <= x;
});
}

What is the problem in this simple js code?

I am wondering what`s the problem with this simple code. I am making a function where I need to get the length of the shortest word in a string. I know that I can find this function anywhere but,
why mine isn't working?
function findShort(s){
var arr = s.split(" ");
var out = 1000;
for (var i = 0; i < arr.length-1; i++){
if (arr[i] <= out){
out = arr[i].length;
}
}
return out;
}
The above function returns 1000 instead.
You need to compare the length of each word (arr[i].length), not each word itself (arr[i]) to the shortest length so far.
function findShort(s){
var arr = s.split(" ");
var out = 1000;
for (var i = 0; i < arr.length-1; i++){
if (arr[i].length <= out){ // <-- here!
out = arr[i].length;
}
}
return out;
}
Your problem is that when you compare strings in javascript, it doesn't use it's length. You have to use the "length" attribute of a String, like in the fixed code below. Also you have to save the result to give an output
function findShort(s){
var arr = s.split(" ");
var comp = 1000;
var out = "";
for (var i = 0; i < arr.length-1; i++){
if (arr[i].length <= comp){
comp = arr[i].length;
out = arr[i];
}
}
return out;
}
There still is a problem, if you want to have an array returned with all the shortest words (same length). You could add another if statement and make it add the word to an array when it's the same length, and clear it when there was found a shorter one.

Understanding get second lowest and second highest value in array

Good day fellow Stack-ers,
I must ask your pardon if this question has been asked before or if it seems elementary (I am only a Javascript novice).
I have been doing w3c js challenges lately: Write a JavaScript function which will take an array of numbers stored and find the second lowest and second greatest numbers.
Here is my answer:
var array = [3,8,5,6,5,7,1,9];
var outputArray = [];
function arrayTrim() {
var sortedArray = array.sort();
outputArray.push(sortedArray[1],array[array.length-2]);
return outputArray;
}
arrayTrim();
and here is the answer that they have provided:
function Second_Greatest_Lowest(arr_num) {
arr_num.sort(function(x,y) {
return x-y;
});
var uniqa = [arr_num[0]];
var result = [];
for(var j=1; j < arr_num.length; j++) {
if(arr_num[j-1] !== arr_num[j]) {
uniqa.push(arr_num[j]);
}
}
result.push(uniqa[1],uniqa[uniqa.length-2]);
return result.join(',');
}
alert(Second_Greatest_Lowest([1,2,3,4,5]));
I know that the for loop runs through until the length of the input, but I don't understand the if statement nested within the for loop. It seems like a long way around to the solution.
Thank you!
Your answer does not perform correct for input such as f.e. [3,8,5,6,5,7,1,1,9]. Your proposed solution returns 1 as the second lowest number here – whereas it should actually be 3.
The solution suggested by the site takes that into account – that is what the if inside the loop is for, it checks if the current number is the same as the previous one. If that’s the case, it gets ignored. That way, every number will occur once, and that in turn allows to blindly pick the second element out of that sorted array and actually have it be the second lowest number.
It seems like a long way around to the solution
You took a short cut, that does not handle all edge cases correctly ;-)
The loop in question:
for(var j=1; j < arr_num.length; j++) {
if(arr_num[j-1] !== arr_num[j]) {
uniqa.push(arr_num[j]);
}
}
Provides some clue as to what it's doing by using a (reasonably) descriptive variable name: uniqa - or "unique array". The if statement is checking that the current element is not the same as the previous element - having sorted the array initially this works to give you a unique array - by only filling a new array if the element is indeed unique.
Thereafter the logic is the same as yours.
import java.util.Arrays;
public class BubbleWithMax_N_Min
{
public static void main(String[] agrs)
{
int temp;
int[] array = new int[5];
array[0] = 3;
array[1] = 99;
array[2] = 55;
array[3] = 2;
array[4] = 1;
System.out.println("the given array is:" + Arrays.toString(array));
for (int i = 0; i < array.length; i++)
{
System.out.println(array[i] + "");
}
for (int i = 0; i < array.length; i++)
{
for (int j = 1; j < array.length - i; j++)
{
if (array[j - 1] > array[j])
{
temp = array[j - 1];
array[j - 1] = array[j];
array[j] = temp;
}
}
}
System.out.println(" 2nd Min and 2nd Highest:");
for (int i = 0; i < 1; i++)
{
System.out.println(array[i+1]);
}
for (int i = 0; i < 1; i++)
{
int a= array.length-2;
System.out.println(array[a]);
}
}
}

Categories