Related
So for a given prime number 31, how can I write a hash function for a string parameter?
Here is my attempt.
private int hash(String key){
int c = 31;
int hash = 0;
for (int i = 0; i < key.length(); i++ ) {
int ascii = key.charAt(i);
hash += c * hash + ascii;
}
return (hash % sizetable);} // sizetable is an integer which is declared outside. You can see it as a table.length().
So, since I can not run any other function in my work and I need to be sure about the process here, I need your answers and help! Thank you so much.
Your implementation looks quite similar to what is documented as standard String.hashCode() implementation, this even uses also 31 as prime factor, so it should be good enough.
I just would not assign 31 to a variable, but declare a private static final field or use it directly as magic number - not OK in general, but might be OK in this case.
Additionally you should add some tests - if you already know about the concept of unit tests - to prove that your method gives different hashes for different strings. And pick the samples clever, so they are different (for the case of the homework ;)
This question already has answers here:
How can I perform multiplication without the '*' operator?
(31 answers)
Closed 4 years ago.
I had an interesting interview yesterday where the interviewer asked me a classic question: How can we multiply two numbers in Java without using the * operator. Honestly, I don't know if it's the stress that comes with interviews, but I wasn't able to come up with any solution.
After the interview, I went home and breezed through SO for answers. So far, here are the ones I have found:
First Method: Using a For loop
// Using For loop
public static int multiplierLoop(int a, int b) {
int resultat = 0;
for (int i = 0; i < a; i++) {
resultat += b;
}
return resultat;
}
Second Method: Using Recursion
// using Recursion
public static int multiplier(int a, int b) {
if ((a == 0) || (b == 0))
return 0;
else
return (a + multiplier(a, b - 1));
}
Third Method: Using Log10
**// Using Math.Log10
public static double multiplierLog(int a, int b) {
return Math.pow(10, (Math.log10(a) + Math.log10(b)));
}**
So now I have two questions for you:
Is there still another method I'm missing?
Does the fact that I wasn't able to come up with the answer proves that my logical reasoning isn't strong enough to come up with solutions and that I'm not "cut out" to be a programmer? Cause let's be honest, the question didn't seem that difficult and I'm pretty sure most programmers would easily and quickly find an answer.
I don't know whether that has to be a strictly "programming question". But in Maths:
x * y = x / (1 / y) #divide by inverse
So:
Method 1:
public static double multiplier(double a, double b) {
// return a / (1 / b);
// the above may be too rough
// Java doesn't know that "(a / (b / 0)) == 0"
// a special case for zero should probably be added:
return 0 == b ? 0 : a / (1 / b);
}
Method 2 (a more "programming/API" solution):
Use big decimal, big integer:
new BigDecimal("3").multiply(new BigDecimal("9"))
There are probably a few more ways.
There is a method called [Russian Peasant Multiplication][1]. Demonstrate this with the help of a shift operator,
public static int multiply(int n, int m)
{
int ans = 0, count = 0;
while (m > 0)
{
if (m % 2 == 1)
ans += n << count;
count++;
m /= 2;
}
return ans;
}
The idea is to double the first number and halve the second number repeatedly till the second number doesn’t become 1. In the process, whenever the second number become odd, we add the first number to result (result is initialized as 0) One other implementation is,
static int russianPeasant(int n, int m) {
int ans = 0;
while (m > 0) {
if ((m & 1) != 0)
ans = ans + n;
n = n << 1;
m = m >> 1;
}
return ans;
}
refer :
https://www.geeksforgeeks.org/russian-peasant-multiply-two-numbers-using-bitwise-operators/
https://www.geeksforgeeks.org/multiplication-two-numbers-shift-operator/
[1]: https://web.archive.org/web/20180101093529/http://mathforum.org/dr.math/faq/faq.peasant.html
Others have hit on question 1 sufficiently that I'm not going to rehash it here, but I did want to hit on question 2 a little, because it seems (to me) the more interesting one.
So, when someone is asking you this type of question, they are less concerned with what your code looks like, and more concerned with how you are thinking. In the real world, you won't ever actually have to write multiplication without the * operator; every programming language known to man (with the exception of Brainfuck, I guess) has multiplication implemented, almost always with the * operator. The point is, sometimes you are working with code, and for whatever reason (maybe due to library bloat, due to configuration errors, due to package incompatibility, etc), you won't be able to use a library you are used to. The idea is to see how you function in those situations.
The question isn't whether or not you are "cut out" to be a programmer; skills like these can be learned. A trick I use personally is to think about what, exactly, is the expected result for the question they're asking? In this particular example, as I (and I presume you as well) learned in grade 4 in elementary school, multiplication is repeated addition. Therefore, I would implement it (and have in the past; I've had this same question in a few interviews) with a for loop doing repeated addition.
The thing is, if you don't realize that multiplication is repeated addition (or whatever other question you're being asked to answer), then you'll just be screwed. Which is why I'm not a huge fan of these types of questions, because a lot of them boil down to trivia that you either know or don't know, rather than testing your true skills as a programmer (the skills mentioned above regarding libraries etc can be tested much better in other ways).
TL;DR - Inform the interviewer that re-inventing the wheel is a bad idea
Rather than entertain the interviewer's Code Golf question, I would have answered the interview question differently:
Brilliant engineers at Intel, AMD, ARM and other microprocessor manufacturers have agonized for decades as how to multiply 32 bit integers together in the fewest possible cycles, and in fact, are even able to produce the correct, full 64 bit result of multiplication of 32 bit integers without overflow.
(e.g. without pre-casting a or b to long, a multiplication of 2 ints such as 123456728 * 23456789 overflows into a negative number)
In this respect, high level languages have only one job to do with integer multiplications like this, viz, to get the job done by the processor with as little fluff as possible.
Any amount of Code Golf to replicate such multiplication in software IMO is insanity.
There's undoubtedly many hacks which could simulate multiplication, although many will only work on limited ranges of values a and b (in fact, none of the 3 methods listed by the OP perform bug-free for all values of a and b, even if we disregard the overflow problem). And all will be (orders of magnitude) slower than an IMUL instruction.
For example, if either a or b is a positive power of 2, then bit shifting the other variable to the left by log can be done.
if (b == 2)
return a << 1;
if (b == 4)
return a << 2;
...
But this would be really tedious.
In the unlikely event of the * operator really disappearing overnight from the Java language spec, next best, I would be to use existing libraries which contain multiplication functions, e.g. BigInteger.multiply(), for the same reasons - many years of critical thinking by minds brighter than mine has gone into producing, and testing, such libraries.
BigInteger.multiply would obviously be reliable to 64 bits and beyond, although casting the result back to a 32 bit int would again invite overflow problems.
The problem with playing operator * Code Golf
There's inherent problems with all 3 of the solutions cited in the OP's question:
Method A (loop) won't work if the first number a is negative.
for (int i = 0; i < a; i++) {
resultat += b;
}
Will return 0 for any negative value of a, because the loop continuation condition is never met
In Method B, you'll run out of stack for large values of b in method 2, unless you refactor the code to allow for Tail Call Optimisation
multiplier(100, 1000000)
"main" java.lang.StackOverflowError
And in Method 3, you'll get rounding errors with log10 (not to mention the obvious problems with attempting to take a log of any number <= 0). e.g.
multiplier(2389, 123123);
returns 294140846, but the actual answer is 294140847 (the last digits 9 x 3 mean the product must end in 7)
Even the answer using two consecutive double precision division operators is prone to rounding issues when re-casting the double result back to an integer:
static double multiply(double a, double b) {
return 0 == (int)b
? 0.0
: a / (1 / b);
}
e.g. for a value (int)multiply(1, 93) returns 92, because multiply returns 92.99999.... which is truncated with the cast back to a 32 bit integer.
And of course, we don't need to mention that many of these algorithms are O(N) or worse, so the performance will be abysmal.
For completeness:
Math.multiplyExact(int,int):
Returns the product of the arguments, throwing an exception if the result overflows an int.
if throwing on overflow is acceptable.
If you don't have integer values, you can take advantage of other mathematical properties to get the product of 2 numbers. Someone has already mentioned log10, so here's a bit more obscure one:
public double multiply(double x, double y) {
Vector3d vx = new Vector3d(x, 0, 0);
Vector3d vy = new Vector3d(0, y, 0);
Vector3d result = new Vector3d().cross(vx, vy);
return result.length();
}
One solution is to use bit wise operations. That's a bit similar to an answer presented before, but eliminating division also. We can have something like this. I'll use C, because I don't know Java that well.
uint16_t multiply( uint16_t a, uint16_t b ) {
uint16_t i = 0;
uint16_t result = 0;
for (i = 0; i < 16; i++) {
if ( a & (1<<i) ) {
result += b << i;
}
}
return result;
}
The questions interviewers ask reflect their values. Many programmers prize their own puzzle-solving skills and mathematical acumen, and they think those skills make the best programmers.
They are wrong. The best programmers work on the most important thing rather than the most interesting bit; make simple, boring technical choices; write clearly; think about users; and steer away from stupid detours. I wish I had these skills and tendencies!
If you can do several of those things and also crank out working code, many programming teams need you. You might be a superstar.
But what should you do in an interview when you're stumped?
Ask clarifying questions. ("What kind of numbers?" "What kind of programming language is this that doesn't have multiplication?" And without being rude: "Why am I doing this?") If, as you suspect, the question is just a dumb puzzle with no bearing on reality, these questions will not produce useful answers. But common sense and a desire to get at "the problem behind the problem" are important engineering virtues.
The best you can do in a bad interview is demonstrate your strengths. Recognizing them is up to your interviewer; if they don't, that's their loss. Don't be discouraged. There are other companies.
Use BigInteger.multiply or BigDecimal.multiply as appropriate.
Alright, so I'm working on a leveling system in java. I have this from my previous question for defining the level "exp" requirements:
int[] levels = new int[100];
for (int i = 1; i < 100; i++) {
levels[i] = (int) (levels[i-1] * 1.1);
}
Now, my question is how would I determine if an exp level is between two different integers in the array, and then return the lower of the two? I've found something close, but not quite what I'm looking for here where it says binary search. Once I find which value the exp falls between I'll be able to determine a user's level. Or, if anyone else has a better idea, please don't hesitate to mention it. Please excuse my possible nooby mistakes, I'm new to Java. Thanks in advance to any answers.
Solved, thanks for all the wonderful answers.
With a general sorted array of numbers, binary search is the way to go, which is O(log n). But because there is a mathematical relationship between the numbers (each number is 1.1 times the previous one), take advantage of that fact. You're looking for the maximum exponent level such that
levels[0] * Math.pow(1.1, level) <= exp
Solving for level,
level = log{base 1.1}(exp / levels[0])
Taking advantage of the fact that loga(b) = ln(b) / ln(a)...
int level = (int) Math.log(exp/levels[0]) / Math.log(1.1);
Because of the mathematical relationship, you just need this calculation, and no searching, so it's O(1).
double base = 1;
double factor = 1.1;
for (double score : Arrays.asList(1.0, 1.1, 1.3, 8.6, 9.46))
{
int level = (int) (Math.log(score / base) / Math.log(factor));
System.out.println(level);
}
Prints
0
1
2
22
23
You can use the built-in binary search method:
int exp = . . .
int pos = Arrays.binarySearch(levels, exp);
if (pos < 0) {
// no exact match -- change pos to the insertion index
pos = -pos - 1;
// Now exp is between levels[pos] and levels[pos - 1]
// (or less than levels[0] if pos is now 0)
} else {
// exp is exactly equal to levels[pos]
}
Yes, you should do binary search here as your array elements seem to be sorted.
This follows from the way you initialize them.
You can also do linear search of course but the former is better.
Why not just use the Arrays Class?
int valueToFind = 100;
int index = Arrays.binarySearch(levels, valueToFind)
Is there a Java function to convert a positive int to a negative one and a negative int to a positive one?
I'm looking for a reverse function to perform this conversion:
-5 -> 5
5 -> -5
What about x *= -1; ? Do you really want a library function for this?
x = -x;
This is probably the most trivial question I have ever seen anywhere.
... and why you would call this trivial function 'reverse()' is another mystery.
Just use the unary minus operator:
int x = 5;
...
x = -x; // Here's the mystery library function - the single character "-"
Java has two minus operators:
the familiar arithmetic version (eg 0 - x), and
the unary minus operation (used here), which negates the (single) operand
This compiles and works as expected.
Another method (2's complement):
public int reverse(int x){
x~=x;
x++;
return x;
}
It does a one's complement first (by complementing all the bits) and then adds 1 to x. This method does the job as well.
Note: This method is written in Java, and will be similar to a lot of other languages
No such function exists or is possible to write.
The problem is the edge case Integer.MIN_VALUE (-2,147,483,648 = 0x80000000) apply each of the three methods above and you get the same value out. This is due to the representation of integers and the maximum possible integer Integer.MAX_VALUE (-2,147,483,647 = 0x7fffffff) which is one less what -Integer.MIN_VALUE should be.
Yes, as was already noted by Jeffrey Bosboom (Sorry Jeffrey, I hadn't noticed your comment when I answered), there is such a function: Math.negateExact.
and
No, you probably shouldn't be using it. Not unless you need a method reference.
original *= -1;
Simple line of code, original is any int you want it to be.
Necromancing here.
Obviously, x *= -1; is far too simple.
Instead, we could use a trivial binary complement:
number = ~(number - 1) ;
Like this:
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
int iPositive = 15;
int iNegative = ( ~(iPositive - 1) ) ; // Use extra brackets when using as C preprocessor directive ! ! !...
System.out.println(iNegative);
iPositive = ~(iNegative - 1) ;
System.out.println(iPositive);
iNegative = 0;
iPositive = ~(iNegative - 1);
System.out.println(iPositive);
}
}
That way we can ensure that mediocre programmers don't understand what's going on ;)
The easiest thing to do is 0- the value
for instance if int i = 5;
0-i would give you -5
and if i was -6;
0- i would give you 6
You can use the minus operator or Math.abs. These work for all negative integers EXCEPT for Integer.MIN_VALUE!
If you do 0 - MIN_VALUE the answer is still MIN_VALUE.
For converting a negative number to positive. Simply use Math.abs() inbuilt function.
int n = -10;
n = Math.abs(n);
All the best!
In kotlin you can use unaryPlus and unaryMinus
input = input.unaryPlus()
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/unary-plus.html
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/unary-minus.html
You can use Math:
int x = Math.abs(-5);
I hacked up a recursive function in Java for a homework problem in my Stats class, that looked something like this:
public static int d (int k, int n) {
if (n == 1) return 1;
else if (n > k) return 0;
else return n*d(k-1, n) + n*d(k-1,n-1);
}
I then plugged (20, 8) into this function, and got 998,925,952. My professor, however, said that this answer was wrong, and after rethinking my code over and over again, I decided to try the same thing in Matlab:
function t = d(k,n)
t = 0;
if n == 1
t = 1;
elseif n > k
t = 0;
else
t = n*d(k-1, n) + n*d(k-1, n-1);
end
This function, apparently, gave me the right answer with the above input, 6.1169 * 10^17.
This has been bugging me all day, and I have absolutely no idea why two seemingly identical programs in two different languages would give me completely different results. Can anyone help explain this?
Your Matlab routine is probably working on floating-point input, so it will compute in floating-point.
Your Java routine has integer types; 6.1169e17 is way outside the supported range, so it overflows. Try changing your types to float or double.
611692004959217300 is much larger than 2147483647 which is the integer MAX_VALUE in Java.
I got 611692004959217300 by running
function d (k, n) {
if (n == 1) return 1;
else if (n > k) return 0;
else return n*d(k-1, n) + n*d(k-1,n-1);
}
console.log(d(20,8));
in Firebug.
Consider what the maximum value an int can have, which is what you've got in Java. Now consider what the maximum value a double can have, which is MATLAB's default type.
Java integers are 4 bytes in size, so the number looks too big (greater than 2^31). You should try again using "long" or "double" as datatype for your variables.