-1

In a slightly modified TOH we have 4 pegs. So in turn we have total of 4^N disk positions. Now in one of the solutions which I was going through, a given state is represented using below code -

for(int disc = 0; disc < N; disc++){
        state += tower[disc]<<(disc*2);
    }

tower[disc] --> tower where disc is currently located, which can be (0,1,2,3)

if I use N=3 in above code, it gives me 63, which is 4^N -1. So the formula works, i.e 0-63 all 64 positions can be represented. but I am not able to understand the mathematical correlation.

Can you please explain how above formula can represent all possible disk positions and how it will change if we further change number of pegs or N to lets say 5.

G.D
  • 305
  • 5
  • 18
  • Can you elaborate on what you mean by "the formula works?" Is the goal to find a way of encoding disk positions using numbers and vice-versa, or to solve the problem by binary counting? – templatetypedef Aug 14 '17 at 21:45
  • @templatetypedef -goal is to understand the encoding of disk positions and how the above equation is working, not solving the problem. I am trying to understand how will i need to modify the give equation when value of N or number of pegs changes. – G.D Aug 15 '17 at 02:57

1 Answers1

1

Since you only have 4 pegs, the position of any disk can be encoded in just 2 bits (00, 01, 10, 11 => 0, 1, 2, 3). Thus the multiplication by 2 gives each disk 2 bits of independent memory space within the integer state, with the first disk starting at bit 0, second at bit 2, and so on... ith disk at (i - 1) * 2. The left shift << moves the data for each disk to its correct bit position.

However this code can be "unsafe" - if there were a mistake in the game logic somewhere else which caused a value of tower to be greater than 3, when shifted it will overflow its designated 2 bits of space. To prevent this, do a bitwise AND to clamp the data to [0, 3]:

state += (tower[disc] & 3) << (i * 2);

Note that you can also use bitwise OR instead of addition - state |= ....

From the example N = 3 provided it looks like all plates are starting from peg 4 (i.e. tower[3]). If you change to N = 5 it will once again give you 4^N - 1 = 1023, as all bits below N * 2 will be set to 1.

meowgoesthedog
  • 14,670
  • 4
  • 27
  • 40
  • Thanks a lot @meogoesthedog. A followup question - we have assigned 2 bits of independent memory in Integer state, then after to move to the right position we should do (1<<2*disc) right?, why are we doing (towerIndex<<2*disc). Also can please give an example use case where i'll have to change the multiplication factor of 2 to some other number. – G.D Aug 15 '17 at 02:53
  • 1
    @G.D because each element of `tower[disk]` is the data being stored in those 2-bit spaces. Not sure how you came up with `1 <<`. Let's replace the 2 with some integer `m` for the sake of argument - `m` is the *minimum* number of bits required to encode the *maximum* tower index, i.e. number of towers - 1. e.g. If you need between 5 and 8 towers you needed 3 bits per index (`m = 3`). Generally for `T` number of towers you need `m = ceil(log2(T))` bits per index. – meowgoesthedog Aug 15 '17 at 07:09
  • Lets say we have N=3 and pegs = 3. We will again need 2 bits to represent 3 pegs, so the equation remains unchanged. When all discs are on last tower[2], it gives a state = 42, whereas total possible states are 3^3 = 27, so 42 is an invalid state. What needs to be changed? – G.D Aug 15 '17 at 07:38
  • @G.D. It is **not** an invalid state. This is because 3 towers does not occupy the entire encoding range of 2 bits (= up to 4 towers). This means that there are unoccupied possible values of `state` in-between values for two adjacent `disc` indices. So the maximum value of state is (2 * 2^0 + 2 * 2^2 + 2 * 2^4) = 42, which is what you have. – meowgoesthedog Aug 15 '17 at 07:59
  • 1
    @G.D. note that you can encode the state data for 3 pegs *tightly* by multiplying by an increasing power of 3 each time; however you would need modulo math to decode at the other end. – meowgoesthedog Aug 15 '17 at 08:03
  • "multiplying by an increasing power of 3" - Can you show how the new equation will look like if we do this? – G.D Aug 15 '17 at 08:14
  • @G.D. Something like `for(int disc = 0, pow = 1; disc < N; disc++, pow *= 3) state += (tower[disc] % 3) * pow;`. There are probably more efficient ways of doing the multiplication (e.g. by shifts), but the modulo operation is the real elephant in the room here, so I'd say this is OK for the final form. – meowgoesthedog Aug 15 '17 at 08:17