So I have a for loop which goes like this:
for(span=N>>1;span;span>>=1)
I am assuming the start and end conditions are equivalent to as follows:
span = N>>1; //right shift N by 1 and initialize to span
while(span!=0)
{
span = span >> 1;
}
However it seems a little bizarre in the context of my code. Thanks in advance!
In every iteration you are dividing the variable span by 2 until it reaches 0.
so if initially N = 8, then values for span will be 4, 2, 1, 0 -> exit loop
That is correct.
The initializer sets span = N >> 1, right-shifting N by 1.
The loop condition is span, which is equivalent to span != 0.
Every time the loop comes around, span is right-shifted again by 1.
In the context of positive integers, this is equivalent to for(span=N/2;span>0;span/=2). However, without knowing your particular context I cannot comment whether this is or is not bizarre.
Short and sweet...Yes as far as you have shown the code, your interpretation stands firm and good.
Related
I was wondering what this code really means. I mean, I would like to know what it does, in what order, and what do ? and : signs mean; all explained.
printf(" %c", ((sq & 8) && (sq += 7)) ? '\n' : pieces[board[sq] & 15]);
Thanks.
The first argument, " %c", means that printf needs to print out a character.
The second argument is the character that the function prints.
In this case, the second argument is a ternary operator. You can read the link provided, but in short, it's basically a short-hand for an if-else block. This is what it looks like in your example:
((sq & 8) && (sq += 7)) ? '\n' : pieces[board[sq] & 15]
Let's separate it into three parts:
((sq & 8) && (sq += 7))
'\n'
pieces[board[sq] & 15]
The first part is a condition (if);
this expression (sq & 8) uses what is called a bitwise AND operation (read more here). Basically, 8 in binary is 1000 and that part checks whether sq has a 1 in that position (it can be 1000, 11000, 101000 etc.); if it does, that expression equals 8 (any number bigger than zero means true) and if it doesn't, it equals 0 (which means false).
&& means AND, it just means that both left and right expression need to be true
sq += 7 will add 7 to sq and if it's not 0, it is true.
The second part \n is returned (and in your case printed out) if the condition is true; else the third part will be printed out (pieces[board[sq] & 15]).
This is fairly obfuscated code, so it's best to try to understand it in the context in which it appears. By obfuscating it in this way, the auther is trying to tell you "you don't really need to understand the details". So lets try to understand what this does from the 'top down' inferring the details of the context, rather than bottom up.
printf prints -- in this case " %c", which is a space and a single character. The single character will either be (from the ?-: ternary expression)
a newline '\n'
a piece from space sq on the board
which it will be depends on the condition before the ? -- it first tests a single bit of sq (the & 8 does a bitwise and with a constant with one set bit), and if that bit is set, adds 7 to sq and prints the newline1, while if it is not set, will print the piece.
So now we really need to know the context. This is probably in a loop that starts with sq = 0 and increments sq each time in the loop (ie, something like for (int sq = 0; ...some condition...; ++sq)). So what it is doing is printing out the pieces on some row of the board, and when it gets to the end of the row, prints a newline and goes on to the next row. A lot of this depends on how exactly the board array is organized -- it would seem to be a 1D array with a 2D board embedded in it; the first row at indexes 0..7, the second at indexes 16..23, the third at indexes 32..39 and so on2.
1technically, when the bit is set, it tests the result of adding 7, but that will be true unless sq was -7, which is probably impossible from the context (a loop that starts at 0 and only increments from there).
2The gaps here are inferred from the test in the line of code -- those indexes with bit 3 set (for which sq & 8 will be true) are not valid board spaces, but are instead "gaps" between the rows. They might be used for something else, elsewhere in the code
Ok, thank you all! I've looked at it and it now works as expected. Thanks!
Image of problem
They lost me at the part where " = -1"
This is my understanding of the solution(so far).
They took the arr variable and scanned for elements that have a remainder of 1 when divided by 2. The = -1 part is where I'm confused.
What are the steps going on in here to replace those odd numbers as
negative 1?
Could someone explain in more depth how "arr[arr % 2 == 1]"
works? I think I have a very simple understanding of it.
Also, what is this particular technique called?
EDIT:
So I tried the solution they gave and it doesn't even run...Not sure if I did something wrong on my end.
Original site link: Source
Just like anything else you're trying to understand, take it step by step. Try printing out each of these intermediate expressions:
arr is a numpy array. This is important, because all of these steps depend on special numpy features - they wouldn't work on an ordinary list.
arr % 2 is an array of the same size, containing the parity of each of the original numbers - 0 for even, 1 for odd.
arr % 2 == 1 turns that into an array of booleans - False for even, True for odd.
arr[arr % 2 == 1] invokes numpy's special boolean indexing feature - it gives you a view of a (possibly discontiguous) subset of the array, wherever the index value was True. In this case, the view contains only the odd numbers of the original array.
arr[arr % 2 == 1] = -1 assigns the same value to each element in the view, overwriting all of the original odd numbers.
A key numpy concept used in all of the steps is "broadcasting" - basically, whenever an operation is attempted between an array and a single element, the single element is effectively replicated to match the size of the array. So, in arr % 2, the 2 notionally becomes an array of 2s, the same size as arr.
So I am relatively new to MatLab and I was assigned the task to find the average of all of the elements in the first or last rows and first or last columns in an array. My function is below:
function [ myavg ] = avg_outer( array_in )
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
[rowsin, colin]=size(array_in);
sum=0;
numelement=0;
currentpos=1;
currentrow=1;
j=1;
while currentpos>1 && currentpos<rowsin
sum=sum+array_in(currentrow,1)+array_in(currentrow,colin);
numelement=numelement+2;
currentrow=currentrow+1;
if currentrow==1
for j=1:1:colin
sum=sum+array_in(currentrow,j);
numelement=numelement+1;
end
elseif currentrow==rowsin
sum=sum+array_in(currentrow,j);
numelement=numelement+1;
end
end
myavg=sum/numelement;
end
When I run the function with a random array, I am not getting a result.
Any help or idea on where I went wrong?
Assuming I read the problem statement correctly, you can just create a mask that is true around the border, false in the middle, and take the mean of the masked version of A.
function [out_avg] = avg_outer(A)
mask = true(size(A));
mask(2:end-1,2:end-1) = false;
out_avg = mean(A(mask));
I couldn't really follow the logic in your posted code to debug it, sorry. Hopefully this answer shows you some of the advantages of vectorizing Matlab code.
The right way to do this is as per the answer from #kmac. But specifically related to your looping code, there are multiple issues.
currentpos starts at 1, which means that the while loop is never entered because currentpos > 1 is false. This is why you are getting NaN as the answer.
Even after fixing the above, you never increment currentpos so the while loop would never be exited (or more correctly would execute until an out of bounds error occurs).
Even after fixing the above, the first time into the while loop (in the 3rd line of the loop) you make currentrow = currentrow + 1;, which will be 2, means that the subsequent if statement is always false, and you will not be summing the first row of the matrix.
Even if you fix the above, the for loop adds all elements of the first row, but you've already accounted for the first and last elements of this row, so you're adding them into the sum twice.
Even if you fix the above, when currentrow == rowsin, i.e. the last row, you don't have a for loop to do the actual summation of the elements of the row. Noting that you don't want the first and last element because you've already added them in.
Consider the following C code
int j,n; //declaration
j=1; //initialization
while(j<=n) //while loop
j=j*2; //code ends here
What is the number of comparisons made in the execution of the loop in the above code?
I have tried the following: let increment of j is pow(2,0), pow(2,1), pow(2,2), etc. For some value of i so according to the question
pow(2,i)<=n
i<=(log n/log2)
What after this? The answer is floor(log n/log 2)+1 but how?
That code is undefined, there is no answer since you don't specify the value of n and as the code is written there's no chance for n to have a well-defined value when the loop runs.
n is never initialised, so technically the behaviour is undefined as you're using an uninitialised variable in while (j<=n).
If you want to set n to the largest possible integer value, use
n = INT_MAX
Which is defined in the standard include file <limits.h>
But, that will result in integer overflow due to j=j*2 happening after the j<=n check. One way round this would be to define n = INT_MAX / 2. Better still use a do / while loop rather than while and perform the check at the end.
Assuming that you initialized the variable n with a proper value, as you know you are going to pow(2,i)<=n which means i<=log{2}n (just inverting the function).
log{base 2}n = log n/log2 for the well known logarithmic property.
Now the calculation is exact when i is real but in this case i is an integer you won't get exactly that number so the correct index will be in the approximation of [floor(logn/log2);floor(logn/log2)+1] which will be the loop required for for pow(2,i)<=n<pow(2,i+1)
Let's do a simple example:
n=11; ln(n)/ln(2)=2.39/0.69=3.46
floor(3.46) = 3
floor(3.46)+1 = 4
i=1 i<=n: true: i*=2
i=2 i<=n: true: i*=2
i=4 i<=n: true: i*=2
i=8 i<=n: true: i*=2
i=16 i<=n: false=> don't loop
which is exactly four
Let us assume some n values
For n=1 loop executes 1 time.
For n=2 loop executes 2 times.
For n=3 loop executes 2 times.
For n=(4 to 7) loop executes 3 times.
For n=8 loop executes 4 times.
So for n values like 1,2,4,8,16... loop executes 1,2,3,4,5...
Therefore if you compare these values mathematically -
For n=2^k loop executes (k+1) times from n=2^k, k=log2n (logn with base 2)
So loop executes log2n(floor value)+1 times.
yes code will end you are not initializing n. First initialize it then calculte
You have an array in which every number is repeated odd number of times (but more than single occurrence). Exactly one number appears once. How do you find the number that appears only once?
e.g.: {1, 6, 3, 1, 1, 6, 6, 9, 3, 3, 3, 3}
The answer is 9.
I was thinking about having a hash table and then just counting the element whose count is 1.
This seems trivial and i am not using the fact that every other element is repeated an odd no of times. Is there a better approach.
I believe you can still use the basic idea of XOR to solve this problem in a clever fashion.
First, let's change the problem so that one number appears once and all other numbers appear three times.
Algorithm:
Here A is the array of length n:
int ones = 0;
int twos = 0;
int not_threes, x;
for (int i=0; i<n; ++i) {
x = A[i];
twos |= ones & x;
ones ^= x;
not_threes = ~(ones & twos);
ones &= not_threes;
twos &= not_threes;
}
And the element that occurs precisely once is stored in ones. This uses O(n) time and O(1) space.
I believe I can extend this idea to the general case of the problem, but possibly one of you can do it faster, so I'll leave this for now and edit it when and if I can generalize the solution.
Explanation:
If the problem were this: "one element appears once, all others an even number of times", then the solution would be to XOR the elements. The reason is that x^x = 0, so all the paired elements would vanish leaving only the lonely element. If we tried the same tactic here, we would be left with the XOR of distinct elements, which is not what we want.
Instead, the algorithm above does the following:
ones is the XOR of all elements that have appeared exactly once so far
twos is the XOR of all elements that have appeared exactly twice so far
Each time we take x to be the next element in the array, there are three cases:
if this is the first time x has appeared, it is XORed into ones
if this is the second time x has appeared, it is taken out of ones (by XORing it again) and XORed into twos
if this is the third time x has appeared, it is taken out of ones and twos.
Therefore, in the end, ones will be the XOR of just one element, the lonely element that is not repeated. There are 5 lines of code that we need to look at to see why this works: the five after x = A[i].
If this is the first time x has appeared, then ones&x=ones so twos remains unchanged. The line ones ^= x; XORs x with ones as claimed. Therefore x is in exactly one of ones and twos, so nothing happens in the last three lines to either ones or twos.
If this is the second time x has appeared, then ones already has x (by the explanation above), so now twos gets it with the line twos |= ones & x;. Also, since ones has x, the line ones ^= x; removes x from ones (because x^x=0). Once again, the last three lines do nothing since exactly one of ones and twos now has x.
If this is the third time x has appeared, then ones does not have x but twos does. So the first line let's twos keep x and the second adds x to ones. Now, since both ones and twos have x, the last three lines remove x from both.
Generalization:
If some numbers appear 5 times, then this algorithm still works. This is because the 4th time x appears, it is in neither ones nor twos. The first two lines then add x to ones and not twos and the last three lines do nothing. The 5th time x appears, it is in ones but not twos. The first line adds it to twos, the second removed it from ones, and the last three lines do nothing.
The problem is that the 6th time x appears, it is taken from ones and twos, so it gets added back to ones on the 7th pass. I'm trying to think of a clever way to prevent this, but so far I'm coming up empty.
For the problem as stated it is most likely that the most efficient answer is the O(n) space answer. On the other hand, if we narrow the problem to be "All numbers appear n times except for one which only appears once" or even "All numbers appear a multiple of n times except for one which only appears once" then there's a fairly straightforward solution for any n (greater than 1, obviously) which takes only O(1) space, which is to break each number into bits and then count how many times each bit is turned on and take that modulo n. If the result is 1, then it should be turned on in the answer. If it is 0, then it should be turned off. (Any other answer shows that the parameters of the problem did not hold). If we examine the situation where n is 2, we can see that using XOR does exactly this (bitwise addition modulo 2). We're just generalizing things to do bitwise addition modulo n for other values of n.
This, by the way, is what the other answer for n=3 does, it's actually just a complex way of doing bit-wise addition where it stores a 2-bit count for each bit. The int called "ones" contains the ones bit of the count and the int called "twos" contains the twos bit of the count. The int not_threes is used to set both bits back to zero when the count reaches 3, thus counting the bits modulo 3 rather than normally (which would be modulo 4 since the bits would wrap around). The easiest way to understand his code is as a 2-bit accumulator with an extra part to make it work modulo 3.
So, for the case of all numbers appearing a multiple of 3 times except the one unique number, we can write the following code for 32 bit integers:
int findUnique(int A[], int size) {
// First we set up a bit vector and initialize it to 0.
int count[32];
for (int j=0;j<32;j++) {
count[j] = 0;
}
// Then we go through each number in the list.
for (int i=0;i<size;i++) {
int x = A[i];
// And for each number we go through its bits one by one.
for (int j=0;j<32;j++) {
// We add the bit to the total.
count[j] += x & 1;
// And then we take it modulo 3.
count[j] %= 3;
x >>= 1;
}
}
// Then we just have to reassemble the answer by putting together any
// bits which didn't appear a multiple of 3 times.
int answer = 0;
for (int j=31;j>=0;j--) {
answer <<= 1;
if (count[j] == 1) {
answer |= 1;
}
}
return answer;
}
This code is slightly longer than the other answer (and superficially looks more complex due to the additional loops, but they're each constant time), but is hopefully easier to understand. Obviously, we could decrease the memory space by packing the bits more densely since we never use more than two of them for any number in count. But I haven't bothered to do that since it has no effect on the asymptotic complexity.
If we wish to change the parameters of the problem so that instead the numbers are repeated 5 times, we just change the 3s to 5s. Or we can do likewise for 7, 11, 137, 727, or any other number (including even numbers). But instead of using the actual number, we can use any factor of it, so for 9, we could just leave it as 3, and for even numbers we can just use 2 (and hence just use xor).
However, there is no general bit-counting based solution for the original problem where a number can be repeated any odd number of times. This is because even if we count the bits exactly without using modulo, when we look at a particular bit, we simply can't know whether the 9 times it appears represents 3 + 3 + 3 or 1 + 3 + 5. If it was turned on in three different numbers which each appeared three times, then it should be turned off in our answer. If it was turned on in a number which appeared once, a number which appeared three times, and a number which appeared five times, then it should be turned on in our answer. But with just the count of the bits, it's impossible for us to know this.
This is why the other answer doesn't generalize and the clever idea to handle the special cases is not going to materialize: any scheme based on looking at things bit by bit to figure out which bits should be turned on or off does not generalize. Given this, I don't think that any scheme which takes space O(1) works for the general case. It is possible that there are clever schemes which use O(lg n) space or so forth, but I would doubt it. I think that the O(n) space approach is probably the best which can be done in the problem as proposed. I can't prove it, but at this point, it's what my gut tells me and I hope that I've at least convinced you that small tweaks to the "even number" technique are not going to cut it.
I know that the subtext of this question is to find an efficient or performant solution, but I think that the simplest, readable code counts for a lot and in most cases it is more than sufficient.
So how about this:
var value = (new [] { 1, 6, 3, 1, 1, 6, 6, 9, 3, 3, 3, 3, })
.ToLookup(x => x)
.Where(xs => xs.Count() == 1)
.First()
.Key;
Good old LINQ. :-)
Test Score 100% with c#
using System;
using System.Collections.Generic;
// you can also use other imports, for example:
// using System.Collections.Generic;
// you can write to stdout for debugging purposes, e.g.
// Console.WriteLine("this is a debug message");
class Solution {
public int solution(int[] A) {
Dictionary<int, int> dic =new Dictionary<int, int>();
foreach(int i in A)
{
if (dic.ContainsKey(i))
{
dic[i]=dic[i]+1;
}
else
{
dic.Add(i, 1);
}
}
foreach(var d in dic)
{
if (d.Value%2==1)
{
return d.Key;
}
}
return -1;
}
}
Java, Correctness 100%, Performance 100%, Task score 100%
// you can also use imports, for example:
// import java.util.*;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
import java.util.HashMap;
class Solution {
/*Simple solution
Will be using HashMap(for performance) as Array,
only Key set is needed.
Initially tried with ArryList but there was performance issue with
that so switch to HashMap.
Iterate over the given array and if item is there in key set
remove it(coz you found your pair) otherwise add as new Key.
After full Iteration only one key will be there in the Map that is
your solution.
In Short: If pair is found, remove it from Map's Key set,
Last Key will be your solution
*/
public int solution(int[] A) {
//Map but used as Array
final HashMap<Integer, Boolean> mapHave = new HashMap<>();
//Iterate over given Array
for (int nIdx = 0; nIdx < A.length; nIdx++) {
//Current Item
Integer nVal = A[nIdx];
//Try to remove the current item, if item does not exists will
//return null and if condition will be true
if (mapHave.remove(nVal) == null) {
//current item not found, add it
mapHave.put(nVal, Boolean.TRUE);
}
}
//There will be only one key remaining in the Map, that is
//your solution
return mapHave.keySet().iterator().next();
}
}