17
\$\begingroup\$

Task

The task is to write a program that outputs a consistent but otherwise arbitrary positive integer \$x\$ (so strictly greater than 0). Here's the catch: when the source is repeated \$N\$ times (the code is appended/concatenated \$N-1\$ to itself), the program should have a \$\dfrac{1}{N}\$ probability of outputting \$N\cdot x\$ and the remaining probability of \$\dfrac{N-1}{N}\$ of outputting \$x\$ unchanged.

Example

Let's assume that your initial source is XYZ and produces the integer 3. Then:

  • For \$N=2\$: XYZXYZ should output \$3\$ with a probability of \$\frac{1}{2}\$ (50% of the time) and \$2\cdot 3=6\$ with a probability of \$\frac{1}{2}\$ as well (50% of the time).

  • For \$N=3\$: XYZXYZXYZ should output \$3\$ with a probability of \$\frac{2}{3}\$ (66.666% of the time) and \$3\cdot 3=9\$ with a probability of \$\frac{1}{3}\$ (33.333% of the time)

  • For \$N=4\$: XYZXYZXYZXYZ should output \$3\$ with a probability of \$\frac{3}{4}\$ (75% of the time) and \$4\cdot 3=12\$ with a probability of \$\frac{1}{4}\$ (25% of the time)

and so on....

Rules

Note: This challenge is a (much) harder version of this one.

\$\endgroup\$
  • \$\begingroup\$ Can the program read its source code? \$\endgroup\$ – someone Sep 6 at 14:44
  • 3
    \$\begingroup\$ @someone Yes, it is allowed. \$\endgroup\$ – Mr. Xcoder Sep 6 at 14:49

15 Answers 15

15
+300
\$\begingroup\$

R, 66 35 bytes

-29 bytes thanks to digEmAll.

-2 bytes thanks to Giuseppe.

+0->A
x=!0:F
F=F+1
sample(F*x+!x,1)

Try it online!

Check the distribution for N=4.

The key is the rightwards assignment ->. When the code is multiplied \$N\$ times, the first \$N-1\$ calls to sample will be assigned to A, and only the last call will be printed.

Original, more convoluted solution:

R, 66 bytes

T->TT
F=F+1
TT=0
`?`=function(x)if(x)sample(c(1,F),1,,c(1,F-1))
?T

Try it online!

Try it online (repeated 3 times)!

Uses two tricks: 1) call the main function of interest ?, so that we can call it without ending the program with a bracket, and 2) use variables T and TT, with code which starts with T and ends with ?T.

F is the iteration counter. ? is redefined as a function which takes a boolean argument: if the input of ? is TRUE (or T), it does the required random sampling; if the input is FALSE (or 0), it does nothing. The value of TT is defined as 0, so that ?T does the sampling but ?TT does nothing.

When the source is repeated, it looks like this:

T->TT
F=F+1
TT=0
`?`=function(x)if(x)sample(c(1,F),1,,c(1,F-1))
?TT->TT
F=F+1
TT=0
`?`=function(x)if(x)sample(c(1,F),1,,c(1,F-1))
?T

so the middle call ?TT outputs nothing but the final call ?T outputs the random result.

\$\endgroup\$
  • 5
    \$\begingroup\$ I don't think I've ever seen -> used in code golf in a situation where <- couldn't be; this is so cool!! \$\endgroup\$ – Giuseppe Sep 6 at 23:45
  • \$\begingroup\$ PS I'm gonna give this a bounty at some point. \$\endgroup\$ – Giuseppe Sep 7 at 2:13
  • 2
    \$\begingroup\$ Absolutely awesome! \$\endgroup\$ – digEmAll Sep 7 at 10:17
  • \$\begingroup\$ This should work as well I think (borrowing +0 idea from python) \$\endgroup\$ – digEmAll Sep 7 at 15:35
  • \$\begingroup\$ @digEmAll Much neater, thanks! \$\endgroup\$ – Robin Ryder Sep 7 at 15:59
11
\$\begingroup\$

Python 3, 81 79 bytes

+0if[]else 1
from random import*
try:n+=1
except:n=1
print([1,n][random()*n<1])

Try it online!

-1 byte thanks to @Nishioka

This is one Python 3 solution that does not access the program source directly. Doing this in Python 3 is more challenging than Python 2 because normal printing statements end with a closing parenthesis so there aren't many choices to change its behavior in the next block of initial source. It would be interesting to see more creative solutions in Python 3.

\$\endgroup\$
  • \$\begingroup\$ -1 byte: +0 if[]else 1 \$\endgroup\$ – Nishioka Sep 7 at 19:49
  • \$\begingroup\$ @Nishioka Thanks. Updated. \$\endgroup\$ – Joel Sep 7 at 20:45
11
\$\begingroup\$

Bash, 31 bytes

trap echo\ $[RANDOM%++n?1:n] 0;

Try it online!

trap ... 0 will run the code contained on exit. Repeated traps will overwrite old ones. The unquoted $[arithmetic expansion] gets run every time a new trap is set.


Zsh can save one byte with <<<:

trap "<<<$[RANDOM%++n?1:n]" 0;
\$\endgroup\$
6
\$\begingroup\$

Jelly, 7 bytes

‘ɼḷXỊ®*

Try it online!

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

05AB1E, 7 bytes

¾Å1¼¾ªΩ

Try it online!

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

Python 3, 78 76 75 bytes

Using the same trick as in the link that was posted, here is a Python one (with x=1).

from random import*;n=len(*open(__file__))//75;print(1+~-n*(random()<1/n))#

Try it online!

-2 bytes thanks to Mr. Xcoder for his (n-1) formula with ~-n which has higher precedence than *
-1 byte thanks to Nishioka

\$\endgroup\$
  • 1
    \$\begingroup\$ Looks good to me! import random;n=len(*open(__file__))//76;print(1+~-n*(random.random()<1/n))# should work for -2 bytes \$\endgroup\$ – Mr. Xcoder Sep 6 at 14:22
  • 1
    \$\begingroup\$ I'd never seen this way of doing n-1 ! I like it, thanks :) \$\endgroup\$ – Pâris Douady Sep 6 at 14:25
  • 1
    \$\begingroup\$ -1 byte: tio.run/##K6gsycjPM/7/… \$\endgroup\$ – Nishioka Sep 6 at 15:30
  • \$\begingroup\$ Another -1 byte but with a bit different approach: tio.run/##K6gsycjPM/7/… \$\endgroup\$ – Nishioka Sep 6 at 17:13
  • \$\begingroup\$ yes I do because of the random()<1/n ;-) \$\endgroup\$ – Pâris Douady Sep 7 at 18:48
3
\$\begingroup\$

Gaia, 17 15 14 13 bytes

Øgl13÷:(1w&+ṛ

Try it online!

I randomly noticed the behavior of Øg yesterday when looking through the docs, which helped immensely.

\$\endgroup\$
3
\$\begingroup\$

Perl 5, 28 26 bytes

-2 bytes thanks to @Grimy

1 if!++$x;say 1<rand$x||$x

TIO

\$\endgroup\$
  • \$\begingroup\$ 26: 1 if!++$x;say 1<rand$x||$x \$\endgroup\$ – Grimmy Sep 7 at 3:11
  • \$\begingroup\$ thanks, nice variation \$\endgroup\$ – Nahuel Fouilleul Sep 7 at 17:36
3
\$\begingroup\$

Ruby, 40 bytes

1
n||=@x=0
n+=1
puts 1>rand(n)?n:1 if @x

Try it online!

Try it online (copied 3 times)!

A ruby port of this Python answer.

Ruby, 38 bytes

2 bytes saved by reading the file:

n=File.size($0)/38;puts 1>rand(n)?n:1#

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Dyalog APL, 25 24 23 22 21 bytes

0{×⍺:1+⍵⋄⎕←1⌈⍵×1=?⍵}1

Try it online!

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

Runic Enchantments, 31 bytes

UwR'10<;$\
I+:'RA0)?/1$;
1
l;
y

Try it online!

Uses the same structure as this answer to count how many times the source has been duplicated:

Execution flow

Just instead of outputting the nth number in a list, we use that value to randomly generate a number, if the result is not 0, print 1, else print that number.

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

Japt, 9 8 bytes

(°Tö)ΪT

Test it | Doubled | Tripled
Verify distribution of 10000 runs after 10 repetitions

(°Tö)ΪT
(            :Prevent the operator that follows from being implicitly applied to the first input variable, U
 °T          :Increment T (initially 0) by 1
   ö         :Random element in the range [0,T)
    )        :Closing the parentheses here instead of after the T saves a byte as there would need to be a space here to close the random method
     Î       :Sign - 0 (falsey) or 1 (truthy)
      ªT     :Logical OR with current value of T

Original, 13 11 10 9 bytes

Note the trailing space.

NoÎp°T ö 

Test it | Doubled | Tripled
Verify distribution of 10000 runs after 10 repetitions

NoÎp°T ö 
N             :Initially, the (empty) array of inputs
 o            :Replace the last element with
  Î           :  Its sign (always 1)
   p          :Push
    °T        :  T (initially 0) incremented
       ö      :Random element of N
\$\endgroup\$
2
\$\begingroup\$

JavaScript (JavaScript shell 71), 78 bytes

(async x=>x)().then(x=>f((''+f).length/78));f=x=>print(1-~x*Math.random()|0)//

No tio link, spidermonkey on tio is too old...

Firefox (Spidermonkey) consider the comment as a part of function f. As the result, (''+f).length will be b+79n where b < 78, and (n + 1) is the times of source code repeated.

This buggy (? I'm not sure. I would prefer it is a bug of JavaScript specification rather than any interpreter) behavior had been submit to BMO by someone else just after this answer posted: https://bugzilla.mozilla.org/show_bug.cgi?id=1579792 . (Neither of the bmo thread nor the tweet is posted by me.)

\$\endgroup\$
  • \$\begingroup\$ What's with the (async x=>x)()? Why is it async? \$\endgroup\$ – Tomáš Zato Sep 9 at 9:46
  • \$\begingroup\$ @TomášZato It is literally asynchronous. So the callback x=>f(...) will be invoked after function f been defined. \$\endgroup\$ – tsh Sep 10 at 2:32
1
\$\begingroup\$

C# (Visual C# Interactive Compiler), 133 114 112 bytes

This is the first (and hopefully last) time I have ever used C# preprocessor directives.

#if!I
#define I
static int i;
class p{~p()=>Console.Write(new Random().Next(i)<1?i:1);}p s=new p();
#endif
i++;

Try it online!

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

Charcoal, 12 bytes

⎚I⎇‽L⊞Oυω¹Lυ

Try it online! Based on my answer to the linked question. Outputs n with probability ¹/ₙ, otherwise 1. Explanation:

⎚               Remove output from previous iterations
       υ        Initially empty list
        ω       Empty string
     ⊞O         Push
    L           Length
   ‽            Random integer [0..length)
  ⎇             Ternary
         ¹      If nonzero then literal 1
          Lυ    If zero then the new length
 I              Cast to string for implicit print
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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