11
\$\begingroup\$

A Tiefling is a character race, from Dungeons and Dragons, that has this list of possible traits:

  • small horns
  • fangs or sharp teeth
  • a forked tongue
  • catlike eyes
  • six fingers on each hand
  • goat-like legs
  • cloven hoofs
  • a forked tail
  • leathery or scaly skin
  • red or dark blue skin
  • cast no shadow or reflection
  • exude a smell of brimstone.

Given a list of Tiefling traits as input, randomly pick 1d4 + 1 (uniform distribution from 2-5) traits from that list and output them.

This challenge uses the standard definition of random, and the number and trait selection from the list must separately conform to definition 1 from here:

  • All possible [numbers] should be produced with the same probability;
  • All possible [traits] should be produced with the same probability;

You are allowed to pick randomly from the list by first shuffling it and taking the top 1d4+1 traits, so long as the shuffle does not favour any item in the list. Repeat selections of the same trait are not allowed.

Here is a non-golfed implementation in Javascript:

const dice = (n, s, a, doSum) => {
  const die = () => Math.floor(Math.random() * s) + 1;
  const dieResults = Array.from(Array(n)).map(each => {
    return die();
  });
  const sum = dieResults.reduce((sum, curr) => sum + curr + a, 0);
  // logging not required here
  console.log(`rolled '${dieResults.join(` + ${a}, `)} + ${a}${doSum ? ` = ${sum}`:''}'`);
  return doSum ? dieResults.reduce((sum, curr) => sum + curr + a, 0) : dieResults.map(each => each + a);
};

const shuffleSlice = (num, array) => array
  .map(value => ({
    value,
    sort: Math.random()
  }))
  .sort((a, b) => a.sort - b.sort)
  .map(({
    value
  }) => value).slice(0, num);

// you can take the list as a string or an actual list
const tieflingTraits = "small horns; fangs or sharp teeth; a forked tongue; catlike eyes; six fingers on each hand; goat-like legs; cloven hoofs; a forked tail; leathery or scaly skin; red or dark blue skin; cast no shadow or reflection; exude a smell of brimstone".split(/;\s+/);

// calling the function
console.log(shuffleSlice(dice(1, 4, 1, true), tieflingTraits))

// outputs like
//  ['goat-like legs', 'cast no shadow or reflection', 'a forked tongue']

This is so shortest in bytes wins.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Some of these are self-contradictory. Does it have red skin or dark blue skin? Leathery or scaly? \$\endgroup\$ Oct 4, 2022 at 17:08
  • \$\begingroup\$ @DarrelHoffman take it up with the developers of D&D ... 🤷🏻‍♂️ \$\endgroup\$ Oct 4, 2022 at 18:10
  • \$\begingroup\$ That's okay, I was just wondering if you wanted e.g. "red skin" and "dark blue skin" to be separate, mutually-exclusive options, but a bit late to change this now. \$\endgroup\$ Oct 4, 2022 at 18:27
  • \$\begingroup\$ @DarrelHoffman oh, if that were the case they'd be new lines, or I'd have specified you need to split on 'or'. But thanks for checking \$\endgroup\$ Oct 4, 2022 at 19:22

15 Answers 15

7
\$\begingroup\$

Factor + dice, 22 bytes

[ ROLL: 1d4+1 sample ]

Try it online!

A quotation (anonymous function) that takes a list of strings as input and outputs a uniformly random sample of 1d4+1 items of said list.

\$\endgroup\$
5
\$\begingroup\$

Jelly,  7  6 bytes

Ẋṫ4XN¤

A monadic Link that accepts a list of lists of characters and yields another with 2-5 random entries.

Try it online!

How?

Ẋṫ4XN¤ - Link: list, A
Ẋ      - get a shuffled copy of A
     ¤ - nilad followed by link(s) as a nilad:
  4    -   four
   X   -   random choice from 1-4
    N  -   negate
 ṫ     - tail (the shuffled copy) from (that) 1-indexed index
\$\endgroup\$
5
\$\begingroup\$

Retina, 22 bytes

?O`
,3G`¶
?&0A`¶
?&0A`

Try it online! Explanation:

?O`

Uniformly shuffle the input.

,3G`¶

Keep the first four (0-indexed) newline characters, which also ends up keeping the first five lines.

?&0A`¶

50% chance to delete the first newline character including the first two lines.

?&0A`

50% chance to delete the first line.

\$\endgroup\$
4
  • \$\begingroup\$ Does this output 1-4 or 2-5 from the list? Also trying to figure if your two lots of 50% make this uniform? \$\endgroup\$ Oct 2, 2022 at 16:36
  • \$\begingroup\$ I must have misread how it work then. You're "keeping the first four lines." Then either deleting one (50%) or two (50%) lines. But that never leads to picking 5 traits, only 2, 3 or 4 traits....? \$\endgroup\$ Oct 2, 2022 at 16:44
  • 1
    \$\begingroup\$ @AncientSwordRage You're right, and I made that same mistake in my Charcoal answer... \$\endgroup\$
    – Neil
    Oct 2, 2022 at 16:46
  • 2
    \$\begingroup\$ The calculation is easier to see with the corrected version: there are separate 50% chances of deleting 2 and 1 lines; imagine a two-bit number where each bit has a 50% chance of being 0 or 1 then the number as a whole has a 25% chance of each of 00, 01, 10 and 11; this means that 0-3 lines are uniformly randomly deleted, leaving 2-5 lines. \$\endgroup\$
    – Neil
    Oct 2, 2022 at 16:48
5
\$\begingroup\$

Raku, 18 bytes

*.pick(pick 2..5:)

Try it online!

pick 2..5: picks a random number from 2 to 5, then gives that as an argument to the pick method on the input list, randomly choosing that many elements from it.

\$\endgroup\$
3
  • \$\begingroup\$ It would be good to see it working on the input in the question \$\endgroup\$ Oct 2, 2022 at 18:01
  • \$\begingroup\$ @AncientSwordRage Changed. (I was just trying to keep the TIO link to a minimal length.) \$\endgroup\$
    – Sean
    Oct 2, 2022 at 22:04
  • \$\begingroup\$ I like it! I was thrown by having the footer run it 10 times, but it makes sense \$\endgroup\$ Oct 2, 2022 at 22:52
4
\$\begingroup\$

Goruby, 16 bytes

->a{a.s rn 2..5}

Attempt This Online!

Ruby, 23 bytes

->a{a.sample rand 2..5}

Attempt This Online!

\$\endgroup\$
4
\$\begingroup\$

Excel (ms365), 52 bytes

=TAKE(SORTBY(A1:A12,RANDARRAY(12)),RANDBETWEEN(2,5))

enter image description here

\$\endgroup\$
4
\$\begingroup\$

Python (Full program), 58 bytes

  • -1 byte thanks to @The Fifth Marshal
from random import*;print(sample([*open(0)],randint(2,5)))

Attempt This Online!

Python (Function), 51 bytes

  • -7 bytes thanks to @Jonathan Allan
lambda a:sample(a,randint(2,5))
from random import*

Attempt This Online!

\$\endgroup\$
6
  • \$\begingroup\$ I'm noticing the input has some semicolons and the output sometimes has newline characters? \$\endgroup\$ Oct 2, 2022 at 16:26
  • \$\begingroup\$ @AncientSwordRage the output will always have newline characters, you can use print(*sample(... at the cost of one byte to not print them. Not sure if it's nececairy \$\endgroup\$
    – mousetail
    Oct 2, 2022 at 16:42
  • \$\begingroup\$ i.stack.imgur.com/k1vQR.jpg \$\endgroup\$ Oct 2, 2022 at 16:46
  • 1
    \$\begingroup\$ You can remove the space before the * for -1 byte. \$\endgroup\$ Oct 2, 2022 at 17:27
  • 1
    \$\begingroup\$ ...avoid all the oddness and save seven by writing a function which accepts a list, ATO \$\endgroup\$ Oct 3, 2022 at 9:14
4
\$\begingroup\$

Japt, 6 5 7 bytes

ö¬o2+4ö

Try it

ö¬o2+4ö     :Implicit input of array
ö¬          :Random permutation
  o         :Pop & return this many elements
   2+       :  Two plus
     4ö     :  Random integer in range [0,4)
\$\endgroup\$
0
3
\$\begingroup\$

Bash + coreutils, 20

shuf -n$[RANDOM%4+2]

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 21 bytes

WS⊞υι≔⟦⟧θF⁺²‽⁴⊞θ‽⁻υθθ

Try it online! Link is to verbose version of code. Explanation:

WS⊞υι

Read in the list of possible traits.

≔⟦⟧θ

Start with no traits selected.

F⁺²‽⁴

Repeat 2-5 times uniformly randomly.

⊞θ‽⁻υθ

Pick a trait uniformly randomly from the list of traits not already picked.

θ

Output the final list of picked traits.

\$\endgroup\$
2
\$\begingroup\$

MathGolf, 17 14 bytes

mÅvαá├mÅ~;3w⌠<

Try it online.

I really hate this language sometimes.. -_- This should in theory have been áv3w⌠< (6 bytes), but due to a number of bugs, it ended up as 17 bytes instead.

Explanation:

Explanation of the intended solution, and why it didn't work due to bugs:

á       # Sort the (implicit) input-list by:
 v      #  A random integer in the range [-2147483648,2147483647]
  3w    # Push a random integer in the range [0,3]
    ⌠   # Increase it by 2 (to have the range [2,5] instead)
     <  # Only keep that meany leading items from the shuffled list
        # (after which the entire stack is output implicitly as result)

Bugs:

  1. MathGolf changes all spaces in string inputs to ", " (try it online with explicit print). This bug is likely because MathGolf supports multiple inputs both separated by commas and spaces, so when a string or string-list is used that contains spaces, it incorrectly splits them, before interpreting the splitted string as string again..
    This is fixed with the leading mÆ',- (only works because the input-strings are all without commas)

    EDIT: Apparently using ' quotes for strings instead of " fixes this issue.

  2. MathGolf's sort-by builtin á apparently evaluates its body once in some cases, because áv and áf both result in an unsorted list and act similar as á1 would.
    This is fixed by replacing it with mÅvαá├mÅ~;:

m       # Map over the (implicit) input-list,
 Å      # using 2 characters as inner code-block:
  v     #  Push a random integer from the range [-2147483648,2147483647]
   α    #  Pair the string and random integer together
á       # After the map: sort by:
 ├      #  The left (a third bug, should have been `┤` for right..) item: the random integer
m       # After the sort-by: map again,
 Å      # using 2 characters as inner code-block:
  ~     #  Dump the string and random integer to the stack
   ;    #  And discard the random integer

After which we can use the 3w⌠< explained above to finish the program.

\$\endgroup\$
2
\$\begingroup\$

PowerShell, 25 bytes

Input comes from the pipeline.

random -c(random -mi 2 6)

Try it online!

Ungolfed:

Get-Random -Count (Get-Random -Minimum 2 -Maximum 6)

Straightforward; Get-Random with "-Count x" will randomly select x objects from the pipeline input.

The verb "Get-" can (in dire situations as code golf) be dropped from cmdlet names <Verb>-<Noun>; if PS finds no program or cmdlet named "<noun>", it will add "Get-" and try to find that. Disclaimer Use this for golfing only, never in normal scripts; it'll slow down the script (because it will try to find <noun>.exe in the path first every time), and may start unrelated programs on other systems.

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 7 bytes

.rY5ŸΩ£

Very straight-forward, but can't find anything shorter. (I initially read the challenge description wrong as 1-4 random outputs, which would be possible in 4 bytes. 2-5 however is a bit longer.)

Try it online.

Explanation:

.r       # Randomly shuffle the (implicit) input-list
  Y5Ÿ    # Push a list in the range [2,5]: [2,3,4,5]
     Ω   # Pop and get a random value from this list
      £  # Only leave that many items from the shuffled list
         # (after which the result is output implicitly)
\$\endgroup\$
2
  • \$\begingroup\$ Huh, why does 2-5 take 3 more bytes than 1-4? \$\endgroup\$
    – Neil
    Oct 11, 2022 at 7:30
  • \$\begingroup\$ @Neil 1-4 could be done with 4ãΩÙ (get a random item from the cartesian power of 4, and uniquify it). \$\endgroup\$ Oct 11, 2022 at 20:20
1
\$\begingroup\$

J-uby, 35 24 bytes

Port of my Ruby answer.

~:sample&(-:rand^(2..5))

Attempt This Online!

\$\endgroup\$
0
\$\begingroup\$

APL (Dyalog Unicode), 23 bytes (15 chars)

{⍵[(≢⍵)?⍨1+?4]}

Explanation:

{              } ⍝ defun:
          1+?4   ⍝ roll a d4, add 1
   (≢⍵)?⍨        ⍝ generate random indices
 ⍵[           ]  ⍝ index them into ⍵ to get final traits
\$\endgroup\$
3
  • \$\begingroup\$ 13: ⊢⌷⍨(1+?4)⊂⍤?≢ \$\endgroup\$
    – user106914
    Oct 5, 2022 at 10:28
  • \$\begingroup\$ @faunlocke just checked, it doesn't save bytes, it actually adds bytes. \$\endgroup\$
    – Joao-3
    Oct 5, 2022 at 11:57
  • 1
    \$\begingroup\$ APL is usually counted in SBCS bytes instead of UTF-8, where each character is usually 1 byte, in which case @faunlocke's comment is 2 bytes shorter. Here an example answer of that. Also, would you mind adding a link to an online compiler (e.g. TIO or razetime's APLgolf) with test code? \$\endgroup\$ Oct 5, 2022 at 13:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.