Ітераційне кочення кости


12

З урахуванням введення , nде 3 <= n <= 25необхідно виконати наступні кроки, починаючи з одного nодностороння штампа (граней в діапазоні [1, n], включно):

  1. Роздрукуйте результат прокатки поточних nкісток у грі у формі kdn: X(де Xрезультат іk кількість кісток у грі).
  2. Якщо Xбільше або дорівнюєn/2 разів грати кістки, додайте штамп. Інше, зніміть плашку.
  3. Якщо кількість кісток у грі дорівнює 0або n, зупиніться. Ще, перейдіть до кроку 1.

Приклад виконання (зауважте, що висновок у дужках є для пояснення і не потрібен):

6-сторонні:

1d6: 4 (avg: 3.0, add)
2d6: 6 (avg: 6.0, add)
3d6: 9 (avg: 9.0, add)
4d6: 16 (avg: 12.0, add)
5d6: 13 (avg: 15.0, remove)
4d6: 9 (avg: 12.0, remove)
3d6: 5 (avg: 9.0, remove)
2d6: 7 (avg: 6.0, add)
3d6: 11 (avg: 9.0, add)
4d6: 14 (avg: 12.0, add)
5d6: 17 (avg: 15.0, add)

9-сторонні:

1d9: 7 (avg: 4.5, add)
2d9: 14 (avg: 9.0, add)
3d9: 18 (avg: 13.5, add)
4d9: 18 (avg: 18.0, add)
5d9: 28 (avg: 22.5, add)
6d9: 26 (avg: 27.0, remove)
5d9: 28 (avg: 22.5, add)
6d9: 34 (avg: 27.0, add)
7d9: 33 (avg: 31.5, add)
8d9: 30 (avg: 36.0, remove)
7d9: 29 (avg: 31.5, remove)
6d9: 35 (avg: 27.0, add)
7d9: 32 (avg: 31.5, add)
8d9: 42 (avg: 36.0, add)

Правила

  • Виходи повинні бути точно у форматі kdn: X , причому нові рядки розділятимуть кожен рулон
  • Ви дійсно повинні імітувати кочення декількох кісток; просто повернення випадкового цілого числа в діапазоні [1, n](включно), помноженому на кількість кісток, які в даний час граються, не дозволяється, оскільки це точно не імітує прокатування декількох кісток.
  • Стандартні лазівки заборонені
  • Це , тому найкоротша відповідь у байтах виграє

Таблиця лідерів

Фрагмент стека внизу цієї публікації генерує таблицю лідерів з відповідей а) як список найкоротших рішень для кожної мови та б) як загальну таблицю лідерів.

Щоб переконатися, що ваша відповідь відображається, будь ласка, почніть свою відповідь із заголовка, використовуючи наступний шаблон Markdown:

## Language Name, N bytes

де Nрозмір вашого подання. Якщо ви покращите свій рахунок, ви можете зберегти старі бали у заголовку, прокресливши їх. Наприклад:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Якщо ви хочете включити у свій заголовок декілька чисел (наприклад, тому що ваш рахунок становить суму двох файлів або ви хочете окремо перерахувати штрафні санкції для перекладача), переконайтесь, що фактичний бал є останнім номером у заголовку:

## Perl, 43 + 2 (-p flag) = 45 bytes

Ви також можете зробити ім'я мови посиланням, яке з’явиться у фрагменті:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


Я вважаю це заплутаним. Приклад відповіді, будь ласка?
Hipe99

Приклад відповіді , оскільки приклади стислі.
Hipe99

Ваша редакція уточнена. Дякую!
Hipe99

16
Ви впевнені у своїй арифметиці? Звичайний d6 має середній рулон 3,5.
Пітер Тейлор

11
Усі середні показники у ваших прикладах здаються неправильними
edc65

Відповіді:



3

Математика, 95 89 80 символів

For[k=1,0<k<#,If[Print[k,d,#,": ",x=Tr[{1,#}~RandomInteger~k]];x<k/2#,k--,k++]]&

Безумовно

For[
  k = 1,
  0 < k < #,
  If[
    Print[k, d, #, ": ", x = Tr[{1, #}~RandomInteger~k]];
    x < k/2 #,
    k--,
    k++
  ]
] &

1
@ MartinBüttner дякую за ваші пропозиції. Echoна жаль, не можна приймати послідовність входів, як Printце робиться.
shrx

О, хороший пункт.
Мартін Ендер

3

PHP, 164 121 112 113 109 байт

Остаточний варіант, обіцяю. Удосконалено за допомогою пропозиції Тіта:

function d($x,$y){for($i=$y;$i--;)$r+=rand(1,$x);echo$y."d$x: $r\n";$y+=$r/$y>$x/2?:-1;$y<$x&&$y?d($x,$y):0;}

EDIT: Додано додатковий байт для форматування. Забув, що там є ІФ, який, завдяки відмінюванню тексту "add / sub", міг стати потрійним оператором:

function d($x,$y){for($i=$y;$i--;)$r+=rand(1,$x);echo$y."d$x: $r\n";$r/$y>$x/2?$y++:$y--;if($y<$x&&$y)d($x,$y);}

Зараз результат виглядає так:

1d6: 5
2d6: 11
3d6: 8
2d6: 11
3d6: 7
2d6: 4
1d6: 5

EDIT: Завдяки @Manatwork врятував мене дуже багато! Нова і непридатна версія:

function d($x,$y){for($i=$y;$i--;)$r+=rand(1,$x);echo$y."d$x=$r\n";if($r/$y>$x/2)$y++;else$y--;if($y<$x&&$y){d($x,$y);}}

Попередній запис:

function d($x,$y){for($i=0;$i<$y;$i++)($r+=rand(1,$x));$s=$y."d$x=$r, ";if($r/$y>$x/2){$y++;$s.="add";}else{$y--;$s.="sub";}echo $s."\n";if($y<$x&&$y>0){d($x,$y);}}`

Розгортає окремі штампи, виводить це:

1d6=6, add
2d6=7, add
3d6=11, add
4d6=14, add
5d6=15, sub
4d6=15, add
5d6=18, add

І це називається таким чином: d(6, 1);

Відображає Addі Subсуфікс обов'язковий? Це незрозуміло з вашого питання.


У вимозі йдеться "зауважте, що висновок у дужках є поясненням і не є необхідним". Цей шлях здається коротшим:function d($x,$y=1){for($i=$y;$i--;)$r+=rand(1,$x);echo$y."d$x, $r↵";$r/$y>$x/2?$y++:$y--;if($y<$x&&$y)d($x,$y);}
маніпуляція

@manatwork Спасибі, ви дуже багато допомогли!
steenbergh

Якщо if все ще може бути потрійним, зберігаючи один байт. А реконструкція збільшення / зменшення може врятувати два байти:$y-=$r/$y>$x/2?:-1
Тит,

2

Пітон 3, 125

Збережено 3 байти завдяки DSM.

def x(d):
 import random;c=1
 while 0<c<d:r=sum(map(random.randint,[1]*c,[d]*c));print('%id%i: %i'%(c,d,r));c+=2*(r>=d*c/2)-1

Досить просто, котить купу кісток і перевіряє середню. Тут ще нічого надто фантазійного.
Його потрібно називати за допомогою int. Отже, x(6)вийде щось подібне:

1d6: 5
2d6: 10
3d6: 8
2d6: 7
3d6: 11
4d6: 8
3d6: 13
4d6: 19
5d6: 13
4d6: 15
5d6: 22

.


2

JavaScript (ES6), 97 102 106 112 байт

Дякую @ user81655 та @Jupotter, що зберегли мені кілька байт.

f=n=>{for(k=1;k%n;console.log(k+`d${n}: `+x),k+=x<k*n/2?-1:1)for(x=i=k;i--;)x+=Math.random()*n|0}

// 102 bytes:
f=n=>{for(k=1;k%n;console.log(k+`d${n}: `+x),k+=x<k*n/2?-1:1)for(x=i=0;++i<=k;)x+=1+Math.random()*n|0}

// Previous attempt, 112 bytes
f=n=>{k=1;while(k&&k!=n){for(x=i=0;i++<=k;)x+=1+~~(Math.random()*n);console.log(k+`d${n}: `+x);k+=x<k*n/2?-1:1}}

Демо

Це працює лише в браузерах, сумісних з ES6 (на даний момент, що включає Firefox та Edge, можливо, в Chrome і Opera з увімкненими експериментальними функціями JavaScript):

f=n=>{for(k=1;k%n;console.log(k+`d${n}: `+x),k+=x<k*n/2?-1:1)for(x=i=k;i--;)x+=Math.random()*n|0}

// Snippet stuff
console.log = x => {
  document.getElementById('O').innerHTML += x + `<br>`;
}

document.getElementById('F').addEventListener('submit', e => {
  document.getElementById('O').innerHTML = ``
  f(document.getElementById('I').valueAsNumber)
})
<form id=F action=# method=get>
  <label>
    Number of faces: 
    <input type=number min=3 max=25 value=9 required id=I>
  </label>
  <button>Play</button>
  
  <div>
    <output id=O></output>
  </div>
</form>


Ви могли б змінити whileдо forпетлі, округлення з |0замість ~~()і рухатися кілька заяв , так що ви можете видалити дужки , щоб заощадити кілька байт. Також вам дозволяється робити це анонімною функцією (ні f=). 103 байти:n=>{for(k=1;k&&k!=n;k+=x<k*n/2?-1:1)for(x=i=0;i++<=k;console.log(k+`d${n}: `+x))x+=1+Math.random()*n|0}
користувач81655

@ user81655 Дякую Чомусь ваша версія створила багато сторонніх результатів, тому я перейшов console.logдо іншого forциклу (коштував мені на 1 char більше, ніж ваш). І все-таки знизився до 106
rink.attendant.6

Я щойно написав це, не перевіряючи його, тому радий, що в основному це спрацювало. :)
користувач81655

Отримати одного персонажа можна, замінивши k&&k!=nумову порівняннямk%n!=0
Джупоттер

@Jupotter Спасибі, k%nпрацює ще краще;)
rink.attendant.6

1

CJam, 45 байт

ri:M;{X__{Mmr+}*[X'dM':S5$N]o_+XM*<_+(-:XM%}g

Спробуйте в Інтернеті.

Реалізує специфікацію досить буквально (включаючи математично неправильну формулу "середній рулон"). Як і слід було очікувати, портирование оригінальної програми GolfScript нижче CJam заощадив купу байт з - за більш короткі імена вбудованих команд ( mr, oі gзамість rand, putsа do).

GolfScript, 51 байт

~:&;{1..{&rand+}*[1"d"&": "4$]puts.+1&*<.+(-:1&%}do

Ось мій оригінальний запис GolfScript. Помітні прийоми з гольфу включають використання числа 1як зручно заздалегідь ініціалізованої змінної для зберігання поточної кількості кісток, які потрібно прокати. (Натомість використовується версія CJam X, яку CJam ініціалізує до значення 1.)


Пс. Побачивши заголовок, я спочатку хотів відповісти на це в AnyDice . Але це виявляється жахливим вибором для цього виклику, і я не думаю, що навіть технічно це можливо використовувати для реалізації цієї специфікації, як дано.

Проблема полягає в тому, що AnyDice - це доменна мова для написання детермінованих програм для обчислення статистики прокатки кісток. Оглядаючи можливі результати рулону і робити умовні рулони на їх основі є можливим з допомогою рекурсії, немає ніякого способу , щоб зробити яку - або фактичну випадковість. Отже, хоча ви могли імітувати цю послідовність рулонів з кістки в AnyDice, все, що ви можете отримати як результат, - це статистика таких речей, як, скажімо, кількість рулонів до закінчення процесу або розподіл результатів на заданому кроці.

Все, що сказано, ось найближче, що я міг отримати в AnyDice :

N: 6
K: 1
function: clip X:n { result: X * (X < N) }
function: adjust X:n { result: [clip X + ((XdN)*2 >= X*N)*2-1] * (X > 0) }
loop I over {1..20} {
  output K named "dice in roll [I]"
  output KdN named "outcome of roll [I]"
  K: [adjust K]
}

Це не особливо гольф-код, оскільки це здавалося вправою марності. Стандартні хитромудрі мовленнєві фокуси, такі як скорочення назв функцій та усунення зайвих пробілів, все одно повинні вичерпати більшість потенціалу для гольфу.

Ключовий трюк, що використовується тут, полягає в тому, що, коли ви викликаєте функцію, яка очікує числа (як зазначено :nу визначенні функції) в AnyDice, і передає їй матрицю (тобто розподіл ймовірностей), AnyDice автоматично оцінює функцію для всіх можливих значення штампу і поєднує результати в нову штампу.

Ось скріншот результату (у форматі діаграми) для перших трьох роликів:

Скріншот AnyDice

(Зверніть увагу, що стовпець "0" у кожному графі вказує на ймовірність того, що ітерація припинилась через кількість кубиків, що потрапили або 0, або N перед поточним рулоном. Це, можливо, є зручним способом представити умову зупинки, оскільки звичайно прокат 0dN завжди дає 0.)


1

R, 103 байт

Досить пряма реалізація. Рулетики з кубиками виконуються sum(sample(n,i)).

i=1;n=scan();while(i&i<=n){cat(i,'d',n,': ',s<-sum(sample(n,i)),'\n',sep='');i=ifelse(s<i*n/2,i-1,i+1)}

Тестовий запуск

> i=1;n=scan();while(i&i<=n){cat(i,'d',n,': ',s<-sum(sample(n,i)),'\n',sep='');i=ifelse(s<i*n/2,i-1,i+1)}
1: 9
2: 
Read 1 item
1d9: 9
2d9: 14
3d9: 10
2d9: 14
3d9: 9
2d9: 9
3d9: 12
2d9: 7
1d9: 9
2d9: 11
3d9: 17
4d9: 18
5d9: 25
6d9: 29
7d9: 33
8d9: 43
9d9: 45
> 

1

CoffeeScript, 106 99 байт

f=(n,k=1)->(x=k;x+=Math.random()*n|0for[k..0];console.log k+"d#{n}: "+x;k+=x<k*n/2&&-1||1)while k%n

# Previous attempt, 106 bytes
f=(n,k=1)->(x=i=0;x+=1+Math.random()*n//1while++i<=k;console.log k+"d#{n}: "+x;k+=x<k*n/2&&-1||1)while k%n

Безумовно

f = (n, k = 1) ->
 (x = k
 x += 1 + Math.random() * n | 0 for [k..0]
 console.log k + "d#{n}: " + x
 k += x < k * n / 2 && -1 || 1
 ) while k % n

1

Джулія, 77 байт

n->(N=1;while 0<N<n k=sum(rand(1:n,N));print(N,"d$n: $k
");N+=1-2(2k<N*n)end)

Більшість цього має бути зрозумілою - фактичний новий рядок використовується в printрядку, а не printlnдля збереження байта. rand(1:n,N)виробляє Nвипадкові цілі числа між 1 і n.


1

Рубі, 93 90 82 символів

->n{d=s=2
puts"#{d}d#{n}: #{s=eval'+rand(n)+1'*d}"while(d+=s<d*n/2.0?-1:1)>0&&d<n}

Проба зразка:

2.1.5 :001 > -->n{d=s=2;puts"#{d}d#{n}: #{s=eval'+rand(n)+1'*d}"while(d+=s<d*n/2.0?-1:1)>0&&d<n}[6]
1d6: 5
2d6: 10
3d6: 6
2d6: 5
1d6: 5
2d6: 8
3d6: 15
4d6: 18
5d6: 22

0

QBIC , 83 байти (неконкурентоспроможний)

:c=a{e=0[1,q|e=e+_rq,a|]?!q$+@d|!+a$+@:|+!e$~e<c/2|q=q-1\q=q+1]c=q*a~q=a|_X]~q=0|_X

Пояснення:

q                    Tracks the number of dice (is implicitly 1 at the start)
:                    Takes input from a CMD line parameter
[1,q|e=e+_rq,a|]     Rolls the dice separately
?!q$+@d|!+a$+@:|+!e$ Prints the roll result (requires an unfortunate amount of casting...)
~e<c/2|q=q-1\q=q+1]  Checks whether to increase or decrease
~q=a|_X]~q=0|_X      Tests the amount of dice and quits on either boundary.

0

PHP, 104 байти

for($n=$argv[$k=1];$k&&$k<$n;print$k."d$n: $x\n",$k-=$x<$n*$k/2?:-1)for($x=$i=0;$i++<$k;)$x+=rand(1,$n);

Бігайте з php -r '<code>' <N>

зламатися

for($n=$argv[$k=1];     // import input, init number of dice
    $k&&$k<$n;          // while 0<$k<$n
    print$k."d$n: $x\n",    // 2. print results
    $k-=$x<$n*$k/2?:-1      // 3. remove or add a die
)
    for($x=$i=0;$i++<$k;)   // 1. roll dice separately
        $x+=rand(1,$n);         // sum up results
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.