Logo

Programming-Idioms

  • JS
  • Kotlin
  • Rust
  • Java
  • Go

Idiom #317 Random string

Create a string s of n characters having uniform random values out of the 62 alphanumeric values A-Z, a-z, 0-9

import "math/rand"
const alphanum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

func randomString(n int) string {
	a := make([]byte, n)
	for i := range a {
		a[i] = alphanum[rand.Intn(len(alphanum))]
	}
	return string(a)
}

Each of these runes fits in a single byte.
The default RNG can be run concurrently, as it incurs the cost of a Mutex.
Note that the package math/rand is not crypto-secure
import "math/rand"
const alphanum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

func randomString(n int, rng *rand.Rand) string {
	a := make([]byte, n)
	for i := range a {
		a[i] = alphanum[rng.Intn(len(alphanum))]
	}
	return string(a)
}

Using a custom rand.Rand instance lets you control the seed, and is also better for performance (lock-free).
Note that the package math/rand is not crypto-secure.
import "math/rand"
var alphanum = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")

func randomString(n int, rng *rand.Rand) string {
	a := make([]rune, n)
	for i := range a {
		a[i] = alphanum[rng.Intn(len(alphanum))]
	}
	return string(a)
}

This version is slightly more generic: it works with an alphabet of arbitrary runes, which don't need to fit in a single byte each.

Note that the package math/rand is not crypto-secure.
const s = ((n) => {
    const alphanum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    let s = "";
    for (let i = 0; i < n; i += 1) {
        s += alphanum[~~(Math.random() * alphanum.length)];
    }
    return s;
})(n);

~~ is a faster way to call Math.floor().

Note that Math.random is not cryptographically secure.
use rand::distributions::Alphanumeric;
use rand::Rng;
fn random_string(n: usize) -> String {
    rand::thread_rng()
        .sample_iter(Alphanumeric)
        .take(n)
        .map(char::from)
        .collect()
}
use rand::distributions::{Alphanumeric, DistString};
fn random_string(n: usize) -> String {
    Alphanumeric.sample_string(&mut rand::thread_rng(), n)
}
import static java.util.Arrays.asList;
import static java.util.Collections.shuffle;
String s = "";
Integer z[], i = 0;
char a[] = new char[62], c;
for (c = 'a'; c <= 'z'; ++c) a[i++] = c;
for (c = 'A'; c <= 'Z'; ++c) a[i++] = c;
for (c = '0'; c <= '9'; ++c) a[i++] = c;
z = new Integer[62];
for (i = 0; i < 62; ++i) z[i] = i;
shuffle(asList(z));
for (i = 0; i < n; ++i) s = s + a[z[i]];
function RandomString(Size: Integer): String;
const
  Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  Len = Length(Chars);
var
  i: Integer;
begin
  Result := '';
  SetLength(Result, Size);
  for i := 1 to Size do
  begin
    Result[i] := Chars[Random(Len)+1];
  end;
end; 

Pascal strings start at index 1.
Then const Len will be calculated at compile time.
Random(Len) returns a random number larger or equal to 0 and strictly less than Len.

New implementation...