<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Uniquely Identifying Particles With Hashes
In many cases, one can just identify particles by their position in the particle array, e.g. using sim.particles[5]. However, in cases where particles might get reordered in the particle array finding a particle might be difficult. This is why we added a hash attribute to particles.
In REBOUND particles might get rearranged when a tree code is used for the gravity or collision routine, when particles merge, when a particle leaves the simulation box, or when you manually remove or add particles. In general, therefore, the user should not assume that particles stay at the same index or in the same location in memory.  The reliable way to access particles is to assign them hashes and to access particles through them. 
Note
Step1:  We can now not only access the Earth particle with
Step2:  but also with
Step3:  We can access particles with negative indices like a list.  We can get the last particle with
Step4:  Details
We can also access particles through their hash directly.  However, to differentiate from passing an integer index, we have to first cast the hash to the underlying C datatype.  We can do this through the rebound.hash function
Step5:  which corresponds to particles[0] as it should.  sim.particles[999] would try to access index 999, which doesn't exist in the simulation, and REBOUND would raise an AttributeError.
When we above set the hash to a string, REBOUND converted this to an unsigned integer using the same rebound.hash function
Step6:  The hash attribute always returns the appropriate unsigned integer ctypes type. (Depending on your computer architecture, ctypes.c_uint32 can be an alias for another ctypes type).
So we could also access the earth with
Step7:  The numeric hashes could be useful in cases where you have a lot of particles you don't want to assign individual names, but you still need to keep track of them individually as they get rearranged
Step8:  Possible Pitfalls
The user is responsible for making sure the hashes are unique.  If two particles share the same hash, you could get either one when you access them using their hash (in most cases the first hit in the particles array).  Two random strings used for hashes have a $\sim 10^{-9}$ chance of clashing.  The most common case is setting a hash to 0
Step9:  Here we expected to get back the first particle, but instead got the last one.  This is because we didn't assign a hash to the last particle and it got automatically set to 0.  If we give hashes to all the particles in the simulation, then there's no clash
Step10:  Due to details of the ctypes library, comparing two ctypes.c_uint32 instances for equality fails
Step11:  You have to compare the value
<ASSISTANT_TASK:>
Python Code:
import rebound
sim = rebound.Simulation()
sim.add(m=1., hash=999)
sim.add(a=0.4, hash="mercury")
sim.add(a=1., hash="earth")
sim.add(a=5., hash="jupiter")
Explanation: Uniquely Identifying Particles With Hashes
In many cases, one can just identify particles by their position in the particle array, e.g. using sim.particles[5]. However, in cases where particles might get reordered in the particle array finding a particle might be difficult. This is why we added a hash attribute to particles.
In REBOUND particles might get rearranged when a tree code is used for the gravity or collision routine, when particles merge, when a particle leaves the simulation box, or when you manually remove or add particles. In general, therefore, the user should not assume that particles stay at the same index or in the same location in memory.  The reliable way to access particles is to assign them hashes and to access particles through them. 
Note: When you don't assign particles a hash, they automatically get set to 0.  The user is responsible for making sure hashes are unique, so if you set up particles without a hash and later set a particle's hash to 0, you don't know which one you'll get back when you access hash 0.  See Possible Pitfalls below.
In this example, we show the basic usage of the hash attribute, which is an unsigned integer.
End of explanation
sim.particles[2]
Explanation: We can now not only access the Earth particle with:
End of explanation
sim.particles["earth"]
Explanation: but also with
End of explanation
sim.particles[-1]
Explanation: We can access particles with negative indices like a list.  We can get the last particle with
End of explanation
from rebound import hash as h
sim.particles[h(999)]
Explanation: Details
We can also access particles through their hash directly.  However, to differentiate from passing an integer index, we have to first cast the hash to the underlying C datatype.  We can do this through the rebound.hash function:
End of explanation
h("earth")
sim.particles[2].hash
Explanation: which corresponds to particles[0] as it should.  sim.particles[999] would try to access index 999, which doesn't exist in the simulation, and REBOUND would raise an AttributeError.
When we above set the hash to a string, REBOUND converted this to an unsigned integer using the same rebound.hash function:
End of explanation
sim.particles[h(1424801690)]
Explanation: The hash attribute always returns the appropriate unsigned integer ctypes type. (Depending on your computer architecture, ctypes.c_uint32 can be an alias for another ctypes type).
So we could also access the earth with:
End of explanation
for i in range(1,100):
    sim.add(m=0., a=i, hash=i)
sim.particles[99].a
sim.particles[h(99)].a
Explanation: The numeric hashes could be useful in cases where you have a lot of particles you don't want to assign individual names, but you still need to keep track of them individually as they get rearranged:
End of explanation
sim = rebound.Simulation()
sim.add(m=1., hash=0)
sim.add(a=1., hash="earth")
sim.add(a=5.)
sim.particles[h(0)]
Explanation: Possible Pitfalls
The user is responsible for making sure the hashes are unique.  If two particles share the same hash, you could get either one when you access them using their hash (in most cases the first hit in the particles array).  Two random strings used for hashes have a $\sim 10^{-9}$ chance of clashing.  The most common case is setting a hash to 0:
End of explanation
sim = rebound.Simulation()
sim.add(m=1., hash=0)
sim.add(a=1., hash="earth")
sim.add(a=5., hash="jupiter")
sim.particles[h(0)]
Explanation: Here we expected to get back the first particle, but instead got the last one.  This is because we didn't assign a hash to the last particle and it got automatically set to 0.  If we give hashes to all the particles in the simulation, then there's no clash:
End of explanation
h(32) == h(32)
Explanation: Due to details of the ctypes library, comparing two ctypes.c_uint32 instances for equality fails:
End of explanation
h(32).value == h(32).value
Explanation: You have to compare the value
End of explanation
<END_TASK>