Replacing Sequence with Random Number

Replacing sequence with random number

For generating unique and random-looking identifiers from a serial, using ciphers might be a good idea. Since their output is bijective (there is a one-to-one mapping between input and output values) -- you will not have any collisions, unlike hashes. Which means your identifiers don't have to be as long as hashes.

Most cryptographic ciphers work on 64-bit or larger blocks, but the PostgreSQL wiki has an example PL/pgSQL procedure for a "non-cryptographic" cipher function that works on (32-bit) int type. Disclaimer: I have not tried using this function myself.

To use it for your primary keys, run the CREATE FUNCTION call from the wiki page, and then on your empty tables do:

ALTER TABLE foo ALTER COLUMN foo_id SET DEFAULT pseudo_encrypt(nextval('foo_foo_id_seq')::int);

And voila!

pg=> insert into foo (foo_id) values(default);
pg=> insert into foo (foo_id) values(default);
pg=> insert into foo (foo_id) values(default);
pg=> select * from foo;
foo_id
------------
1241588087
1500453386
1755259484
(4 rows)

How to replace x to a random number

Here is a possible answer for your problem

input_string = 'GGI20-xxxxxxx'

import random
def replace_val(input_str):
str_list = list(input_str)
str_list = [str(i).replace('x',str(random.randint(0,9))) for i in str_list]
return ''.join(str_list)

replace_val(input_string)

o/p : 'GGI20-3428855' (it will vary as result will be random)

`

Replace Values in Column with Random Sequence of Values

The problem is that you are taking the row out of the dataframe, edit it, but don't put it back.

To get your code working, you can do

for(i in 1:nrow(df)) {
df$acq_date[i] <- sample(seq(as.Date('2020/12/15'), as.Date('2021/01/30'), by="day"), 1)
}

But i would suggest creating the randomdates all at one via

randomDates <- sample(seq(as.Date('2020/12/15'), as.Date('2021/01/30'), by="day"), nrow(df))

and then insert them into the df via

df$acq_date <- randomDates 

Multiple sequences of random numbers without replacement

Approach #1

For N >> n, we can use an iterative method with masking, so that at each iteration we pick one not-previously picked element per row. The implementation would look something like this -

R = np.arange(M)
mask = np.ones((M,N), dtype=bool)
idx = np.random.randint(0,N,(M))
mask[R,idx] = 0

for i in range(1,n):
lim = N-i
m2 = np.ones((M,lim), dtype=bool)
idx2 = np.random.randint(0,lim,(M))
m2[R,idx2] = 0
mask[mask] = m2.ravel()

out = np.nonzero(~mask)[1].reshape(-1,n)

If you need to randomize numbers per row, use the rand-trick as linked in question post :

out = np.take_along_axis(out, np.random.rand(M,n).argsort(1), axis=1)

If the constant array-creation with m2 bothers you, re-use after initializing before looping, while keeping the rest of the code same -

m2 = np.ones((M,N-1), dtype=bool)
for i in range(1,n):
lim = N-i
idx2 = np.random.randint(0,lim,(M))
m2[R,idx2] = 0
mask[mask] = m2.ravel()
m2[R,idx2] = 1
m2 = m2[:,:-1]

Approach #2 Similar to Approach #1, but the initialization part does most of the job to setup unqiue random numbers per row. An additional while iterative part takes care of the rows that could not assign unique ones. With N >> n, we will hardly need to iterate though. The implementation would look something like this -

# https://stackoverflow.com/a/51915131/ @Divakar
def random_num_per_grp(L):
# For each element in L pick a random number within range specified by it
r1 = np.random.rand(np.sum(L)) + np.repeat(np.arange(len(L)),L)
offset = np.r_[0,np.cumsum(L[:-1])]
return r1.argsort()[offset] - offset

R = np.arange(M)
mask = np.ones((M,N), dtype=bool)
idx = np.random.randint(0,N,(M,n))
mask[R[:,None],idx] = 0

rows_notdone = mask.sum(1)!=N-n
while np.any(rows_notdone):
idx0 = random_num_per_grp(mask[rows_notdone].sum(1))
steps = np.r_[0,mask.sum(1).cumsum()[:-1]]
flat_idx0 = steps[rows_notdone] + idx0

m2 = np.ones(mask.sum(), dtype=bool)
m2[flat_idx0] = 0
mask[mask] = m2

rows_notdone = mask.sum(1)!=N-n

out = np.nonzero(~mask)[1].reshape(-1,n)

Replace ending integer number of a function with another random integer number

If the method names follow a specific pattern as you say, you can use the getattr function to get the method based on a calculated name:

def roll(self):
sense = SenseHat()
self.number = random.randint(1,6)
getattr(self, 'dice_%d' % self.number)()

But in this case it's more likely that you can combine your dice_# methods into one method that makes use of the dice number of the instance instead, resulting in more elegant code:

def roll(self):
sense = SenseHat()
self.number = random.randint(1,6)
self.dice()

def dice(self):
print(self.number)
# so something with self.number

How can I replace the random values in a column in Studio with a sequential number set?

If you don't care about the order, then you may use ROW_NUMBER ordered by the data column:

WITH cte AS (
SELECT data, 1000 + ROW_NUMBER() OVER (ORDER BY data) rn
FROM yourTable
)

If you also want to update then use:

UPDATE cte
SET data = rn;

Why are my random numbers not changing accordingly in Excel?

The behaviour you described is a bug.

First, if we replace line:

Randomize i

with:

Randomize 0

we can see that on Windows we get the exact same repeated values as we would get on a Mac:

image1

This immediately suggested to me that there can only be 2 possible explanations:

  1. Maybe the algorithm is different
  2. There is an issue and the value of i is not passed/read correctly.

In order to find a rule, I used a separate method (brute-forced i/x) and found the following magic numbers. Again, if we replace line:

Randomize i

with:

#If Mac Then
Dim arr() As Variant: arr = Array(26489, 63707, 185603, 15365, 92513)
Randomize i / arr(i - 1)
#Else
Randomize i
#End If

we get the same results on Windows and Mac.

I could not find a clear pattern in those magic numbers so I discarded that the algorithm is different. This left me with finding the issue/bug.

After some trial and error I found that if we pass a Double data type to the Randomize method it does not read the full 8 bytes but instead only reads the first 4 bytes. That is why dividing by those magic numbers worked, because the resulting numbers (of those divisions) were using the first 4 bytes (including the exponent bits) instead of the 8 full bytes.

The fix is to offset (to the left) the double value by 4 bytes. Here is the final code that works on both Windows and Mac:

Option Explicit

#If Mac Then
#If VBA7 Then
Public Declare PtrSafe Function CopyMemory Lib "/usr/lib/libc.dylib" Alias "memmove" (Destination As Any, Source As Any, ByVal Length As LongPtr) As LongPtr
#Else
Public Declare Function CopyMemory Lib "/usr/lib/libc.dylib" Alias "memmove" (Destination As Any, Source As Any, ByVal Length As Long) As Long
#End If
#End If

Sub Macro1()
Dim i As Long
Dim j As Long
Dim RA1 As Variant
ReDim RA1(1 To 5)

For i = 1 To 5
Rnd (-1)

#If Mac Then
Dim d As Double

d = CDbl(i)
CopyMemory d, ByVal VarPtr(d) + 4, 4 'Read the last 4 double bytes into the first 4
Randomize d
#Else
Randomize i
#End If

For j = 1 To 5
RA1(j) = Rnd
Next j

With Sheets("Sheet1")
.Range(Cells(i, 1), Cells(i, 5)).Value = RA1
End With
Next i
End Sub

You'll have noticed that I've also added Option Explicit, declared all variables and indented the code.



Related Topics



Leave a reply



Submit