I am tring to write this C# function in Python, unfortunatly I have this ERROR: IndexError: list assignment index out of range in Population.BinaryX.insert([i][j], dec) line. Can anyone tell me how can I fix this problem?! What`s wrong I did?
C# CODE:
public class Population
{
public float[] CodedX = new float[20];
public float[,] BinaryX = new float[10, 8];
}
private void BinaryTranslating()
{
int dec;
int j = 0;
for (var i = 0; i < 10; i++)
{
while (Population.CodedX[i] > 1 & j < 8)
{
dec = (int)Population.CodedX[i] % 2;
Population.BinaryX[i, j] = dec;
Population.CodedX[i] /= 2;
j++;
}
j = 0;
}
}
private void DecimalTranslating()
{
for (var i = 0; i < 10; i++)
{
Population.CodedX[i] = Population.BinaryX[i, 7] * 128 + Population.BinaryX[i, 6] * 64 +
Population.BinaryX[i, 5] * 32 + Population.BinaryX[i, 4] * 16 +
Population.BinaryX[i, 3] * 8 + Population.BinaryX[i, 2] * 4 +
Population.BinaryX[i, 1] * 2 + Population.BinaryX[i, 0];
}
}
Python CODE:
class Population:
CodedX = []
BinaryX = [[], []]
class Application:
#staticmethod
def binary_translating():
j = 0
for i in range(10):
while Population.CodedX[i] > 1 & j < 8:
dec = int(Population.CodedX[i]) % 2
Population.BinaryX.insert([i][j], dec)
Population.CodedX[i] /= 2
j += 1
j = 0
#staticmethod
def decimal_translating():
for i in range(10):
new_item = Population.BinaryX[i][7] * 128 + Population.BinaryX[i][6] * 64 + Population.BinaryX[i][5] * 32 +\
Population.BinaryX[i][4] * 16 + Population.BinaryX[i][3] * 8 + Population.BinaryX[i][2] * 4 +\
Population.BinaryX[i][1] * 2 + Population.BinaryX[i][0]
Population.CodedX.insert(i, new_item)
Consider the [i][j] expression in Population.BinaryX.insert([i][j], dec). That expression creates a 1 item list containing the value of i and then tries to take the jth item from that list.
>>> i=1
>>> j=2
>>> [i][j]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Python lists are one dimensional and if you want a multidimensional list, you need to create a list of lists or use some other structure such as a numpy or pandas array.
One option is to preallocate the array with a known value so that you can simply index it later
#staticmethod
def binary_translating():
Population.BinaryX = [[None] * 8 for _ in range(10)]
j = 0
for i in range(10):
while Population.CodedX[i] > 1 & j < 8:
dec = int(Population.CodedX[i]) % 2
Population.BinaryX[i][j] = dec
Population.CodedX[i] /= 2
j += 1
j = 0
Another option is to insert into the sublist:
#staticmethod
def binary_translating():
Population.BinaryX = []
j = 0
for i in range(10):
Population.BinaryX.insert([])
while Population.CodedX[i] > 1 & j < 8:
dec = int(Population.CodedX[i]) % 2
Population.BinaryX[i].insert(j, dec)
Population.CodedX[i] /= 2
j += 1
j = 0
please make sure that Population.BinaryX is a valid entity and has at least 10 element in it because you are running the loop 10 times. Same goes for CodedX.
If either of them do not have at least 10 elements, you will get
IndexError: list assignment index out of range
Try..
class Population:
CodedX = [0 for i in range(10)]
BinaryX = [[0 for i in range(10)] for j in range(10)]
This is preallocating as mentioned by tdelaney.
If you look at each functions in the Application class, they try to use either BinaryX or CodedX arrays but if these arrays do not have any elements in them, then how will python index into them?
What I mean is before calling the decimal_translating() function, the Population.BinrayX must have elements in it. It cannot be empty array.
Similarly, before calling the binary_translating() function, Population.CodedX must have elements in it.
[edit #1]
After your comments and trying to understand your code.Here is what I have:-
class Population(object):
def __init__(self):
self.CodedX = [0 for i in range(10)] # as per your C# code
self.BinaryX = []
# debug code to fill CodedX array - remove it
for i in range(10):
self.CodedX[i] = int(761)
def binary_translating(self):
for i in range(10):
j = 0
self.BinaryX.append([0 for k in range(10)])
while (self.CodedX[i] > 0) and (j < 10):
dec = int(self.CodedX[i] % 2)
self.BinaryX[i][j] = dec # this will append at j
self.CodedX[i] = int(self.CodedX[i] / 2)
j += 1
# debug code to print - remove it
print(self.BinaryX)
# debug code to clear CodedX - remove it
for i in range(10):
self.CodedX[i] = int(0)
def decimal_translating(self):
for i in range(10):
value = self.BinaryX[i][7] * 128 + self.BinaryX[i][6] * 64 + self.BinaryX[i][5] * 32 + \
self.BinaryX[i][4] * 16 + self.BinaryX[i][3] * 8 + self.BinaryX[i][2] * 4 + \
self.BinaryX[i][1] * 2 + self.BinaryX[i][0]
self.CodedX[i] = value
print(self.CodedX)
pop = Population()
pop.binary_translating()
pop.decimal_translating()
I have added some debug code to have some starting values in CodedX and print statements for you to see the output.
generates the output:
[[1, 0, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 1, 1, 0, 1]]
[249, 249, 249, 249, 249, 249, 249, 249, 249, 249]
[edit #2]
Related
I am trying to get the random sum of i into the four variables scoreTotalOne, scoreTotalTwo, scoreTotalThree, and scoreTotalFour. I am not getting the correct answer in the output? Any help will be appreciated.
//array for par
int[] parArray = { 4, 3, 4, 4, 5, 4, 5, 3, 4, 4, 3, 5, 4, 4, 5, 4, 3, 4};
//multi-rectangular array 18 holes, 4 golfers
int[,] arr = new int[18, 4];
//generate random scores for holes/golfers
Random randomScores = new Random();
Console.WriteLine("Hole Par Golfer 1 Golfer 2 Golfer 3 Golfer 4");
int scoreTotalOne = 0;
int scoreTotalTwo = 0;
int scoreTotalThree = 0;
int scoreTotalFour = 0;
for (int i = 0; i < 9; i++)
{
Console.Write((i + 1) + "\t");
Console.Write(parArray[i] + "\t");
for (int j = 0; j < 4; j++)
{
arr [i, j] = randomScores.Next(parArray [i] - 2, parArray [i] + 3);
Console.Write(arr[i, j] + "\t");
scoreTotalOne += arr[i, j];
scoreTotalTwo += arr[i, j];
scoreTotalThree += arr[i, j];
scoreTotalFour += arr[i, j];
}
Console.WriteLine();
}
Console.WriteLine("Front" + " " + scoreTotalOne + " " + scoreTotalTwo + " " + scoreTotalThree + " " + scoreTotalFour);
You need one more array, instead of four separate variables. This will make it easy to pick only (the right) one of the totals to update in the inner loop. Otherwise, all four scores will always get the score of the final golfer, since the inner loop currently sets all four variables. It will look like this:
int[] holePars = { 4, 3, 4, 4, 5, 4, 5, 3, 4, 4, 3, 5, 4, 4, 5, 4, 3, 4};
int[,] holeScores = new int[18, 4];// 18 holes, 4 golfers
int[] totals = {0, 0, 0, 0};
var randomScores = new Random();
Console.WriteLine("Hole Par Golfer 1 Golfer 2 Golfer 3 Golfer 4");
for (int i = 0; i < 9; i++)
{
Console.Write($" {i + 1}{holePars[i],4} ");
for (int j = 0; j < 4; j++)
{
holeScores[i,j] = randomScores.Next(holePars[i] - 2, holePars[i] + 3);
Console.Write($"{holeScores[i,j],-9}");
totals[j] += holeScores[i,j];
}
Console.WriteLine();
}
Console.WriteLine($"Front {totals[0]} {totals[1]} {totals[2]} {totals[3]}");
See it work here:
https://dotnetfiddle.net/6XSLES
I like what you've done with the deviation from par for getting the random scores. If you really want to make this look more like a real golf game, you could also create weights for the scores, so golfers are more likely to end up closer to par. That might look like this:
https://dotnetfiddle.net/qoUOWf
The code at the above link makes you more than 4 times as likely to hit a par over a double eagle, where the original was purely random.
Additionally, it would be fun to also weight golfer skills once at the beginning, so you're less likely to have the same golfer get both triple bogeys and eagles.
How can I rotate (or shift) a 2D square array but leave any elements that are not on the "border" of the array unmoved?
Example:
1 2 3 4
12 13 14 5
11 15 16 6
10 9 8 7
What I want:
12 1 2 3
11 13 14 4
10 15 16 5
9 8 7 6
That was just an example. I need this to work on any square array of N width where 2 < N < 100
If the array is stored as a square .NET array of rank 2 the code is pretty simple mainly consisting of four loops - one for each edge:
var array = new [,] {
{ 1, 2, 3, 4, 5 },
{ 16, 17, 18, 19, 6 },
{ 15, 24, 25, 20, 7 },
{ 14, 23, 22, 21, 8 },
{ 13, 12, 11, 10, 9 }
};
// Rank = 2 and "square" and side length >= 2 checks removed for clarity.
var sideLength = array.GetLength(0);
// Save first element from top edge.
var element00 = array[0, 0];
// Rotate left edge.
for (var y = 1; y < sideLength; y += 1)
array[y - 1, 0] = array[y, 0];
// Rotate bottom edge.
for (var x = 1; x < sideLength; x += 1)
array[sideLength - 1, x - 1] = array[sideLength - 1, x];
// Rotate right edge.
for (var y = sideLength - 2; y >= 0; y -= 1)
array[y + 1, sideLength - 1] = array[y, sideLength - 1];
// Rotate top edge.
for (var x = sideLength - 2; x > 0; x -= 1)
array[0, x + 1] = array[0, x];
// Put saved element in place.
array[0, 1] = element00;
Now the original array has been rotated as described in the question.
If the array is stored as a one dimensional array it is easier to create a class to perform the rotation. This class can store properties (the array and the side length) that can be used across method calls to simplify the code.
The four loops contains the same logic even though they look different:
class ArrayRotator<T> {
public ArrayRotator(T[] array) {
if (array == null)
throw new ArgumentNullException("array");
var sideLength = (Int32) Math.Sqrt(array.Length);
if (sideLength*sideLength != array.Length)
throw new ArgumentException("Not a square.", "array");
Array = array;
SideLength = sideLength;
}
public T[] Array { get; private set; }
public Int32 SideLength { get; private set; }
public void RotateArray() {
if (SideLength < 3)
return;
// Save first element from top edge.
var element00 = Array[0];
// Rotate left edge.
for (var y = 1; y < SideLength; y += 1)
CopyElement(0, y, 0, y - 1);
// Rotate bottom edge.
for (var x = 1; x < SideLength; x += 1)
CopyElement(x, SideLength - 1, x - 1, SideLength - 1);
// Rotate right edge.
for (var y = SideLength - 2; y >= 0; y -= 1)
CopyElement(SideLength - 1, y, SideLength - 1, y + 1);
// Rotate top edge.
for (var x = SideLength - 2; x > 0; x -= 1)
CopyElement(x, 0, x + 1, 0);
// Put saved element in place.
Array[1] = element00;
}
void CopyElement(Int32 x1, Int32 y1, Int32 x2, Int32 y2) {
Array[GetIndex(x2, y2)] = Array[GetIndex(x1, y1)];
}
Int32 GetIndex(Int32 x, Int32 y) {
return y*SideLength + x;
}
}
Here is how to use the class:
var array = new [] {
1, 2, 3, 4,
12, 13, 14, 5,
11, 15, 16, 6,
10, 9, 8, 7
};
var arrayRotator = new ArrayRotator<Int32>(array);
arrayRotator.RotateArray();
Now the original array has been rotated as described in the question.
I found this question pretty interesting and fun, I've devised a little solution that works as long as the array conforms to a perfect square, this should work regardless of the side length.
NOTE: this is not the most optimized solution (I'm keen to try and make a more elegant solution, but this should suffice for now).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ArraySquareRotation
{
class Program
{
static void Main(string[] args)
{
int[] arr = new int[]
{
1, 2, 3, 4, 5, 3,
12, 13, 14, 5, 6, 1,
11, 15, 16, 6, 7, 22,
10, 9, 8, 7, 8, 30,
11, 15, 16, 6, 7, 22,
1, 2, 3, 4, 5, 3
};
// detect array size
int size = arr.Length;
// calculate the side length of the array (in terms of index)
int sideLength = BruteForceSquareDimensions(size);
// find the start of the last side of the square
int lastRowStartIndex = size - sideLength;
// a placeholder for us to generate a shifted array
int[] arrRotated = new int[size];
Console.WriteLine("Detected square with side length {0}", sideLength);
Console.WriteLine();
for (int i = 1; i <= size; i++)
{
// side rotation
if ((i % sideLength) == 0 && i != size)
{
// is multiple of
// right hand side, shift down
arrRotated[i + sideLength - 1] = arr[i - 1];
// left hand side, shift up
arrRotated[i + sideLength - (sideLength * 2)] = arr[i];
} else if (i < sideLength)
{
int lastRowIndex = sideLength * (sideLength - 1);
// first row, shift right
arrRotated[i] = arr[i - 1];
// last row, shit left
arrRotated[i + lastRowIndex - 1] = arr[i + lastRowStartIndex];
} else if(i < lastRowStartIndex)
{
// the inner square (this case may need some work)
arrRotated[i - 1] = arr[i - 1];
}
}
Console.WriteLine("Printing original array");
Console.WriteLine("======================");
PrintSquareArray(arr);
Console.WriteLine();
Console.WriteLine("Printing Shifted array");
Console.WriteLine("======================");
PrintSquareArray(arrRotated);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
/// <summary>
/// there is definately a better way.
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
static int BruteForceSquareDimensions(int size)
{
int sideLength = 0;
for (int i = 1; i < size; i++)
{
if ((i * i) == size)
{
sideLength = i;
}
}
return sideLength;
}
/// <summary>
/// This method just prints the array in the desired readable format
/// </summary>
/// <param name="arr"></param>
static void PrintSquareArray(int[] arr)
{
int size = arr.Length;
int sideLength = BruteForceSquareDimensions(size);
for(int i = 1; i <= size; i++)
{
if ((i % sideLength) == 0)
{
Console.WriteLine(arr[i - 1]);
}
else
{
Console.Write(arr[i - 1] + "\t");
}
}
}
}
}
The output should look as follows (Square):
Detected square with side length 4
Printing original array
======================
1 2 3 4
12 13 14 5
11 15 16 6
10 9 8 7
Printing Shifted array
======================
12 1 2 3
11 13 14 4
10 15 16 5
9 8 7 6
Press any key to exit
And here's a 6 by 6
Detected square with side length 6
Printing original array
======================
1 2 3 4 5 3
12 13 14 5 6 1
11 15 16 6 7 22
10 9 8 7 8 30
11 15 16 6 7 22
1 2 3 4 5 3
Printing Shifted array
======================
12 1 2 3 4 5
11 13 14 5 6 3
10 15 16 6 7 1
11 9 8 7 8 22
1 15 16 6 7 30
2 3 4 5 3 22
Press any key to exit
Here's what I got. Tested on the 4x4 you provided and the following 5x5 square array. Also, I am assuming the data is stored in jagged arrays, such that 1 array contains n arrays each of length n.
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
static int[][] Transform(int[][] old)
{
var maxIdx = old.Length-1;
var canvas = new List<int[]>();
//top border
var top = new List<int>();
top.Add(old[1][0]);
for (var i = 0; i < maxIdx; i++)
{
top.Add(old[0][i]);
}
//bottom border
var bottom = new List<int>();
for (var i = 1; i < maxIdx+1; i++)
{
bottom.Add(old[maxIdx][i]);
}
bottom.Add(old[maxIdx - 1][maxIdx]);
//middle
var middle = new List<int[]>();
for (var i = 1; i < maxIdx; i++) //for each inner array
{
var inside = new List<int>();
inside.Add(old[i + 1][0]);
for (var j = 1; j < maxIdx; j++)
{
inside.Add(old[i][j]);
}
inside.Add(old[i - 1][maxIdx]);
middle.Add(inside.ToArray());
}
//Rebuild
canvas.Add(top.ToArray());
foreach (var arr in middle)
{
canvas.Add(arr);
}
canvas.Add(bottom.ToArray());
return canvas.ToArray();
}
I'm having trouble with int[] arrays and adding them to a List<>. I'd like to add the values of my int[] array to something each loop but every time I do this my "something" gets the same value for every element I add. Very annoying. I understand arrays are always reference vars. However even the "new" key word doesn't seem to help. What needs to happen is to add result to some enumerated object like a List or Array or ArrayList.
Here's the codility question:
You are given N counters, initially set to 0, and you have two possible operations on them:
increase(X) − counter X is increased by 1,
max_counter − all counters are set to the maximum value of any counter.
A non-empty zero-indexed array A of M integers is given. This array represents consecutive operations:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max_counter.
For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the values of the counters after each consecutive operation will be:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
The goal is to calculate the value of every counter after all operations.
I copied some code from others and the variable "result" does indeed load the data correctly. I just wanted to copy it back to the main program so I could see it. The only method that works is += add it into a string. Thus losing any efficiency I might have gained.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testarray
{
class Program
{
static void Main(string[] args)
{
int[] A = new int[7];
A[0] = 3;
A[1] = 4;
A[2] = 4;
A[3] = 6;
A[4] = 1;
A[5] = 4;
A[6] = 4;
List<int[]> finish = solution(5, A);
}
public static List<int[]> solution(int N, int[] A)
{
int[] result = new int[N];
int maximum = 0;
int resetlimit = 0;
int iter = 0;
List<int[]> collected_result = new List<int[]>;
for (int K = 0; K < A.Length; K++)
{
if (A[K] < 1 || A[K] > N + 1)
{
throw new InvalidOperationException();
}
if (A[K] >= 1 && A[K] <= N)
{
if (result[A[K] - 1] < resetlimit)
{
result[A[K] - 1] = resetlimit + 1;
}
else
{
result[A[K] - 1]++;
}
if (result[A[K] - 1] > maximum)
{
maximum = result[A[K] - 1];
}
}
else
{
resetlimit = maximum;
result = Enumerable.Repeat(maximum, result.Length).ToArray<int>();
}
collected_result.Add(result);
}
// for (int i = 0; i < result.Length; i++)
//result[i] = Math.max(resetLimit, result[i]);
return collected_result;
}
}
}
This doesn't work, the collected_result ends up like:
(0,0,1,2,0)
(0,0,1,2,0)
(0,0,1,2,0)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
I know it's the line collected_result.Add(result); adding the reference each time to every instance of result in the List<>. Bother. I've tried adding "new" which is a compiler error. Finally in desperation I just added everything to a very long string. Can someone help me figure out how to properly load an object to pass back to main?
Easiest way to go:
Get a copy of your array before adding it to list:
collected_result.Add(result.ToArray());
Here is a Python solution:
def solution(A, N):
lenA = len(A)
k = 0
max_counter_value = 0
counters = [0 for x in range(0, N)]
for k in range(0, lenA):
if A[k] >= 1 and A[k] <= N:
counters[A[k] - 1] += 1
max_counter_value = max(counters)
if A[k] == N + 1:
counters = [max_counter_value for x in range(0, N)]
print counters
A = [3, 4, 4, 6, 1, 4, 4]
N = 5
solution(A, N)
Given a matrix[n,n] I want to find out how many ways we can reach from [0,0] to [n,n] non recursively.
My approach is to
Create a stuct Node to store row, col and path travelled so far
Add node to a Queue
Iterate thru queue till not empty . Increment row, increment col. Add to Queue
Print the path if row=n, col=n
Question
Is there a different way of storing row,col and path
If n is very large, storing nodes in Queue can be a problem. How can we avoid this?
Please not I am not looking for recursive solution.
I see such questions in many interview forums and so want to know if this would be the right approach.
Below is the structure of Node and the function
struct Node
{
public int row;
public int col;
public string path;
public Node(int r, int c, string p)
{
this.row = r;
this.col = c;
this.path = p;
}
}
public static void NextMoveNonRecursive(int max)
{
int rowPos;
int colPos;
string prevPath = "";
Node next;
while (qu.Count > 0)
{
Node current = qu.Dequeue();
rowPos = current.row;
colPos = current.col;
prevPath = current.path;
if (rowPos + 1 == max && colPos + 1 == max)
{
Console.WriteLine("Path = ..." + prevPath);
TotalPathCounter++;
}
if (rowPos + 1 < max)
{
if (prevPath == "")
prevPath = current.path;
prevPath = prevPath + ">" + (rowPos + 1) + "" + (colPos);
next = new Node(rowPos + 1, colPos, prevPath);
qu.Enqueue(next);
prevPath = "";
}
if (colPos + 1 < max)
{
if (prevPath == "")
prevPath = current.path;
prevPath = prevPath + ">" + (rowPos) + "" + (colPos+1);
next = new Node(rowPos, colPos+1, prevPath);
qu.Enqueue(next);
prevPath = "";
}
}
}
Let dp[i, j] be the number of paths from [0, 0] to [i, j].
We have:
dp[0, i] = dp[i, 0] = 1 for all i = 0 to n
dp[i, j] = dp[i - 1, j] + come down from all paths to [i - 1, j]
dp[i, j - 1] + come down from all paths to [i, j - 1]
dp[i - 1, j - 1] come down from all paths to [i - 1, j - 1]
for i, j > 0
Remove dp[i - 1, j - 1] from the above sum if you cannot increase both the row and the column.
dp[n, n] will have your answer.
Given a matrix [n,n], how many ways we can reach from [0,0] to [n,n] by increasing either a col or a row?
(n*2-2) choose (n*2-2)/2
If you can only go down or right (i.e., increase row or col), it seems like a binary proposition -- we can think of 'down' or 'right' as '0' or '1'.
In an nxn matrix, every path following the down/right condition will be n*2-2 in length (for example, in a 3x3 square, paths are always length 4; in a 4x4 square, length 6).
The number of total combinations for 0's and 1's in binary numbers of x digits is 2^x. In this case, our 'x' is n*2-2, but we cannot use all the combinations since the number of 'down's or 'right's cannot exceed n-1. It seems we need all binary combinations that have an equal number of 0's and 1's. And the solution is ... tada:
(n*2-2) choose (n*2-2)/2
In Haskell, you could write the following non-recursive function to list the paths:
import Data.List
mazeWays n = nub $ permutations $ concat $ replicate ((n*2-2) `div` 2) "DR"
if you want the number of paths, then:
length $ mazeWays n
Javascript solutions with sample
var arr = [
[1, 1, 1, 0, 0, 1, 0],
[1, 0, 1, 1, 1, 1, 0],
[1, 0, 1, 0, 1, 0, 0],
[1, 1, 0, 0, 1, 0, 0],
[1, 0, 0, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1]
];
function sols2(arr){
var h = arr.length,
w = arr[0].length,
i, j, current, left, top;
for(i = 0; i < h; i++){
for(j = 0; j < w; j++){
current = arr[i][j];
top = i === 0 ? 0.5 : arr[i - 1][j];
left = j === 0 ? 0.5 : arr[i][j-1];
if(left === 0 && top === 0){
arr[i][j] = 0;
} else if(current > 0 && (left > 0 || top > 0)){
arr[i][j] = (left + top) | 0;
} else {
console.log('a6');
arr[i][j] = 0;
}
}
}
return arr[h-1][w-1];
}
sols2(arr);
Given two bytes, how would I find the length of the common bits at the start of the two bytes.
For example:
9 == 00001001
6 == 00000110
Common prefix is 0000, length 4
I'm working in C#, so please stick to C# operations only.
Addendum: This particular piece of code will run thousands of times and needs to be very fast.
byte x = 9;
byte y = 6;
while ( x != y )
{
x >>= 1;
y >>= 1;
}
Basically, remove a bit from the right of each number until the two are equal. When they become equal, their bits are equal too.
You can keep track of the length of the prefix easily by introducing another variable. I'll leave that to you.
If you want it to be fast, and considering that you're dealing with bytes, why not precompute the values and return the answer in a single operation? Run this algorithm for all possible combinations of two bytes and store the result in a table.
You only have 2^8 * 2^8 = 2^16 possibilities (2^15 actually, because x = 6 and y = 9 is the same as x = 9 and y = 6). If you can afford the initial time and memory, precomputation should be fastest in the end.
Edit:
You got a solution that's at least better for precomputation and probably faster in general: find the leftmost 1 bit in x ^ y. Using this, build a table Pre where Pre[i] = position of leftmost 1 bit in i. You only need 2^8 bytes for this table.
EDIT: Thanks to the comments, I found that I misunderstood the problem. (Below is a fixed version).
With a lookup table:
readonly static int[] bytePrefix = new int[] {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
And use it XORing the two bytes:
bytePrefix[9 ^ 6]
I believe this is as fast as it can get, it's just one XOR operation and an array lookup (you can also change it to 2 array lookups, but it would use 256 times more memory and probably be slower, bitwise it really fast).
First get the binary difference between the bytes using the xor operator. Then you just shift bits out to the right until the difference is zero:
byte b1 = 6;
byte b2 = 9;
int length = 8;
for (int diff = b1 ^ b2; diff != 0; length--) diff >>= 1;
This will give you a minimum of calculations in the loop, so it will be rather fast.
If you're in a space-limited environment (which obviously you're not if you're using C#, but just in general) and can't afford a lookup table:
byte test = byte1 ^ byte2;
int length = 0;
if ((test & 0x80) == 0)
{
if ((test & 0x40) == 0)
{
if ((test & 0x20) == 0)
{
if ((test & 0x10) == 0)
{
// I think you get the idea by now.
// Repeat for the lower nibble.
}
else
length = 3;
}
else
length = 2;
}
else
length = 1;
}
This is basically an unraveled loop to find the first 1 bit in the XOR'd number. I don't think it can get any faster than this without the lookup table.
This can be restated as a simpler problem with a known fast solution:
Find the left-most true bit in X ^ Y.
Some code (apparently code can't immediately follow a bulleted list?!?)
int findCommonPrefix(long x, long y, out long common)
{
int prefixPlace = 0;
int testPlace = 32;
long w, mismatch = x ^ y;
do {
w = mismatch >> testPlace;
if (w != 0) { prefixPlace |= testPlace; mismatch = w; }
testPlace >>= 1;
} while (testPlace != 0);
common = x >> prefixPlace;
return 64 - prefixPlace;
}
This needs only 6 iterations to find the common prefix in a 64-bit long, the byte version will need only 3 iterations. Unroll the loop for even more speed.
Another approach using exclusive or (xor):
public int GetCommonPrefixLength(byte a, byte b)
{
int c = a ^ b;
int len = -1;
while ((++len < 8) && ((c & 0x80) == 0))
c = c << 1;
return len;
}
Here's a procedural way:
int r = 8;
while (a != b)
{
a >>= 1;
b >>= 1;
r -= 1;
}
Here's a way that uses a lookup table with just 256 entries:
int[] lookupTable;
void createLookupTable()
{
lookupTable = new int[256];
for (int a = 0; a <= 255; ++a)
{
int n = 8;
byte b = (byte)a;
while (b > 0) {
b >>= 1;
n -= 1;
}
lookupTable[a] = n;
}
}
int commonPrefix(byte a, byte b)
{
return lookupTable[a ^ b];
}
And just for fun here's a way to do it with LINQ:
int r = 8 - Enumerable.Range(0, 9).Where(n => a >> n == b >> n).First();
Here's one without a table or a loop:
len = (a^b) ? (7 - (int)Math.Log( a^b, 2)) : 8;
Explanation:
log2 X is the power to which the number 2 must be raised to obtain the value X. Since each bit in a binary number represents the next power of 2, you can use this fact to find the highest bit set (counting from 0):
2**0 = 1 = 0b0001; log2(1) = 0
2**1 = 2 = 0b0010; log2(2) = 1
2**1.6 =~3 = 0b0011; log2(3) =~1.6; (int)log2(3) = 1
2**2 = 4 = 0b0100; log2(4) = 2
...
2**3 = 8 = 0b1000; log2(8) = 3
So the code works by taking a XOR b, which sets only the bits which are different. If the result is non-zero, we use log2 to find the highest bit set. 7 less the result gives the number of leading zeros = the number of common bits. There is a special case when a XOR b == 0: log2(0) is -Infinity, so that won't work, but we know that all the bits must match, so the answer is 8.
int i;
for (i=0;i<sizeof(byte);i++)
if (a >> sizeof(byte)-i != b >> sizeof(byte)-i) break;
The 256-byte table versions seem quite nice; depending upon caching and branching issues, a 16-byte table version might or might not run faster. Something like:
/* Assumes table[16] is defined similarly to the table[256] in earlier examples */
unsigned int find_mismatch(unsigned char a, unsigned char b)
{
unsigned char mismatch;
mismatch = a^b;
if (mismatch & 0xF0)
return table[mismatch >> 4];
else
return table[mismatch]+4;
}
More instructions, including a branch, but since the table is now only 16 bytes it would take only one or two cache misses to fill entirely. Another approach, using a total of three lookups on a 16-byte table and a five-byte table, but no branching:
unsigned char table2[5] = {0,0,0,0,0xFF};
unsigned int find_mismatch(unsigned char a, unsigned char b)
{
unsigned char mismatch,temp2;
mismatch = a^b;
temp2 = table[mismatch >> 4];
return temp2 + (table2[temp2] & table[mismatch & 15]);
}
One would have to do some profiling in the real application to see whether the reduced cache load of the smaller tables was sufficient to offset the extra instructions.