Повторная игра в кости

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](включительно), умноженном на количество играющих в данный момент костей, не допускается, так как это не позволяет точно имитировать бросание нескольких костей.
  • Стандартные лазейки запрещены
  • Это , поэтому выигрывает самый короткий ответ в байтах

Leaderboard

Фрагмент стека в нижней части этого поста создает таблицу лидеров из ответов а) в виде списка кратчайшего решения для каждого языка и б) в качестве общей таблицы лидеров.

Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:

## 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

Mego
источник
Я нахожу это запутанным. Пример ответа, пожалуйста?
Hipe99
Пример ответа , так как примеры являются краткими.
Hipe99
Ваше редактирование уточнено. Благодарность!
Hipe99
16
Вы уверены в своей арифметике? Обычный d6 имеет средний крен 3,5.
Питер Тейлор
11
Все средние значения в ваших примерах кажутся неправильными
edc65

Ответы:

3

Mathematica, 95 89 80 символов

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

Ungolfed

For[
  k = 1,
  0 < k < #,
  If[
    Print[k, d, #, ": ", x = Tr[{1, #}~RandomInteger~k]];
    x < k/2 #,
    k--,
    k++
  ]
] &
shrx
источник
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;}

РЕДАКТИРОВАТЬ: Добавлен дополнительный байт для форматирования. Забыл, что там есть IF, который, благодаря удалению текста "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

РЕДАКТИРОВАТЬ: Благодаря @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суффикс обязательным? Это неясно из вашего вопроса.

steenbergh
источник
Требование гласит: «обратите внимание, что вывод в скобках для пояснения и не требуется». Этот путь кажется короче: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>

rink.attendant.6
источник
Вы могли бы изменить 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}
user81655
@ user81655 Спасибо. По какой-то причине ваша версия вызвала много посторонних выводов, поэтому я переместил console.logв другой forцикл (стоил мне на 1 символ больше, чем ваш). Все еще получил его до 106
rink.attendant.6
Я просто написал это без тестирования, поэтому я рад, что в основном это сработало. :)
user81655
Вы можете получить один символ, заменив k&&k!=nусловие сравнениемk%n!=0
Jupotter
@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.)


Ps. Увидев заголовок, я изначально хотел ответить на это в 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
> 
MickyT
источник
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

Ungolfed

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
rink.attendant.6
источник
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
manatwork
источник
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.
steenbergh
источник
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
Titus
источник