Я умножаю источник, вы (вероятно) умножаете вывод!

18

задача

Задача состоит в том, чтобы написать программу, которая выводит непротиворечивое, но в любом случае произвольное положительное целое число x (поэтому строго больше 0). Вот подвох: когда источник повторяется N раз (код добавляется / соединяется N1 к себе), программа должна иметь 1N вероятность выдачиNxи оставшаяся вероятностьN1N выдачиxбез изменений.

пример

Давайте предположим, что ваш исходный источник является XYZцелым числом 3. Потом:

  • Для N=2 : XYZXYZдолжен вывести 3 с вероятностью 12 (50% времени) и23=6с вероятностью12 также (50% времени).

  • Для N=3 : XYZXYZXYZследует вывести 3 с вероятностью 23 (66,666% времени) и33знак равно9с вероятностью13 (33,333% времени)

  • Для Nзнак равно4 : XYZXYZXYZXYZследует вывести 3 с вероятностью 34 (75% времени) и43=12 с вероятностью14 (25% времени)

и так далее....

правила

Примечание: этот вызов является (намного) более сложной версией этого .

Мистер Xcoder
источник
Может ли программа прочитать свой исходный код?
мое местоимение monicareinstate
3
@ Someone Да, это разрешено.
г-н Xcoder

Ответы:

16

R , 66 35 байт

-29 байт благодаря digEmAll .

-2 байта благодаря Джузеппе .

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

Попробуйте онлайн!

Проверьте распределение для N = 4.

Ключ - правильное назначение ->. Когда код умножается N раз, первый N-1 вызовыsampleбудут назначеныA, и будет напечатан только последний вызов.

Оригинальное, более замысловатое решение:

R , 66 байт

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

Попробуйте онлайн!

Попробуйте онлайн (повторяется 3 раза)!

Используются два трюка: 1) вызвать интересующую основную функцию ?, чтобы мы могли вызывать ее, не заканчивая программу скобкой, и 2) использовать переменные TиTT , с кодом, который начинается Tи заканчивается на ?T.

Fсчетчик итераций ?переопределяется как функция, которая принимает логический аргумент: если входное значение ?равно TRUE(или T), оно выполняет требуемую случайную выборку; если ввод FALSE(или 0), он ничего не делает. ЗначениеTT определяется как 0, так что ?Tделает выборку, но ?TTничего не делает.

Когда источник повторяется, это выглядит так:

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

поэтому средний вызов не ?TTвыводит ничего, кроме последнего вызова, ?Tвыводит случайный результат.

Робин Райдер
источник
5
Я не думаю, что когда-либо видел, как ->используется в коде гольф в ситуации, когда <-не может быть; это так круто!!
Джузеппе
PS Я собираюсь дать эту награду в какой-то момент.
Джузеппе
2
Абсолютно потрясающе!
digEmAll
@digEmAll Очень аккуратно, спасибо!
Робин Райдер
11

Python 3 , 81 79 байт

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

Попробуйте онлайн!

-1 байт благодаря @Nishioka

Это одно из решений Python 3, которое не имеет прямого доступа к исходному тексту программы. Делать это в Python 3 сложнее, чем в Python 2, потому что нормальные операторы печати заканчиваются закрывающей круглой скобкой, поэтому не так много вариантов изменить его поведение в следующем блоке исходного источника. Было бы интересно увидеть больше креативных решений в Python 3.

Joel
источник
-1 байт:+0 if[]else 1
Нисиока
@Nishioka Спасибо. Обновлено.
Джоэл
11

Баш , 31 байт

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

Попробуйте онлайн!

trap ... 0запустит код, содержащийся при выходе. Повторные traps перезапишут старые. Без кавычек $[arithmetic expansion]запускается каждый раз, когда устанавливается новая ловушка.


Zsh может сохранить один байт с помощью <<<:

trap "<<<$[RANDOM%++n?1:n]" 0;
GammaFunction
источник
4

Питон 3 , 78 76 75 байт

Используя тот же трюк, что и в опубликованной ссылке , вот Python (с x = 1).

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

Попробуйте онлайн!

-2 байта благодаря Mr. Xcoder за его (n-1)формулу, у ~-nкоторой приоритет выше, чем *
-1 байт благодаря Nishioka

Пэрис Дуади
источник
1
Выглядит хорошо для меня! import random;n=len(*open(__file__))//76;print(1+~-n*(random.random()<1/n))#должен работать на -2 байта
г-н Xcoder
1
Я никогда не видел такой способ делать н-1! Мне это нравится, спасибо :)
Pâris
1
-1 байт: tio.run/##K6gsycjPM/7/...
Нисиока
Другой -1 байт , но с несколько иной подход: tio.run/##K6gsycjPM/7/...
Нисиока
да я делаю из-за random()<1/n;-)
Пэрис Дуади
3

Perl 5, 28 26 байт

-2 байта благодаря @Grimy

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

TIO

Науэль Фуйе
источник
26:1 if!++$x;say 1<rand$x||$x
Grimmy
спасибо, хорошая вариация
Науэль Фуйе
2

Рунические чары , 31 байт

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

Попробуйте онлайн!

Использует ту же структуру, что и этот ответ, чтобы подсчитать, сколько раз источник дублировался:

Поток выполнения

Просто вместо вывода n-го числа в списке мы используем это значение для случайной генерации числа, если результат не равен 0, выведите 1, иначе выведите это число.

Draco18s больше не доверяет SE
источник
2

Japt , 9 8 байт

(°Tö)ΪT

Проверьте это | Вдвое | Утроить
проверить распределение 10000 прогонов после 10 повторений

(°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

Оригинал, 13 11 10 9 байт

Обратите внимание на завершающий пробел.

NoÎp°T ö 

Проверьте это | Вдвое | Утроить
проверить распределение 10000 прогонов после 10 повторений

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
мохнатый
источник
2

JavaScript ( оболочка JavaScript 71 ), 78 байт

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

Нет ссылки tio, spidermonkey на tio слишком стар ...

Firefox (Spidermonkey) рассматривает комментарий как часть функции f. В результате (''+f).lengthбудетb+79n где b <78, и (n + 1) - времена повторения исходного кода.

Эта ошибка (? Я не уверен. Я бы предпочел, чтобы это ошибка спецификации JavaScript, а не какого-либо интерпретатора ) была передана в BMO кем-то еще сразу после публикации этого ответа: https://bugzilla.mozilla.org/ show_bug.cgi? id = 1579792 . (Ни я, ни твит не опубликовали ни мою ветку bmo.)

ТТГ
источник
Что с (async x=>x)()? Почему это асинхронно?
Томаш Зато - Восстановить Монику
@ TomášZato Это буквально asyncхроническое. Так что обратный звонокx=>f(...) будет вызван после fопределения функции .
TSH
1

Уголь , 12 байт

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

Попробуйте онлайн! На основании моего ответа на связанный вопрос. Выводы nс вероятностью ¹/ₙ, в противном случае 1. Объяснение:

⎚               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
Нил
источник