Скудная машина


26

Классическим примером для представления людям концепции дискретного распределения вероятностей является бобовая машина . У этой машины большое количество мрамора выпадает из узкого прохода наверху, после чего они ударяются о ряды переплетенных штифтов, где на каждом штифте попадание мрамора может упасть влево или вправо от штифта. Наконец, штифты собраны в вертикальные бункеры в нижней части машины. Простая схема этой машины выглядит следующим образом:

|     O     |
|     ^     |
|    ^ ^    |
|   ^ ^ ^   |
|  ^ ^ ^ ^  |
| ^ ^ ^ ^ ^ |
|_|_|_|_|_|_|

На этой диаграмме Oобозначено место падения мрамора. Каждый из них ^- это булавка, на которой мрамор с вероятностью 50% может переместиться на квадрат слева или справа от булавки. Мрамор затем собирается в ящиках на дне устройства, и для достаточно большого количества мраморов высота мраморных стопок в ящиках будет напоминать дискретное биномиальное распределение.

Вызов

Для этой задачи вы будете вычислять результирующее распределение вероятностей бобовых машин на основе диаграмм, подобных приведенной выше. Диаграммы интерпретируются как двумерная «программа», через которую проходят шарики, либо к боковым полям, либо к полям под текущим полем. Когда шарики достигают нижней части машины, они учитываются для распределения вероятностей. Чтобы было интересно, эти диаграммы будут содержать несколько полей, а не только простой источник и выводы. Пример диаграммы:

|     O     |
|     ^     |
|    ^ /    |
|   ^ | ^   |
|  <^- =  v |
| ^ ^ ^ ^ ^ |

Кроме того, каждый шарик теперь имеет направление вращения. Это направление задается некоторыми полями и определяет, к какому следующему полю перемещается мрамор в нескольких других полях.

Определены следующие поля:

  • O: Источник. Создает мрамор прямо под ним. Направление этих шариков - 50% влево, 50% вправо. Каждый источник производит одинаковое количество мрамора.
  • UРаковина Любые шарики, попадающие в это поле, удаляются из бобовой машины.
  • : Пустое пространство. Если мрамор прибудет на это поле, он переместится на поле ниже.
  • -: Пол. Если мрамор прибудет на это поле, он переместится либо к полю слева, либо к полю справа, в зависимости от его текущего направления.
  • ^Разветвитель Если мрамор попадает на это поле, он имеет 50% перемещения к полю справа или к полю слева от сплиттера. Это также определяет направление мрамора.
  • v: Присоединиться. Если мрамор прибудет на это поле, он переместится на поле ниже.
  • /Наклонная накладка. Если мрамор прибудет на это поле, он переместится на поле слева от площадки, задав направление мрамора.
  • \То же, что и предыдущий, но справа.
  • |Отражатель Если мрамор прибудет на это поле, он изменит направление мрамора и переместит мрамор в поле вправо или влево, основываясь на этом обратном направлении.
  • =: Пушка Если мрамор прибывает в это поле, оно будет переместить его вправо или влево , в направлении тока, пока мрамор не встречает поле, которое не , -или O.
  • <: То же, что и предыдущий, но всегда будет устанавливать направление и двигаться влево.
  • >То же, что и предыдущий, но справа.

Следующие гарантии даны относительно диаграммы.

  • Каждая строка ввода будет иметь одинаковую длину в полях.
  • Самое левое и самое правое поле каждой строки всегда будет a |.
  • Диаграмма не будет содержать никаких возможных путей, по которым шарики могут застрять в машине на неопределенное количество итераций, например \/или ^^.
  • Диаграмма будет содержать только вышеупомянутые поля.
  • Есть один или несколько источников

Результат

Ваша задача будет состоять в том, чтобы сгенерировать 16-строчную гистограмму ASCII высотой распределения вероятностей, в которой шарики выходят из нижней части графика, в таком масштабе, чтобы наибольшая вероятность охватывала все 16 символов. Итак, для следующей проблемы:

|     O     |
|     ^     |
|    ^ ^    |
|   ^ ^ ^   |
|  ^ ^ ^ ^  |
| ^ ^ ^ ^ ^ |

Ваша программа должна создать следующее решение (обратите внимание, что она должна иметь ту же ширину, что и входная программа, включая каналы в сторону:

     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
   # # # #  
   # # # #  
   # # # #  
   # # # #  
   # # # #  
   # # # #  
 # # # # # #
 # # # # # # 

Примеры

Ниже приведен пример, который должен проверить функциональность всех типов полей:

|     O     O         |
|  O  ^ /  <^\\\      |
|    ^ >            ^ |
|   ^ ^ ^            =|
|  ^ ^ | ^    <^   O  |
| ^ > ^ | ^   O ^> v  |
||  ^U  ^  |  =    ^\ |
|  ^ ^ ^ ^U ^\ ---^   |
| = ^   ^     =    v  |

Это должно привести к следующему выводу:

                     # 
                     # 
                     # 
                     # 
                   # # 
                   # # 
                   # # 
       # #         # # 
       # #         # # 
       # #         # # 
       # #         # # 
      ## #         # # 
      ## # #       # # 
   # ### # #       # # 
 # # ### # #       # # 
 # # ### # #       # # 

правила

Обе функции и полные программы представляют собой правильные ответы на этот вызов. Вы получите диаграмму в виде строки, разделенной новой строкой, и вам следует вернуть выходной граф в заданном формате. Применяются правила ввода / вывода по умолчанию . Хотя в выходных данных допускается завершающий и начальный переводы строк, каждая строка должна иметь точно такую ​​же ширину, что и входные.

Для более креативных решений требуется, чтобы ваша программа выводила правильный результат более 90% времени для одной и той же диаграммы. В конце концов, это симуляция вероятности.

счет

Это , поэтому выигрывает самая низкая оценка в байтах.


Гораздо проще, но связано .
Питер Тейлор

Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат .
Деннис

так v= [space]?
16м2

@ l4m2 vи [space]отличаются тем, как пушки взаимодействуют вокруг них.
CensoredUsername

Ответы:


8

Python 3 , 431 429 410 байт

def t(a):e=enumerate;p=a.split("\n");o=[0]*len(p[0]);{m(i,j,p,o,1):m(i,j,p,o,-1)for i,r in e(p)for j,c in e(r)if"O"==c};[print("".join(" #"[round(16*r/max(o)+i)>15]for r in o))for i in range(16)]
def m(r,k,p,o,l,x=1):
 while r<len(p):
  c=p[r][k]
  if"^"==c:x/=2;m(r,k-l,p,o,l,x)
  if"U"==c:return
  if c in" vO":r+=1;continue
  l=[1,l,-1,l,-l,1][ord(c)%6];k-=l
  while";"<c<"?"and p[r][k]in" O-":k-=l
 o[k]+=x

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

Этот ответ является совместным усилием между Wheat Wizard и CensoredUsername. Для справки, это алгоритм без заглатывания.

-2 байта от мистера Xcoder

-19 байт от CensoredUsername


-2 байта, если вы переключитесь на Python 2 (оператор print)?
Кэрд coinheringaahing

1
Об этом было сказано: but I can confirm it's doable in 519 characters of python 3 code ;) I don't think I can golf mine much more- CensoredUsername
Стивен

Я был безнадежно наивен, когда сказал это. Тем не менее, обеспечение соревнований по гольфу было довольно забавным. Также @cairdcoinheringaahing, оператор печати Python 2 является оператором, а не выражением, и поэтому его нельзя использовать в понимании списка. Это будет означать, что верхний слой должен быть разделен на несколько строк с отступом, что сделает 2-байтовый выигрыш от удаления пустым.
CensoredUsername

4

Python 2 , 731 байт

i=raw_input
l=i()
c=[]
while l:c,l=c+[l],i()
p=[[0]*len(l)for l in c]+[[0]*max(map(len,c))]
S=lambda r,C,p:r>=0and C>=0and r<len(p)and C<len(p[r])
def U(r,C,P,D,N=0):
 if S(r,C,p):p[r][C]+=P
 if S(r,C,c):
	K=c[r][C]
	if K in' O':U(r+1-N,C+D*N,P,D,N)
	elif'v'==K:U(r+1,C,P,D)
	elif'-'==K:U(r,C+D,P,D,N)
	elif'^'==K:U(r,C-1,P/2,-1);U(r,C+1,P/2,1)
	elif'/'==K:U(r,C-1,P,-1)
	elif'\\'==K:U(r,C+1,P,1)
	elif'='==K:U(r,C+D,P,D,1)
	elif'>'==K:U(r,C+1,P,1,1)
	elif'<'==K:U(r,C-1,P,-1,1)
	elif'|'==K:U(r,C-D,P,-D)
for r in range(len(c)):
 for C in range(len(c[r])):
	if'O'==c[r][C]:U(r+1,C,1.,1);U(r+1,C,1.,-1)
p=p[-1][::-1]
s=16/max(p)
f=['#'*min(int(n*s),16)+' '*min(int(16-n*s),16)for n in p]
print('\n'.join(map(''.join,zip(*f)))[::-1])

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

-17 байт благодаря caird

-12 байт благодаря Натану Ширайни

-56 байт при переключении на смешанный отступ (Python 2)

-28 благодаря CensoredUsername, потому что вероятности в конце нормализованы, поэтому нет необходимости, чтобы конечные вероятности всегда составляли 1.

-7 байт благодаря калькулятору Feline за счет использования более короткого конечного elifоператора.

-218 байтов путем слияния двух функций



@cairdcoinheringaahing Правильно, спасибо.
HyperNeutrino

2
В звонках Rи Lлайке R(r+1-N,C+N,P,N=N)(первый звонок R) вам не нужно N=в конце; это должно быть R(r+1-N,C+N,P,N)вместо.
Натан. Эйлиша Ширайни

@NathanShiraini Правильно, спасибо.
HyperNeutrino

... вы забыли немного Последние 2 строки обоих Lи R^^ Кроме того, ваш второй уровень отступа - это 4 пробела везде, я думаю, вы могли бы сделать это 2.
Натан. Элиша Ширайни

3

C 569 568 556 байт

Golfed

#define A s[1]
#define c(i,j,k) break;case i:x=j;y=k;
w,S,i,j,d,x,y,z;main(int*a,char**s){w=strchr(&A[1],'|')+2-A;a=calloc(w,4);for(;i++<'~~';j=0){for(;A[j];){if(A[z=j++]==79){d=rand()%2;x=4;y=7;z+=w;for(;z<strlen(A);){z+=x%3-1+(y%3-1)*w;switch(A[z]){case 85:goto e;c(32,x/3*(3+1),y/3*(3+1))c(45,d*2+3,7)c(94,(d=rand()%2)*2+3,7)c(118,4,8)c(47,3,7)d=0;c(92,5,7)d=1;c(124,(d=!d)*2+3,7)c(60,x,y)case 62:d=A[z]/2%2;case 61:x=d*8;y=4;}}a[z%w]++;e:;}}}for(i=-1;++i<w;S=a[i]>S?a[i]:S);for(j=17;j-->1;puts(""))for(i=0;i<w-1;printf("%c",a[i++]*16./S+0.6<j?32:35));}

Ungolfed

//Variable Definitions
//direction - marbles current direction, 0 -> left, 1-> right
//arrwidth - width of array
//x - change in x of marble in base 3 - 0 -> Left, 1 -> stay, 2-> right
//y - change in y of marble in base 3 - 0 -> Up, 1 -> stay, 2-> Down
//z - position of marble
//i - iterator on runs of program
//j - iterator on string
//k - iterator on outputstring
//argc - array holding all buckets

#define c(i,j,k) break;case i:x=j;y=k;

arrwidth,scale,i,j,direction,x,y,z;

main(int *argc, char**argv){
  arrwidth=strchr(&A[1],'|')+2 - A; //get width
  argc=calloc(arrwidth,4);
  for(;i++<'~~';j=0){
    for(;A[j];){
      if(A[z=j++] == 79){ //if it finds an O, start sim
        direction=rand()%2;
        x=4;
        y=7;
        z+=arrwidth;
        for(;z<strlen(A);){
          z+=x%3-1 + (y%3-1)*arrwidth;
          switch (A[z]){
            case 85://marble dies dont record
              goto e;
            c(32,x/3*(3+1),y/3*(3+1)) //case ' '
            c(45,direction*2+3,7)    //case -
            c(94,(direction=rand()%2)*2+3,7)    //case ^
            c(118,4,8)    //case v
            c(47,3,7)    //case /
              direction=0;
            c(92,5,7)   //case '\'
              direction=1;
            c(124,(direction=!direction)*2+3,7)
            c(60,x,y)    //case <
            case 62:    //case >
              direction=A[z]/2%2;
            case 61:  //case =
              x=direction*8;
              y=4;
          }
        }
        argc[z%arrwidth]++;
        e:;
      }
    }
  }
  //get output answer in terms of '#'
  for(i=-1;++i<arrwidth;scale=argc[i]>scale?argc[i]:scale);
  for(j=17;j-->1;puts(""))
    for(i=0; i < arrwidth-1;printf("%c",argc[i++]*16./scale+0.6<j?32:35));
}

Правки

Сохранено 12 байт, изменив мой регистр макросов.

Заметки

В моем коде используется система из целых 3-х целых чисел, чтобы определить, куда и куда направится мрамор (для пушек и прочего).

Я пытался, поэтому должен был победить это решение Python, я действительно сделал.


1
Я считаю 568 байт; может быть, вы посчитали завершающий перевод строки? И черт возьми, я плохо себя чувствую; превзошел в питоне C? Боже ...: P
HyperNeutrino

Вы правы, я оставил в файле запаздывающего новичка. Благодарность!
dj0wns
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.