-2

This may be a rather simple problem. I'll show an example.

I have A and B (take it as client and server set-up). A does the following (2^10) mod 23 = 12.

It then sends the value 12 over to B

Now, B has the equation 12 = (2^x) mod 23. (It has the modulus and the base value). How would I find the value 10? I tried inverse mod, but that seems to work only for a power of -1. Google doesn't seem to help much either. Just the math help would be great, but if there is a Java function for it, it would be even better.

E_net4
  • 27,810
  • 13
  • 101
  • 139
  • 3
    Could you please post your code as well as some inputs and outputs so we can better understand where you're struggling/What you are trying to do – GBlodgett Jul 31 '18 at 13:46
  • @GBlodgett There is no code involved in my question, although I will need to write the code for it later. From 12 = (2^10) mod 23, I need a way to find the value 10, assuming that it is unknown. That means, I have 12 = (2^r) mod 23, and need to find r. – dancerdiver101 Jul 31 '18 at 13:48
  • Hint: the inverse function for (2^x) is log base 2 (implemented `Math.log(x)/Math.log(2);` in Java) – Ben Jones Jul 31 '18 at 13:48
  • 5
    So is this more of a maths question than a programming question? – khelwood Jul 31 '18 at 13:50
  • @khelwood It is a math question, but I need it for programming. That means, if there is a function in a java package which will help me solve this, I need that more than a math solution right now. – dancerdiver101 Jul 31 '18 at 13:51
  • 3
    The problem with finding the inverse of the modulus operator is that it is a many-to-one function, so you can't reproduce the values that were originally passed in, unless you know they were in some range, say [0, 23). – Ben Jones Jul 31 '18 at 13:54
  • 1
    This is called the [discrete logarithm](https://en.wikipedia.org/wiki/Discrete_logarithm), and is a well studied problem. – President James K. Polk Jul 31 '18 at 15:51

3 Answers3

1

The property we can use to solve this is that A can only have 23 unique outputs. Therefore you can precalculate all the values that you might pass into the left hand side of B, and record the inputs that get those values, until you get a full list:

2^0 % 23 == 1
2^1 % 23 == 2
2^2 % 23 == 4
2^3 % 23 == 8
2^4 % 23 == 16
2^5 % 23 == 9
2^6 % 23 == 18
2^7 % 23 == 13
2^8 % 23 == 3
2^9 % 23 == 6
2^10 % 23 == 12
   .
   .
   .

You will find that after the 10th output, there is a repeating sequence of the above values, so those are the only values that B should take as input.

Ben Jones
  • 652
  • 6
  • 21
  • I don't agree. I think that the reasoning does not prove that you won't find the 23th value at the 1 000 000th step. So it does not tell when the program will end or if it will end in a reasonable amount of time. – Arnaud Denoyelle Jul 31 '18 at 14:20
  • You've given the proof in your answer, it is mathematically proven to repeat, and therefore you will never get a value outside of the ones I listed. I'm not sure what it is that you don't agree with... – Ben Jones Jul 31 '18 at 14:25
  • Oh yeah I see what you're saying. Yeah in the general case (for arbitrary _A_), you can't be sure that you will get all the values for sure. – Ben Jones Jul 31 '18 at 14:29
1

Sorry to add this:

Basically after certain loop due to 2^11 mod 23 = 1 and (a * b) mod c = (a mod c) * (b mod c) mod c, which is the mod multiplication rule.

So we can definitely use the loop to get the final result using just a simple list (no matter how big the i might be) as:

 int getMod(int i) {
     int[] ret = new int {1, 2, 4, 8, 16, 9, 18, 13, 3, 6, 12};
     return ret[i % 11];
 }

To OP, there is a tutorial explaining well about the math solving program problems. Might it be helpful.

Hearen
  • 7,420
  • 4
  • 53
  • 63
0

You can sometimes find the solution by trying with the first values and see what happens :

public static void main(String[] args) {
    for(int i = 0; i< 100; i++) {
        System.out.println("" + i +" : " + (int)Math.pow(2, i) % 23);
    }
}

Here is the result :

0 : 1
1 : 2
2 : 4
3 : 8
4 : 16
5 : 9
6 : 18
7 : 13
8 : 3
9 : 6
10 : 12
11 : 1
12 : 2
13 : 4
14 : 8
15 : 16
16 : 9
17 : 18
18 : 13
19 : 3
20 : 6
21 : 12
22 : 1
23 : 2
24 : 4
25 : 8
26 : 16
27 : 9
28 : 18
29 : 13
30 : 3
31 : 5
32 : 5
33 : 5

I cut the output but for each value after 33, the result will be 5, because of some overflows.

But you can see that there is a loop in the results : 1 2 4 8 16 9 18 13 3 6 12.

This is explained because of this mathematical relationship :

(2^(n+1)) mod 23 = ((2 ^ n) mod 23) * 2 mod 23

(in english, multiply the previous result by 2 and apply a mod 23 if necessary)

So

  • when n = 10, the result is 12
  • when n = 11, the result is 12 * 2 mod 23 = 24 mod 23 = 1 and there you go for a new cycle 1, 2, 4 etc

Hence the answer is that eihter you find the corresponding value in the first 10 tries or you will never find it. Trying to find a value of 5 or 7 will end in an infinite loop.

Arnaud Denoyelle
  • 29,980
  • 16
  • 92
  • 148
  • This is a good method, but what if the numbers are bigger? It may be a bit impractical to try 1000s of numbers... – dancerdiver101 Jul 31 '18 at 14:07
  • @dancerdiver101 I edited the answer. I showed that there is actually a loop (which is mathematically proven) in the results. – Arnaud Denoyelle Jul 31 '18 at 14:26
  • @dancerdiver101 A more general reasoning is that there is a relationship `u(n+1) = f(u(n))` and because of the modulo, `u(n)` has less that `23` distinct values so you are sure to loop at most at the `23th` step. Same reasonning could be applied if you had `1000` instead of `23`, you are sure to loop before the `1000th` step. – Arnaud Denoyelle Jul 31 '18 at 14:44