Generate a 6 character string from a 15 character alphabet

In one of our projects at work, we recently discovered a particularly large method for generating a 6 character string from a 15 character alphabet. A few of us claimed "I bet we can get that in one line" which started a little internal game of code golf.

Your task is to beat us, which I have no doubt won't take long!

The original algorithm used the alphabet 0-9A-E, but we've experimented with other alphabets. There are therefore three subtasks.

1. Generate a 6 character string randomly selecting from an arbitrary hardcoded 15 character alphabet like ABC123!@TPOI098. (This is just an example, and should be customizable without affecting the byte count.)
2. Generate a 6 character string randomly selecting from a 15 character alphabet 0123456789ABCDE.
3. Generate a 6 character string randomly selecting from a 15 character alphabet of your choice (printable characters only please).

Each character should have equal chance of selection and repetition should be possible.

The best we have been able to manage for each of the subtasks is:

• "ABC123!@TPOI098" - 24 bytes
• "0123456789ABCDE" - 21 bytes
• Custom alphabet - 13 bytes

Your score is the sum of the bytes in each subtask's solution. i.e. our score is currently 58.

We've attempted using among others, CJam and Ruby. The original was in C#. Use any language you like, but we'll be interested to see solutions in these languages particularly

• Regarding multi-part challenges. Unfortunately, I don't have a good solution in this case, since these three subtasks are way too similar for it to make sense to split them up into multiple challenges. I've also been considering proposing an exception to that policy for multi-part challenges where the subtasks are just minor variations of the same challenge. (Although that still has the problem that sub-solutions can be taken from other answers.) So I won't mod-hammer this, and see what the community thinks. – Martin Ender Oct 15 '16 at 13:51
• "Your score is the sum of the bytes..." so my first example is unfortunate. I'll amend to another potential example – James Webster Oct 15 '16 at 14:11
• @MartinEnder My 2 cents: I think it's OK and will not VTC. Sure, I generally think a challenge with a single interesting task is better, but since these tasks are very similar, it's a lot better than a "golf-course" that says "do these 8 random unrelated tasks." Even though there is no interaction between tasks, in my eyes this challenge is not very different than say Golf all 16 logic gates. – DJMcMayhem Oct 15 '16 at 14:41
• Are there any time or memory limits? Do the subtasks have to be independent or are they allowed to share code? – Dennis Oct 15 '16 at 14:41
• Does "generate a string" mean the code has to actually generate a string value with the appropriate characters in it, or is outputting the six characters (not separated by space or newlines) acceptable? – DLosc Oct 15 '16 at 19:17

Jelly, 38 bytes

TryItOnline links A, B, and C.

A: ABC123!@£POI098, 22 bytes

“ABC123!@£POI098”Wẋ6X€


(thinking about a compression to lessen this one)

B: 0123456789ABCDE, 8 bytes:

ØHṖWẋ6X€


C:123456789ABCDEF (choice), 8 bytes:

ØHḊWẋ6X€


How?

...Wẋ6X€ - common theme
W     - wrap (string) in a list
ẋ6   - repeat six times
X€ - random choice from €ach

ØH...... - hexadecimal digit yield: "0123456789ABCDEF"

..Ṗ..... - pop: z[:-1] (B)

..Ḋ..... - dequeue: z[1:] (C)


CJam (23 + 14 + 10 = 47 bytes)

Arbitrary alphabet: 23 bytes (online demo)

{"ABC123!@TPOI098"mR}6*


Hexadecimal alphabet: 14 bytes (online demo)

{FmrAbHb'0+}6*


Custom alphabet: ABCDEFGHIJKLMNO, 10 bytes (online demo)

{Fmr'A+}6*


Dissection

The hexadecimal one is the interesting one:

{      e# Loop...
Fmr  e#   Select a random number from 0 to 14
AbHb e#   Convert to base 10 and then to base 17
e#   (i.e. add 7 if the number is greater than 9)
'0+  e#   Add character '0' (i.e. add 48 and convert from integer to character)
e#   Note that 'A' - '0' = 17
}6*    e# ...six times


The six characters are left on the stack and printed automatically.

• AbHb is brilliant. I thought about that general approach but _9>7*+ was too long. – Martin Ender Oct 15 '16 at 15:00

Perl, 46 + 26 + 26 = 98 bytes

A lot of the credit goes to @Dom Hastings for saving 13 bytes!

The 3 programs are pretty much identical, except for the alphabet that changes.

• Hardcoded alphabet (ABC123!@)POI098 in this example) -> 46 bytes:

say map{substr"ABC123!@)POI098",15*rand,1}1..6

• Fixed alphabet 0123456789ABCDE -> 26 bytes:

printf"%X",rand 15for 1..6

• Custom alphabet 0123456789ABCDE in that case -> 26 bytes:

printf"%X",rand 15for 1..6

You can put them all in a file to run them :

$cat 6chr_strings.pl say map{substr"ABC123!@)POI098",15*rand,1}1..6; say ""; printf"%X",rand 15for 1..6; say ""; printf"%X",rand 15for 1..6; say "";$ perl -M5.010 6chr_string.pl
CB8!8!
24D582
9ED58C


(the say ""; are just here to improve the output format)

• Good answers! I had pretty much the same for the first and last, but you can save a byte using say: say map{("ABC123!@)POI098"=~/./g)[rand 15]}1..6 and say map{(A..O)[rand 15]}1..6. For the second you can use printf: printf"%X",rand 15for 1..6 to save 11 over all! I'm sure Ton can advise on some arcane magic to save more too! – Dom Hastings Oct 17 '16 at 14:40
• Actually with the custom alphabet substr saves another: say map{substr"ABC123!@)POI098",15*rand,1}1..6 – Dom Hastings Oct 17 '16 at 14:42
• @DomHastings Hmm indeed, that's nice, well played! Thanks :-) – Dada Oct 17 '16 at 15:06
• I like that you removed the note about the code being straightforward :D – Dom Hastings Oct 17 '16 at 15:32
• @DomHastings with printf"%X", substr..rand and map, it's just a bit less obvious, so I let people enjoy perl magic with no spoilers! :D – Dada Oct 17 '16 at 15:36

R, 33+43+59 = 135 bytes

Arbitrary hard-coded alphabet (change the string to change the alphabet):

cat(sample(strsplit("ABC123!@TPOI098","")[[1]],6,1),sep="")


Alphabet of [0-9A-E]:

cat(sample(c(0:9,LETTERS[1:6]),6,1),sep="")


User-defined alphabet from stdin:

cat(sample(scan(,''),6,1),sep="")


All cases print the output word to stdout.

JavaScript (ES6), 167166164 163 bytes

Saved 1 byte thanks to Neil
Saved 2 bytes thanks to ETHproductions
Saved 1 byte thanks to premek.v

Hardcoded: "ABC123!@TPOI098" (58 bytes)

f=(n=6)=>n?"ABC123!@TPOI098"[Math.random()*15|0]+f(n-1):''


Fixed: "0123456789ABCDE" (58 57 bytes)

f=(n=6)=>n?f(n-1)+("ABCDE"[n=Math.random()*15|0]||n-5):''


Custom: "()+.1=>?M[afhnt" (51 49 48 bytes)

f=(n=6)=>n?(f+1)[Math.random()*15|0+5]+f(n-1):''

• (n=6)=>n?f(n-1)+("ABCDE"[n=Math.random()*15|0]||n-5):'' saves you a byte. – Neil Oct 15 '16 at 17:58
• 1/8+Math is great :) – ETHproductions Oct 16 '16 at 0:52
• But .1+JSON is better ;) – ETHproductions Oct 16 '16 at 13:49
• Or JSON+f ([object JSON](n => " (JNOS[]bcejnot") – ETHproductions Oct 16 '16 at 13:53
• @ETHproductions Nice one. :) – Arnauld Oct 16 '16 at 14:05

JavaScript (ES6), 184 bytes

Custom alphabet: 66 bytes

_=>"......".replace(/./g,c=>"ABC123!@TPOI098"[Math.random()*15|0])


0-9A-E: 63 bytes

_=>"......".replace(/./g,c=>"ABCDE"[n=Math.random()*15|0]||n-5)


0-9a-e: 55 bytes

_=>(Math.random()*11390625+1e8|0).toString(15).slice(1)


(Subtract 6 bytes if date-based randomness is permissible.)

• You can save a byte on the last one with **: _=>((Math.random()+1)*15**6|0).toString(15).slice(1) – ETHproductions Oct 16 '16 at 14:21
• @ETHproductions Surely that would make it ES7, rather than ES6? (Also, it looks like a 3-byte saving to me.) – Neil Oct 16 '16 at 21:21
• Yes, and it does appear to save 3 bytes. I must have included the f= in the byte count – ETHproductions Oct 20 '16 at 2:39

q, 42 bytes

A

19 bytes

6?"ABC123!@TPOI098"


B

14 bytes

6?15#.Q.n,.Q.A


C

9 bytes

6?15#.Q.a


(uses the first fifteen letters of the alphabet)

Julia (36+26+21 = 83)

join(rand(["ABC123!@TPOI098"...],6))

base(15,rand(15^6:15^7-1))

join(rand('a':'o',6))


CJam, 48 bytes

Arbitrary alphabet, 23 bytes:

{"ABC123!@TPOI098"mR}6*


Try it online!

Hex digits, 15 bytes:

{A,'F,65>+mR}6*


Try it online!

Alphabet ABCDEFGHIJKLMNO, 10 bytes:

{Fmr'A+}6*


Try it online!

• I had a bad idea. If we consider U+FFFE a character, ~c instead of 'A+ returns something technically printable. – jimmy23013 Oct 16 '16 at 15:34
• Maybe I'm wrong. I didn't find a definition of printable Unicode characters. – jimmy23013 Oct 16 '16 at 15:38

Ruby 47 + 37 + 31 = 115

Hardcoded: "ABC123!@TPOI098" (47)

(1..6).map{"5CABC123!@TPOI098".chars.sample}*''


Fixed: "0123456789ABCDE" (37)

(1..6).map{[*0..9,*?A..?E].sample}*''


Custom: "ABCDEFGHIJKLMNO" (31)

(1..6).map{[*?A..?O].sample}*''


05AB1E, 43 bytes

Arbitratry alphabet (ABC123!@TPOI098), 23 bytes Try it online

"ABC123!@TPOI098"6F.r¬?


Almost hexadecimal alphabet (0123456789ABCDE), 10 bytes Try it online

14Ýh6F.r¬?


Custom alphabet (abcdefghijklmno), 10 bytes Try it online

A15£6F.r¬?


Python 2, 70 + 70 + 64 = 204 bytes

from random import*
s=""
exec"s+=choice('ABC123!@TPOI098');"*6
print s

from random import*
s=""
exec"s+=choice('0123456789ABCDE');"*6
print s

from random import*
s=""
exec"s+=chr(randint(65,80));"*6
print s


Unfortunately, the second example is easier with the first method than something like choice([randint(48,57)),choice(65,69)])

• Why do you use from random import*? I think you can use import random and random.choice at least in the first two examples. – Roman Gräf Oct 15 '16 at 18:27
• import random random.choice is 27 but from random import* choice is 26, also import random as r r.choice is 27 – Karl Napf Oct 15 '16 at 19:26
• For the hex case, we can do a bit better by using format(randrange(8**8),'X'), I think. – DSM Oct 16 '16 at 15:37
• @DSM the problem is, there must be no F – Karl Napf Oct 16 '16 at 20:32

Vitsy, 27 + 24 22 + 13 10 = 6462 59 bytes

#1:

"ABC123!@TPOI098"6\[eR2+@O]


Try it online!

#2:

aH7+D4+H6\[eR2+@68*+O]


Try it online!

#3:

6\[eR5F-O]


Where the available characters are:

ﾖﾕﾔﾓﾒﾑﾐﾏﾎﾍﾌﾋﾊﾉﾈ


Try it online!

J, 24 + 24 + 18 10 = 58 bytes

8 bytes saved thanks to miles!

'ABC123!@TPOI098'{~?6#15
'0123456789ABCDE'{~?6#15
u:65+?6#15


Yeah, the second string isn't easily compressible in J:

u:47+23#.inv 12670682677028904639x
u:47+;(+i.@])/"1&.>1 10;18 5
('ABCDE',~1":i.10)
(toupper,hfd?6#15)
'0123456789ABCDE'


If a lowercase hex alphabet is fine, then there's ,hfd?6#15 for 9 bytes, as @miles noted.

Anyhow, ?6#15 is 6 random numbers between 0 and 15; {~ is take-from. u: converts numbers to chars. The last example encodes ABCDEFGHIJKLMNOP.

Bonus: general case

{~6?@##


{~6?@## is roughly:

{~6?@##  input: y
#  length of y
6  #   six copies of the length
?@    random numbers between 0 and the length
{~       taken from y

• On the second case, there's a builtin named hfd which converts to hex from decimal. You can get a 9 byte solution using ,hfd?6#15. The last case, just to have something easily read, uses the alphabet from 'A' for a 10 byte solution u:65+?6#15, making a total 24 + 9 + 10 = 45. – miles Oct 17 '16 at 3:51
• @miles I think the second case requires capitalized letters. As for the last case... haha, oops. I completely forgot about vectorized addition. – Conor O'Brien Oct 17 '16 at 11:08

PHP, 46+36+35=117 bytes

Hardcoded (46 bytes)

for(;$i++<6;)echo"ABC123!@TPOI098"[rand()%15];  (47 bytes) for(;$i++<6;)echo"ABC123!@TPOI098"[rand(0,14)];


for(;$j++<6;)echo dechex(rand()%15);  For uppercase, 46 bytes with Hardcoded version. Custom (A-O) (35 bytes) for(;$k++<6;)echo chr(rand(65,79));

• I don't think I can accept your 2nd part. a-e isn't the same as A-E – James Webster Oct 17 '16 at 8:38

Scala, 154 bytes

Hardcoded alphabet (54 bytes):

Seq.fill(6)("ABC123!@TPOI098"((math.random*14).toInt))


Hex alphabet (54 bytes):

Seq.fill(6)("0123456789ABCDE"((math.random*14).toInt))


Custom alphabet ABCDEFGHIJKLMNO (47 bytes):

Seq.fill(6)(('A'to'O')((math.random*14).toInt))


Explanation:

Seq.fill(6)(               //build a sequence of 6 elements, where each element is...
"ABC123!@TPOI098"(         //from the string
(math.random*14).toInt   //take a random char
)
)


'A'to'O' creates a sequence of 15 chars, A to O

Pip, 42 bytes

Hardcoded alphabet, 22 bytes:

L6ORC"ABC123!@TPOI098"


Hex digits, 11 bytes:

L6ORR15TB16


First 15 lowercase letters, 9 bytes:

L6Oz@RR15


Explanation

All three programs start with L6O: loop 6 times and output the given expression.

• RC"...": Random Choice of a character from the hard-coded string
• RR15TB16: RandRange(15), converted To Base 16
• z@RR15: lowercase alphabet z, indexed with RandRange(15)

Try it online!

Skript/skQuery, 108 bytes

Hardcoded (43 bytes):

random 6 char string from A@cD%F3h9JK{mN!


0123456789ABCDE (34 bytes):

random 6 char string from 0-9A-E


Choice (31 bytes):

random 6 char string from A-M

• Can you move the opening  to the left? – Addison Crump Oct 16 '16 at 16:01
• @VTCAKAVSMoACE No, it doesn't let you – Oliver Ni Oct 16 '16 at 16:38

Jolf, 26 + 14 + 13 = 51 bytes

Μ*S6d rG"ABC123!@TPOI098"E


Custom alphabet, 24 bytes. Try it here!

Μ*S6d r lp^0wά


0-9A-E alphabet, 14 bytes. Try it here! lp^0wά is lp (0-Z) sliced (l) from 0 to 15 (wά).

Μ*S6d r lp^1ά


1-9A-F alphabet, 13 bytes. Try it here! lp^1ά is the same as above, except from 1 to 16.

General method:

Μ*S6d r
M*S6d      map six newlines over this function:
r    select random element from array.


Other attempts (using string compression):

Μ*S6d rGμpwΞ \$AE


PowerShell v2+, 45 + 44 + 37 = 126 bytes

Fixed alphabet, 45 bytes

-join(0..5|%{'ABC123!@TPOI098'[(Random)%15]})


-join[char[]](0..5|%{Random(48..57+65..69)})


Custom alphabet (A to O), 37 bytes

-join[char[]](0..5|%{Random(65..79)})


All of these follow the same pattern -- loop from 0 to 5, each iteration selecting a Random character or ASCII value, casting that as a char-array if necessary, and -joining it together into a string. That string is left on the pipeline, and output is implicit.

Examples

PS C:\Tools\Scripts\golfing> -join(0..5|%{'ABC123!@TPOI098'[(Random)%15]})
32ATB3

PS C:\Tools\Scripts\golfing> -join(0..5|%{'ABC123!@TPOI098'[(Random)%15]})
III@B2

PS C:\Tools\Scripts\golfing> -join(0..5|%{'ABC123!@TPOI098'[(Random)%15]})
@302O@

PS C:\Tools\Scripts\golfing> -join[char[]](0..5|%{Random(48..57+65..69)})
74E117

PS C:\Tools\Scripts\golfing> -join[char[]](0..5|%{Random(48..57+65..69)})
09D7DD

PS C:\Tools\Scripts\golfing> -join[char[]](0..5|%{Random(65..79)})
COJDFI

PS C:\Tools\Scripts\golfing> -join[char[]](0..5|%{Random(65..79)})
EAKCNJ


Pyke, 35 bytes

Arbitary alphabet, 20 bytes

6V"ABC123!@TPOI098"H


Try it here!

Hex alphabet, 8 bytes

6V~J15<H


Try it here!

~J15< - "0123456789abcdefghijklmno..."[:15]


Custom alphabet, 7 bytes

6VG15<H


Try it here!

G15< - alphabet[:15]


Alphabet chosen: abcdefghijklmno

6V     - repeat 6 times:
...  -   get alphabet
H -  choose_random(^)
`
• This seems to output 6 chars separated by newline instead of a 6-char string. – Emigna Oct 17 '16 at 11:26
• The question doesn't state the output format. – Blue Oct 17 '16 at 11:29
• I see the words Generate a 6 character string in 4 places in the specification. – Emigna Oct 17 '16 at 11:30