5
\$\begingroup\$

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!

\$\endgroup\$
4
  • \$\begingroup\$ See also Million-to-one chance quote. \$\endgroup\$
    – Neil
    Oct 25, 2018 at 19:42
  • 1
    \$\begingroup\$ @Neil Discworld has literal Random Number Gods? \$\endgroup\$
    – Nissa
    Oct 25, 2018 at 19:44
  • \$\begingroup\$ Discworld has all possible Gods, but only the ones that get believed in have any power. \$\endgroup\$
    – Neil
    Oct 25, 2018 at 19:49
  • 3
    \$\begingroup\$ Alternative title: "Does your language have a terse if-else ternary operator?" \$\endgroup\$
    – ngm
    Oct 25, 2018 at 20:27

7 Answers 7

1
\$\begingroup\$

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.

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

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.

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

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)
\$\endgroup\$
1
\$\begingroup\$

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
}
\$\endgroup\$
0
\$\begingroup\$

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).

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

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.

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

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

\$\endgroup\$

Your Answer

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

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