# Choose the Most Dramatic Outcome

The premise of this is simple: A 10% chance is pretty unlikely, but everyone knows that a one-in-a-million chance is a sure thing!

So, write code that implements the following "dramatic" probability rules:

• Take in a floating point P from 0 to 1 representing the unmodified chance of some plot-related event, and a boolean representing whether we're in the climax or not.
• Determine P' on these conditions:
• If 0 < P ≤ 10-3 then P' = 1.
• If .999 ≤ P < 1 then P' = 0.
• If P = 0 and we're in the climax, then the heroes will likely get a last-minute sudden advantage and P' = .9.
• If P = 1 and we're in the climax, then the villain will unveil an as-yet-unseen superweapon and P' = .1.
• Otherwise, P' = P.
• Return truthy or falsey based on P' as the chance of truth. For example, if P' = .7, then you should return truthy 70% of the time and falsey 30% of the time.

Shortest code in bytes wins!

– Neil
Oct 25, 2018 at 19:42
• @Neil Discworld has literal Random Number Gods? Oct 25, 2018 at 19:44
• Discworld has all possible Gods, but only the ones that get believed in have any power.
– Neil
Oct 25, 2018 at 19:49
• Alternative title: "Does your language have a terse if-else ternary operator?"
– ngm
Oct 25, 2018 at 20:27

# R, 86 bytes

function(a,b,d=a*(1-a))runif(1)<="if"(d,"if"(d>999e-6,a,1-round(a)),"if"(b,.9-.8*a,a))


Try it online!

a is P' and b is 1 or 0 for "in the climax" or not.

If a is 0 or 1, then d will be 0, in which case if b is 0 just return a, otherwise .9 minus .8*a.

Otherwise if a is not near 0 or 1, d will be "far" from 0 so return a. Otherwise 1-round(a) will take a to the "opposite" 0 or 1.

Then see if a random selection from [0,1] is less than or equal to the resulting probability.

The link does a little simulation for all the possible scenarios to demonstrate that it all seems to work.

• Where did you get the 999e-6 from? Oct 25, 2018 at 18:48
• Since 0 <= a <= 1, d will be bigger than 999e-6 = 0.000999 exactly when a < 0.001 or a > 0.999.
– ngm
Oct 25, 2018 at 18:52
• Huh, I was wondering how you could take advantage of the symmetry in the sandbox, you seem to have figured it out. Oct 25, 2018 at 18:58
• Also, you can save bytes on parentheses by setting d to a-a*a. Oct 25, 2018 at 18:59

# C (gcc), 82 bytes

Zero bytes of source code. Use the preprocessor directive:

-Df(p,c)=rand()<~(1<<31)*(c&p==0?.9:p==1&c?.1:(p<=1e-3|p>=.999)&p!=1&p!=0?p<.1:p)


Try it online!

Very little to explain about it; p is the probability, c the climax boolean. Main golfing trick is ~(1<<31), which seems to be the equivalent to RAND_MAX for gcc. The usual C golfing tricks go straight out the window with floating points.

# Java 8, 65 bytes

P->C->Math.random()<(P==0?C?.9:0:P>.001?P<.999?P:P==1?C?.1:1:0:1)


Try it online.

Explanation:

We have the following scenario combinations to consider:

P=0, C=falsey             → 100% falsey
P=0, C=truthy             → 90% truthy; 10% falsey
P=(0,0.001], C=either     → 100% truthy
P=(0.001,0.999), C=either → (P*100)% truthy; (100-P*100)% falsey
P=[0.999,1), C=either     → 100% falsey
P=1, C=truthy             → 10% truthy; 90% falsey
P=1, C=falsey             → 100% truthy


Which gives us the following code:

P->C->           // Method with double and boolean parameters and boolean return-type
Math.random()  //  Random value in the range [0, 1)
<(P==0?       //  If P is 0:
C?         //   And there is a climax:
.9        //    Check if the random value is smaller than 0.9 (90% true)
:          //   Else:
0         //    Check if the random value is smaller than 0 (0% true)
:P>.001?     //  Else-if P is larger than 0.001:
P<.999?    //   If P is smaller than 0.999, so in range (0.001,0.999):
P         //    Check if the random value is smaller than P (P*100% true)
:P==1?     //   Else-if P is 1:
C?        //    And there is a climax:
.1       //     Check if the random value is smaller than 0.1 (10% true)
:         //    Else:
1        //     Check if the random value is smaller than 1 (100% true)
:          //   Else, so P is in the range [0.999,1):
0         //    Check if the random value is smaller than 0 (0% true)
:            //  Else, so P is in the range (0,0.001]:
1)          //   Check if the random value is smaller than 1 (100% true)


# Perl 6, 54 bytes

{(($/=1-$^p min$p)??.001>=$/||$/!!$^c*.9)>rand^^$p>.5}  Try it online! ### Explanation { ( ($/=1-$^p min$p)    # Compute min(p,1-p) and store in $/ ?? # if$/ > 0
.001>=$/|| # if$/ <= 0.001 then 1
$/ # else$/
!!$^c*.9 # else 0.9 * climax )>rand # Random Bool with given probability ^^$p>.5              # Flip if p > 0.5
}


# 05AB1E,  44  42 bytes

Crossed out &nbsp;44&nbsp; is no longer 44 :)

_i90*ë¹₄*©1›i1₄®-‹i¹т*ë¹iiTëтë0ëт]5°<Ý₄/Ω›


Port of my Java 8 answer. First input is P, second input is 0/1 for truthy/falsey whether there is a climax.

Try it online.

Explanation:

_i                     # If the first (implicit) input is exactly 0:
90                   #  Push 90
*                  #  Multiply it with the second (implicit) input (0 if 0, 90 if 1)
ë                     # Else:
¹₄*                  #  Push the first input, and multiply it by 1000
©                 #  Save it in the register (without popping)
1›i              #  If it's larger than 1 (so input larger than 0.001):
₄®-          #   Push 1000, and subtract the value from the register
1   ‹i        #   If it's smaller than 1 (so input smaller than 0.999):
¹т*     #    Push the first input multiplied by 100
ë        #   Else:
¹i      #    If the first input is exactly 1:
i     #     If the second (implicit) input is 1:
T    #      Push 10
ë     #     Else:
т    #      Push 100
ë      #    Else:
0     #     Push 0
ë            #  Else:
т           #   Push 100
]                   # Close all if-else clauses
5°                 # Push 100000 (10**5)
<                # Decrease it by 1: 99999
Ý               # Create a list in the range [0,99999]
₄/             # Divide it by 1000: [0,0.001,0.002,...,99.997,99.998,99.999]
Ω            # Take a random value from the list
›           # Check if the earlier value is larger than this random value
# (and output implicitly)


05AB1E has no builtin for a random decimal value in the range [0, 1), so I use 5°<Ý₄/ to generate a list in the range [0,99.999] in steps of 0.001 and then Ω to take a random value from that list (and I use percentages [0, 100] instead of decimals [0, 1] in the rest of my code).

# Perl 5-pl, 61 bytes

$_=(!$_?<>?.9:0:$_==1?<>?.1:1:$_<=.001||($_<.999&&$_))>rand<>


Try it online!

Input is on two lines. First line is P; second line is 0 if not in climax, 1 if in climax.

# Python 3, 118 bytes

from random import *
def f(p,c):
if c:
if p==1:p=.9
if p==0:p=.1
if p<1e-3:p=1
if p>.999:p=0
return random()<p


Inputs: p is initial probability, c is climax