Radix Sort in JavaScript - javascript

I've come up with the following but it predictably doesn't work.
var t = new Array(a.length);
var r = 4;
var b = 64;
var count = new Array(1<<r);
var pref = new Array(1<<r);
var groups = Math.ceil(b / r);
var mask = (1 << r) - 1;
var shift = 0;
for(var c = 0; c < groups; c++)
{
shift += r;
for(var j = 0; j < count.length; j++)
{
count[j] = 0;
}
for(var i = 0; i < a.length; i++)
{
count[ (a[i] >> shift) & mask ]++;
}
pref[0] = 0;
for(var i = 0; i < count.length; i++)
{
pref[i] = pref[i-1] + count[i-1];
}
for(var i = 0; i < a.length; i++)
{
t[ pref[ (a[i] >> shift) & mask ]++ ] = a[i];
}
for(var i = 0; i < a.length; i++)
{
a[i] = t[i];
}
// a is sorted?
}

This loop does basically the same thing, in a more Javascript-y way:
for (var div = 1, radix = 16; div < 65536 * 65536; div *= radix) {
var piles = [];
for (var i = 0; i < a.length; ++i) {
var p = Math.floor(a[i] / div) % radix;
(piles[p] || (piles[p] = [])).push(a[i]);
}
for (var i = 0, ai = 0; i < piles.length; ++i) {
if (!piles[i]) continue;
for (var pi = 0; pi < piles[i].length; ++pi)
a[ai++] = piles[i][pi];
}
}
Instead of doing it like a C programmer might, this loop builds a list of lists, one list for each possible 4-bit value. I avoid bit-shift operators because this is Javascript and while they do work, things get funny when numbers get large.
Starting with the low 4 bits of each value in "a", the code copies that element of "a" to the end of one of the "piles", that being the one corresponding to the 4-bit value. It then gathers up the piles and rebuilds "a" starting from all of the values whose low 4 bits were 0, then 1, etc. (Clearly there'll be some gaps, so those are skipped.) At the end of each iteration of the overall loop, the divisor is multiplied by the radix, so that the next set of 4 bits will be examined.
Once the divisor has exhausted the available range of integers, it's done.
Note that this will only work for positive numbers. Doing this with negative numbers gets a little weird; it might be easier to strip out the negative numbers into a separate array, flip the sign, sort, then reverse. Sort the positive numbers, and then finally glue the reversed negative numbers (flipping the signs again) to the front of the sorted positive numbers.

this
for(var i = 0; i < count.length; i++)
{
pref[i] = pref[i-1] + count[i-1];
}
is a problem because on the first iteration, i is zero and so pref[ 0 - 1 ] is not going to work very well.
I don't have a reference for radix sorts handy to determine what you should actually be doing here.

Related

Output only one possible result looping thru 2 arrays with if-statement

I have two arrays. Each element of which I compare numbers of first array are greater than the seconds' and if it finds (through if statement) any number from first array greater than any number from second array, I console.log them. However, there might be more than one coincidence but per one request in need to console.log only first result.
Say,
First array has [0.4,0,6]
Second array has [0.5,0.5]
It produces 2 results since there are two matches. How to get only first one.
My code looks like that:
https://jsfiddle.net/oxpwb0j3/2/
const numbers = [0.6,0.4];
for(a = 0; a < numbers.length; a++) {
var res_num1 = numbers[a];
const numbers2 = [0.5,0.5];
for(b = 0; b < numbers2.length; b++) {
var res_num2 = numbers2[b];
if(res_num1 > res_num2){
console.log(res_num1+" = "+res_num2);
}
}
}
it outputs:
0.6 = 0.5
0.6 = 0.5
as I explained in the beginning how to limit to only log the first result like so 0.6 = 0.5.
I'm new to JS and learning. Thank you!
just add break the first time it met the condition.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break
const numbers = [0.4,0.6];
for(a = 0; a < numbers.length; a++) {
var res_num1 = numbers[a];
const numbers2 = [0.5,0.5];
for(b = 0; b < numbers2.length; b++) {
var res_num2 = numbers2[b];
if(res_num1 > res_num2){
console.log(res_num1+" = "+res_num2);
break;
}
}
}
Try to use labels
const numbers = [0.4,0.5,0.6];
for(a = 0; a < numbers.length; a++) {
var res_num1 = numbers[a];
const numbers2 = [0.5,0.5];
outerloop: for(b = 0; b < numbers2.length; b++) {
var res_num2 = numbers2[b];
if(res_num1 > res_num2){
console.log(res_num1+" = "+res_num2);
break outerloop;
}
}
}

How to sort based on columns in 2 dimensional arrays in C?

I've just started to learn C. And I'm trying to sort the columns in 2 dimensional arrays in C.
Here's the problem
Write a program to input an array of m x n. Sort the odd column in increasing order and the even column in decreasing order
My idea is to use recursive function. At each row of the array, I will push the elements in a new array, sort it, and reassign to the old array. Loop that recursively until we reach the end of the columns.
Here's my code in C:
#include <stdio.h>
int j = 0, temp[] = {}, sizeTemp = 0; // The size of temp, change overtime in loop()
int arr[4][3] = {
{1,2,3},
{4,8,6},
{2,1,5},
{3,7,4}
};
void pushToArray(int arr[], int currentEl, int addEl){ // Push an element into an array
arr[currentEl] = addEl;
}
void bubbleSort(int arr[], int size, int inc_dec){
// Using bubble sort to sort the temporary array, which is then reassigned to the old array
int temp;
for(int i = 0; i < size; i++){
for(int j = 0; j < size - 1;j++){
if(inc_dec == 1){
// Increasing
if(arr[j] > arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}else{
// Decreasing
if(arr[j] < arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
int justForReturnSomething(){
// void function can't return a value, so I use this just for returning something
return 1;
}
void loop(){
int temp2;
for(int i = 0; i < 4; i++){
if(j > 2){
return justForReturnSomething();
}
temp2 = arr[i][j];
pushToArray(temp,sizeTemp,temp2);
sizeTemp++;
if(j % 2 != 0){
bubbleSort(temp,sizeTemp,1);
}else{
bubbleSort(temp, sizeTemp,-1);
}
}
for(int k = 0; k < 4; k++){
arr[k][j] = temp[k];
}
if(j > 2){
return justForReturnSomething();
}else{
j++;
for(int m = 0; m < sizeTemp; m++){ // Reassign the temp to empty
temp[m] = 0;
}
sizeTemp = 0; // reassign the size of temp to 0
loop();
}
}
int main(){
loop();
printf("Your sorted array: \n");
for(int i = 0; i < 4; i++){
for(int j = 0; j < 3; j++){
printf("%d,",arr[i][j]);
}
printf("\n");
}
return 0;
}
Result:
Your sorted array:
5,0,7,
4,0,6,
3,0,4,
Just for DEMONSTRATING the idea to approach the problem, I tried it with Javasript, the result is fine:
let arr = [
[1,2,3],
[4,8,6],
[2,1,5],
[3,7,4]
];
let temp = [], j=0;
function bubbleSort( arr, size, inc_dec){
let temp;
for(let i = 0; i < size; i++){
for(let j = 0; j < size - 1;j++){
if(inc_dec == 1){
// Increasing
if(arr[j] > arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}else{
// Decreasing
if(arr[j] < arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
function loop(){
for(let i = 0; i < 4; i++){
if(j > 2){
return;
}
temp.push(arr[i][j]);
if(j % 2 !== 0){
bubbleSort(temp,temp.length,1);
}else{
bubbleSort(temp, temp.length,-1);
}
}
for(let k = 0; k < 4; k++){
arr[k][j] = temp[k];
}
if(j > 2){
return;
}else{
j++;
temp = [];
loop();
}
}
loop();
console.log(arr);
Since I've tried to solve this with my own idea and did come up with a solution without searching on google, I'd be very happy if you can guide me to bring in the solution for C with this approach. But, other approaches are greatly appreciated.
This is the answer from #Brian. Thank you very much Brian
#include <stdio.h>
void bubbleSort2D(int numRows, int numCols, int arr[][numCols], int col, int incDec) {
// Using bubble sort to sort a column in the matrix
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numRows - 1; j++) {
int a = arr[j][col];
int b = arr[j + 1][col];
if ((incDec && a > b) || (!incDec && a < b)) {
arr[j][col] = b;
arr[j + 1][col] = a;
}
}
}
}
int main() {
int arr[4][3] = {
{1,2,3},
{4,8,6},
{2,1,5},
{3,7,4}
};
for (int i = 0; i < 3; i++) {
// sort "odd" columns in descending order, "even" columns in ascending order
bubbleSort2D(4, 3, arr, i, i % 2 == 0);
}
printf("Your sorted array: \n");
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++) {
printf("%d,", arr[i][j]);
}
printf("\n");
}
return 0;
}
Here's repl link:
Srort columns in 2D array
Not a complete answer, since it looks like you want to solve this problem on your own.
The trick here is to sort by columns, when C stores arrays in row-major order. You can do this by defining a stride (for an array witn M columns and N rows, this would be sizeof a[0], that is, the size of a single row) and doing all indexing in multiples of that stride. Or you can transpose the array, sort by rows, and transpose the result back.
I would recommend sorting in place for performance, but writing the code that does round-trip transposition will probably be simpler. Copying entire arrays twice is expensive, but not incredibly so: it’s proportional to the size of the array.
If you write functions to sort in ascending order and in descending order, and you have an int[M][N], you can call sort_ascending( int[i], N ) or sort_descending( int[i], N ) as appropriate. You might have a look at qsort() in the standard library. If you want to try to sort in place, you’d need to pass the number of rows, the number of columns, and the column to sort. The number of columns would be the stride between the elements you care about.
A few different ways to control whether you sort rows up or down: always sort decreasing then increasing and increment by 2, keep a flag that remembers whether you sorted the last row ascending or descending, or check 1%2, which optimizes to an extremely cheap bitwise or instruction.

Why my "Repeated Strings" code isn't working? || Hackerrank || JavaScript

((s, n) => {
let nStrings = ''; // stores the string we get after multiplying s to reach length n.
let aNos = 0; // stores the number of 'a's present in nStrings;
for (let i = 0; i < n; i++) {
for (let j = 0; j < s.length; j++) {
if (nStrings.length === n) {
break;
} else {
nStrings += s[j];
}
}
}
for (let k = 0; k < nStrings.length; k++) {
if (nStrings[k] === 'a') {
aNos++;
}
}
return aNos;
})('a', 1000000000000);
Above is my code written for the problem "Repeated Strings" in Hackerrank (Problem link). I wrote this in JavaScript. When I ran this code it shows that it ran out of memory. I don't understand why.
Please review my code and let me know why it failed.
Thank you.
You could get the the count of a in the given string, divide the length by the string length, get the integer part and multiply with the count of the given string.
The second part is to get the rest of the wanted length with remainder operator and iterate the given string for getting a count of a.
Return the sum of the integer and rest count.
function getCount(string, length) {
var first = 0,
count = 0,
rest = 0,
restCount = 0,
i;
for (i = 0; i < string.length; i++) if (string[i] === 'a') count++;
first = Math.floor(length / string.length) * count;
rest = length % string.length;
for (i = 0; i < rest; i++) if (string[i] === 'a') restCount++;
return first + restCount;
}
console.log(getCount('aba', 10)); // 7

How to shuffle characters in a vertical inverted pattern?

I have a string "ABCDEFGHIJKLMN" that I need to shuffle in a specific manner. To do that, I write the characters sequentially in columns bottom -> top and then left -> right (4 chars per column for example) until all characters are done. If the last column is not complete, then the empty spaces need to be on the bottom (this is very important). Like so:
D H L N
C G K M
B F J
A E I
The shuffle is accomplished by producing a new string reading the block of letters as we read text, in rows left -> right:
"DHLNCGKMBFJAEI"
The cases where the columns are not complete (word.size % column_height !=0) complicate things considerably.
I came up with a few solutions, but I'm not sure if there is a simpler (ie, shorter OR easier to read) and more elegant way of coding this problem. My solutions either have an ugly, separate block of code to handle the final incomplete column or seem way too complicated.
My question is, could it be done better?
If you don't want any spoilers and decide to try and figure it out for yourself, stop reading now. If you want to work from what I fiddled so far, then a working piece of code is
var result = "";
var str = "ABCDEFGHIJKLMN";
var nr_rows = 4;
var current_row = 4;
var columns = Math.floor(str.length / nr_rows);
var modulus_table = str.length % nr_rows;
var modulus_position = -1;
for (var i = 0; i < nr_rows; i++) {
for (var j = 0; j < columns; j++) {
result += str[current_row + j * nr_rows - 1];
}
if (modulus_table > 0) {
result += str[str.length + modulus_position];
modulus_table--;
modulus_position--;
}
current_row--;
}
console.log(result);
Moving on to arrays, the next example would loop through each character, placing it correctly in a matrix-like array, but it doesn't work. The array needs to be created another way. For another example of this issue, see How to create empty 2d array in javascript?. This would also need an ugly hack to fix the last characters on the last incomplete column aligning to the bottom instead of the top.
var result = [[],[]];
var str = "ABCDEFGHIJKLMN";
var nr_rows = 4;
var row = nr_rows - 1;
var column = 0;
for (var i = 0; i < str.length; i++) {
result[row][column] = str[i];
row--;
if (row < 0) {
row = nr_rows;
column++;
}
}
console.log(result);
This last method goes full matrix array, but it quickly becomes complicated, since it needs to loop through the array in 3 different directions. First, create a dummy array with the characters in the wrong place, but where the 'undefined' positions correspond to those that should be left empty. That is acomplished by populating the array 'rotated 90º' from the reading orientation.
Without this first step, the empty positions would be stacked at the bottom instead of the top.
A second pass is required to re-write the caracters in the correct places, skipping any holes in the matrix using the 'undefined' value. This check is made for every position and there is no separate block of code to handle an incomplete last line.
A third pass then reads every character in order to form the final shuffled string. All this seems way too complicated and confusing.
// matrix populated top->bottom and left->right
// with the characters in the wrong place
// but the undefined postions in the correct place of the empty positions
var matrix = [];
var str = "ABCDEFGHIJKLMN";
var rows = 4;
var columns = Math.ceil(str.length / rows);
var k = 0;
for (var i = 0; i < rows; i++) {
matrix[i] = [];
for (var j = columns - 1; j >= 0; j--) {
matrix[i][j] = str[k];
k++;
}
}
// populate the matrix with the chars in the correct place and the 'undefined' positions left empty
var k = 0;
for (var i = 0; i < rows; i++) {
for (var j = 0; j < columns; j++) {
if (matrix[i][j] != undefined) {
matrix[i][j] = str[k];
k++;
}
}
}
// read matrix in correct direction and send to string, skipping empty positions
var result = "";
for (var j = columns - 1; j >= 0; j--) {
for (var i = 0; i < rows; i++) {
if (matrix[i][j] != undefined) {
result += matrix[i][j];
}
}
}
console.log(result);
What if you just split/reverse the array into column groups, and convert to rows?
const result = str.match(/.{1,4}/g) // split string into groups of 4
.map(i => i.split('').reverse()) // reverse each group (bottom to top, and solves the last col issue)
.reduce((res, col) => { // reduce the groups into rows
col.forEach((c, i) => res[i] += c) // concat each string char to the right row
return res
}, ['','','','']) // initialise empty strings per row
.join('') // join the rows up
Fiddle here
If you wish to return a string, I don't see why any intermediate result should use an array when it doesn't have to. The following could use one less array, but it's convenient to use split and an array to control the while loop rather than mutate the string.
The idea is to fill the strings from the bottom up until the column is full, then keep adding from the bottom of each column until it runs out of characters to assign. The row to start filling from is based on how many characters are left and how many rows there are.
Rather than building strings, it could build arrays but then generating a string requires multiple joins.
It can also produce results where there are insufficient slots for all the characters, so a result using 9 characters from 10 or more using a 3x3 "matrix" (see last example).
function verticalShuffle(s, rows, cols) {
var result = [''];
s = s.split('');
while (s.length && result[0].length < cols) {
for (var i = (rows < s.length? rows : s.length) -1 ; i>=0; i--) {
if (!result[i]) result[i] = '';
result[i] += s.splice(0,1)[0] || '';
}
}
return result.join('');
}
var s = 'ABCDEFGHIJKLMN';
console.log(verticalShuffle(s, 4, 4)); // DHLNCGKMBFJAEI
console.log(verticalShuffle(s, 6, 3)); // FLNEKMDJCIBHAG
// Only use 9 characters
console.log(verticalShuffle(s, 3, 3)); // CFIBEHADG
This uses plain ed3 functionality that will run in any browser. I don't see the point of restricting it to ECMAScript 2015 or later hosts.
If interpret Question correctly, you can use for loop, String.prototype.slice() to to populate arrays with characters of string. Use Array.prototype.pop() within recursive function to get last element of array until each array .length is 0.
To create array
[
["D","H","L","N"],
["C","G","K","M"],
["B","F","J"],
["A","E","I"]
]
from vertically inverted string you can use for loop, String.prototype.slice() to set array of arrays containing elements having .length 4, or 3 once .length of parent array is 2, having been set with two arrays containing four elements
var str = "ABCDEFGHIJKLMN";
function fnVerticalInvert(str, arr, res) {
if (!arr && !res) {
arr = []; res = "";
}
if (str) {
for (var i = 0; i < str.length; i += 4) {
arr.push([].slice.call(str.slice(i, i + 4)));
}
}
for (var i = 0; i < arr.length; i++) {
if (arr[i].length) {
res += arr[i].pop()
}
}
if (arr.some(function(curr) {return curr.length}))
return fnVerticalInvert(null, arr, res);
for (var i = 0, l = 4, j = 0, n = l - 1, k; i < l; i++, j += l) {
if (i === l / 2) k = j;
arr[i] = [].slice.call(res.slice(!k ? j : k, !k ? j + l : k + n));
if (k) k += n;
}
return {str: res, arr:arr};
};
var res = fnVerticalInvert(str);
console.log(res);

finding an array in another Multidimensional array in javascript

I'm writing a simple snakes game using JavaScript and HTML5 canvas.
I have a Multidimensional array that hold snake block like this:
snake=[[1,1],[1,2]];
and set it on arrayMap using (snake.indexOf([i],[j])!=-1) then draw arrayMap on canvas.
for (var i = 0; i < blocksHeightCount; i++) {
for (var j = 0; j < blocksWidthCount; j++) {
if ((snake.indexOf(i,j)!=-1)||
(walls.indexOf(i,j)!=-1)||
(foods.indexOf(i,j)!=-1)) {
arrayMap[i][j]=1;
} else {
arrayMap[i][j]=0;
}
}
}
for (var i = 0; i < blocksHeightCount; i++) {
for (var j = 0; j < blocksWidthCount; j++) {
Block = arrayMap[i][j];
if (Block!=0){
ctx.fillStyle = (Block != 9) ? colors[Block]
: "#bdc3c7";
ctx.fillRect(j * cubeWidth, i * cubeHeight
, cubeWidth-.4,cubeHeight-.4);
}
}
}
the problem is indexOf isn't working when I set array on it!
It works fine when I set indexOf("i,j") but i need it to be array.
please help, thx
First solution : using Array.map
Each element of your arrays snake, walls and foods is an array with 2 elements. So to check if an [x,y] exists in one of the arrays you need a simple way to
compare two arrays [x1, y1] and [x2, y2]. Comparing arrays directly using the operator == will compare their references and not values (Thanks #Elena for the remarque). A way to compare values
would be to affect a hash to each array and compare hashes. By hash I mean a number which is unique for each array of type [x, y]. That could be x * blocksWidthCount + y
in your case and the code will be :
function getHash(x, y){
return x * blocksWidthCount + y;
}
var blockHashes = snake.concat(walls).concat(foods).map(function(cell) {
return getHash(cell[0], cell[1]);
}); // hashes of all blocks in one array
for (var i = 0; i < blocksHeightCount; i++) {
for (var j = 0; j < blocksWidthCount; j++) {
if (blockHashes.indexOf(getHash(i, j)) != -1) {
arrayMap[i][j]=1;
} else {
arrayMap[i][j]=0;
}
}
}
Second Solution Changing the way we see things
Instead of looping over all cells and verifying if every single cell is a block which gives a complexity of O(N * M) (N number of cells and M number of blocks).
We can do better simply by supposing that there is no block and then loop over blocks and mark them as blocks which is in O(N + M) !
function markBlock(cell){
arrayMap[cell[0]][cell[1]] = 1;
}
for (var i = 0; i < blocksHeightCount; i++)
for (var j = 0; j < blocksWidthCount; j++)
arrayMap[i][j] = 0;
snake.forEach(markBlock);
walls.forEach(markBlock);
foods.forEach(markBlock);

Categories

Resources