Аліса і Боб побилися


24
  • Аліса (А) та Боб (Б) вирішили битися.
  • У кожного учасника бою 10 здоров'я.
  • Вони по черзі котять 6-сторонній штамб на шкоду.
  • Ця шкода знімається зі здоров’я опонента.
  • Зрештою або Аліса, або Боб переможуть ворога.

Покажіть мені, як пройшов бій. Виведення цих кодів на дії, які відбулися.

Атака

B a A    
^ Combatant
  ^ Action (attack)
    ^ Target

Рулон

B r 4
^ Combatant
  ^ Action (roll)
    ^ Value

Зміна здоров'я

A h 6
^ Combatant
  ^ Attribute (health)
    ^ Value   

Виграти

A w 
^ Combatant
  ^ Action (win)

Приклад виводу:

A a B
A r 4
B h 6
B a A
B r 6
A h 4
A a B
A r 6
B h 0        
A w

Ось правила:

  • Пишіть будь-якою мовою.
  • Один рулон штанги повинен мати рівний шанс отримати будь-яке з чисел 1, 2, 3, 4, 5 або 6.
  • Аліса завжди починається (Боб - рицарський, по-старому).
  • Виведіть дію на кожен виток.
  • Ви повинні повідомити про атаку, прокрутити, пошкодити та виграти дії.
  • Бойовики - це великі регістри, дії - малі.
  • Він не повинен послідовно давати однаковий результат.
  • Між бойовим вивідником, дією та значенням має бути принаймні один символ пробілу.
  • Дія виграшу відбувається тоді, коли суперник має нульовий стан або менше.
  • Усі частини дії повинні бути в одному рядку.
  • На рядок має бути одна дія.
  • Виграє найменше байт.

Майте це!


9
Імена Аліса (А) та Боб (В) надають мені зворотній зв'язок до класу безпеки мережі. Актор Аліса (А) надсилає пакет Боб (Б) з ключем ... тощо ...
Чарівна восьминога Урна

21
@MagicOctopusUrn це вони. Вони зазвичай намагаються спілкуватися. На жаль, конфлікт часто виникає, коли спілкування порушується.
AJFaraday

7
Я сумую за тими днями, коли ми намагалися з'ясувати, як приховати свої таємниці від Меллорі ... це були простіші часи ...
Боб

4
@Bob Mallory насправді щось відволікає. Це Єва, на яку потрібно стежити.
AJFaraday

3
@ msh210 добре, важлива деталь у гольф-коді полягає в тому, що всі приймають однакові проблеми, але ось логіка: - якби ви грали в Dungeons and Dragons, ви б сказали: "Я буду бити гобліна", то ти " d рол для ефективності, а потім реалізуйте результат рулону. Рулон безглуздий, якщо ніхто не знає, для чого ви котиться.
AJFaraday

Відповіді:


5

05AB1E , 49 байт

"BaABr0Aha"S3ô»D„AB‡[6LΩ©Tǝ¤H®-©16ǝ=®0‹#s]н…ÿ w?

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

Пояснення

"BaABr0Aha"                                        # push the initial state of B
           S                                       # split to list of characters
            3ô                                     # divide into 3 parts
              »                                    # join each part on space and all on nl
               D„AB‡                              # make a copy with A and B inverted
                     [                             # start a loop
                      6LΩ©                         # pick a random number in [1 ... 6]
                          Tǝ                       # insert at position 10 of the string
                            ¤H                     # get the last char of the string and
                                                   # convert from hex
                              ®-©                  # subtract the random number
                                 16ǝ=              # insert at position 16 and print
                                     ®0‹#          # if the hp is less than 0, break
                                         s         # swap the other string to the stack top
                                          ]        # end loop
                                           н…ÿ w?  # print the winner

13

Python 3 , 131 байт

x,y="AB"
from random import*
X=Y=10
p=print
while X>0:p(x,"a",y);d=randint(1,6);p(x,"r",d);Y-=d;p(y,"h",Y);x,y,X,Y=y,x,Y,X
p(y,"w")

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

-8 байт завдяки службовому
значенню -2 байти завдяки ChooJeremy


5
попереднє визначення p=printдозволить заощадити близько 8 байт.
officialaimm

Оскільки y завжди перемагає в цій точці (І тільки X атаки в циклі, який згодом поміняється на Y), вам не потрібно перевіряти, чи y програв. - ChooJeremy - З огляду
NoOneIsHere

@NoOneIsHere дякую, що передав мені повідомлення: D
HyperNeutrino

randint(1,6)може бути замінено на id(X+Y)//3%6+1, хоча розподіл не зовсім рівномірний.
Вінсент

@Вінсент Я не бачу сенсу згинати правила, якщо це навіть не допомагає скоротити його ...
HyperNeutrino

7

C (gcc) , 146 141 байт

f(A,B,r,t,a,b){for(A=B=10;r=1+clock()%6,A*B>0;t=!t)printf("%c a %c\n%c r %u\n%c h %i\n",a=65+t,b=66-t,a,r,b,t?A-=r:(B-=r));printf("%c w",a);}

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

Де-гольф:

f(A,B,r,t,a,b){
    for(A=B=10; //Initialize HP
        r=1+clock()%6, // Get the number of processor cycles the program has consumed. This is relatively random, so I call it good enough.
        A*B>0;t=!t) // Flip t for change of turns
        printf("%c a %c\n%c r %u\n%c h %i\n", // Print the turn
            a=65+t,b=65+!t,a,r,b, // 65 is ASCII for 'A', 66 for 'B'
            t?A-=r:(B-=r)); // Deduct the damage.
    printf("%c w",a); // Print the winner
}

2
Чи можете ви зберегти байт за допомогою a=65+t,b=66-t?
moopet

A*B>0заощадить вам кілька байт.
Олів'є Грегоар

A*Bзаощадить ще більше, але я начебто поспішаю з банкоматом. Я

Знайдено помилку в костях {6,4,3,1,5}. б перемагає зі здоров’ям -4. Дивіться TIO Я змінив ваш калькулятор на кістки, щоб демонструвати цю помилку.
GPS

@GPS Спасибі, я зараз виправити це.

7

Python 3 , 127 байт

Це вдосконалення щодо відповіді @HyperNeutrino , яке не вміститься в коментарі. Дивіться пояснення нижче.

x,y="AB"
s=id(0)
X=Y=10
p=print
while X>0:p(x,"a",y);s=s**7%~-2**67;d=s%6+1;p(x,"r",d);Y-=d;p(y,"h",Y);x,y,X,Y=y,x,Y,X
p(y,"w")

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


Епічний квест про коротший рулон кісток пітона

TL; DR: За допомогою шифрування RSA можна відшаровувати 4 байти від стандартного рулону кісток пітона.

Я хотів побачити, чи можна скоротити стандартний рулон на кістки пітона ( 32 байти ):

from random import*;randint(1,6)

Зокрема, id(x)досить зручно вносити певну недетерміновану цінність у програму. Моя ідея тоді полягала в тому, щоб якось зафіксувати це значення, щоб створити деяку фактичну випадковість. Я спробував кілька підходів, і один з них окупився: шифрування RSA .

Шифрування RSA, завдяки своїй простоті, вимагає тільки кілька байт: m**e%n. Наступне випадкове значення може бути створене за допомогою шифрування попереднього. Припускаючи, що (e,n)ключ доступний, рулон з кістки може бути записаний з 22 байтами :

s=id(0);s=s**e%n;s%6+1

Це означає, що у нас є приблизно 10 байт для визначення дійсного ключа RSA. Тут мені пощастило. Під час своїх експериментів я почав використовувати Mersenne prime M67 лише для того, щоб пізніше зрозуміти, що Mersenne допустив помилку, включивши M67 у свій список. Це виявляється продуктом p=193707721і q=761838257287. Я знайшов свій модуль:

n=~-2**67

Тепер показник і тотант Charmichael (p-1)*(q-1) повинні бути одночасно. На щастя , знову ж , перше просте число, не ділять totient п тільки одна цифра довго: 7. кидок кісток , то можна записати з допомогою 28 байт (4 байта менше , ніж стандартний підхід):

s=id(0);s=s**7%~-2**67;s%6+1

Хороша річ з M67 - це те, що генероване випадкове значення має 66 біт, що більше, ніж звичайні 64-бітні RNG. Крім того, використання RSA дає змогу повернутися назад у часі, дешифруючи поточне значення кілька разів. Ось ключі шифрування та розшифрування:

Encryption: (7,                    147573952589676412927)
Decryption: (42163986236469842263, 147573952589676412927)

Я, безумовно, не є експертом у галузі статистики чи криптографії, тому я не можу реально сказати, перевіряє чи цей RNG критерії "доброї випадковості". Я написав невеликий орієнтир, який порівнює стандартне відхилення зустрічальності від 1 до 6 рулонів з кістки, використовуючи різні RNG. Схоже, запропоноване рішення працює так само, як і інші.


3
Вражаюча робота! :)
HyperNeutrino


4

Java (JDK 10) , 180 байт

v->{var r="";int p=0,H[]={10,10},h=0;for(;H[0]*H[1]>0;)r+=r.format("%3$c a %4$c%n%3$c r %d%n%4$c h %d%n",h+=Math.random()*6-h+1,H[p]-=h,p+65,(p^=1)+65);return r+(char)(66-p)+" w";}

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

Кредити


1
Java 10 має var? o.Ô Мені дійсно потрібно незабаром дослідити деякі нові характеристики .. У будь-якому випадку, ви можете пограти в 4 байти, змінивши масив char на масив int-array:v->{var r="";int P[]={65,66},p=0,H[]={10,10},h=0;for(;H[0]*H[1]>0;)r+=r.format("%3$c a %4$c%n%3$c r %d%n%4$c h %d%n",h+=Math.random()*6-h+1,H[p]-=h,P[p],P[p^=1]);return r+=P[p^1]+" w";}
Кевін Круїйсен

1
@KevinCruijssen Так, у Java 10 є var. Не потрібно читати далі, це в основному єдина зміна, яка може бути використана для нас, гольфістів. І ні, я не можу зробити те, що ви пропонуєте: перевірте останній рядок результату: він стає 65 wзамість A w. Ось чому я витягнув це з int ...висловлювання: пограти в декілька байтів ;-)
Олів'є Грегоар

1
@KevinCruijssen Я виконав кілька прикладів тут: codegolf.stackexchange.com/a/159922/16236
Олів'є



3

Рубі , 122 120 96 92 91 байт

f=->x=?A,y=?B,m=10,n=m{p [x,?a,y],[x,?r,r=1+rand(6)],[y,?h,t=n-r]
t<1?p([x,?w]):f[y,x,t,m]}

Збережено 1 байт завдяки Asone Tuhid .

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



Боюся, що ваша альтернатива не працює, "Усі частини дії повинні бути в одній лінії". Хоча, чи можливо зробити таку ж оптимізацію з символом вкладки?
AJFaraday

@AJFaraday Чи допустимо виводити рядки у форматі ["A", "a", "B"]? Якщо це так, у мене є цей 96-байтовое рішення.
Крістіан Лупаску

Якщо вони виводять один на рядок. Це має зробити.
AJFaraday

-1 байт, якщо ви заміните ?(p [x,?w]):на?p([x,?w]):
Асона Тухід

3

Java 8, 230 байт

v->{for(int h=104,a=h,x=0,y=1,A=10,B=A,r=0,t=0,T;a<119;)System.out.printf("%c %3$c %c%n",(x=a>h|A*B<1?x^1:x)+65,y=(a<98?t=r+=Math.random()*6-r+1:a>h?(T=x<1?A-=t:(B-=t))<0?0:T:A*B<1?-16:(x^1)+17)+48,a=a<98?114:a>h?104:A*B<1?119:97);}

Примітка: вже є відповідь на Java набагато коротша, тому обов'язково підтвердіть його ! Однак я використовую зовсім інший підхід, тому я вважав, що варто також розміщувати повідомлення.

Пояснення:

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

v->{                     // Method with empty unused parameter and no return-type
  for(int h=104,         //  Temp integer with unicode for 'h' to save bytes
          a=h,           //  Second part (Action)
          x=0,           //  First part
          y=1,           //  Third part
          A=10,          //  Score player A, starting at 10
          B=A,           //  Score player B, starting at 10
          r=0,           //  Random dice-roll
          t=0,           //  Previous dice-roll
          T;             //  Temp integer
      a<119;)            //  Loop until there is a winner
     System.out.printf(  //   Print
      "%c %3$c %c,%n",   //    The three parts with spaces, and a new-line
      (x=                //    First part:
         a>h             //     If the previous action is 'r',
         |A*B<1?         //     or there is a winner:
           x^1           //      Change A→B or B→A
         :               //     Else:
          x)             //      A/B remains unchanged
       +65,              //     Add 65 to convert 0/1 to 65/66 (unicode values of A/B)
      (y=                //    Third part:
         (a<98?          //     If the previous action was 'a'
           t=r+=Math.random()*6-r+1
                         //      Roll the dice, and save it in `t`
          :a>h?          //     Else-if the previous action was 'r':
           (T=x<1?       //      If the first part changed to player A:
            A-=t         //       Subtract the previous dice-roll from A
           :             //      Else:
            (B-=t))      //       Subtract the previous dice-roll from B
           <0?           //      If this score is below 0:
            0            //       Use 0
           :             //      Else:
            T            //       Use this score
         :               //     Else (the previous action was 'h'):
          A*B<1?         //      Is there a winner:
           -16           //       Change the third part to a space
          :              //      Else:
           (x^1)+17)     //       Change the third part to the other player
       +48,              //     Add 48 to convert it to unicode
       a=                //    Second part:
         a<98?           //     If the previous action was 'a': 
          114            //      Change it to 'r'
         :a>h?           //     Else-if the previous action was 'r':
          h              //      Change it to 'h'
         :               //     Else (the previous action was 'h'):
          A*B<1?         //      If either score is 0:
           119           //       Use 'w'
          :              //      Else:
           97);}         //       Use 'a'


2

Пакетна, 174 байт

@set/aA=B=10
@set c=A
@set d=B
:g
@set/ar=%random%%%6+1,h=%d%-=r
@echo %c% a %d%
@echo %c% r %r%
@echo %d% h %h%
@if %h% gtr 0 set c=%d%&set d=%c%&goto g
@echo %c% w

Пояснення: %змінні посилання підміняються під час розбору. Це має дві корисні переваги:

  • %d%-=rвіднімання rзі змінної, названої d(тобто непряма посилання)
  • set c=%d%&set d=%c% це просто прямий своп.

2

PHP 7.1: 159 байт

<?php $A=$B=10;$t='AB';while($A>0&&$B>0){$a=$t[0];$b=$t[1];$d=rand(1,6);$$b-=$d;echo"$a a $b\n$a r $d\n$b h {$$b}\n";$t=strrev($t);}echo($A>0?'A':'B')." w\n";

Запустити його в браузері тут!

PHP 5.6: 156 байт

<?php $A=$B=10;$t='AB';while($A>0&&$B>0){list($a,$b)=$t;$d=rand(1,6);$$b-=$d;echo"$a a $b\n$a r $d\n$b h {$$b}\n";$t=strrev($t);}echo($A>0?'A':'B')." w\n";

Запустити його в браузері тут!

Ось як виглядає рішення PHP 5.6 з форматуванням та коментарями:

<?php
// Initialize both HP counters
$A = $B = 10;

// Set the turn order as a string (which 5.6 allows to be unpacked into a list)
$t = 'AB';

// Run this loop as long as both players have HP
while ($A > 0 && $B > 0) {
    // Unpack the turn string into $a and $b variables; on the first run, $a = 'A'
    // and $b = 'B'. This is no longer possible in PHP 7.0, so the PHP 7.0
    // solution needed to use an array instead.
    list($a, $b) = $t;

    // Set damage to a random number between 1 and 6
    $d = rand(1, 6);

    // Subtract the damage from the referenced value $b. On the first turn, this
    // is 'B', so this ends up subtracting $d from $B. Next turn, $b will be 'A',
    // so it'll subtract $d from $A
    $$b -= $d;

    // Echo the string (interpolated values)
    echo "$a a $b\n$a r $d\n$b h {$$b}\n";

    // Reverse the turn order string ('AB' becomes 'BA', which will affect the
    // call to list in the first line of the while-loop)
    $t = strrev($t);
}

// Someone's run out of HP; figure out whom by figuring out who still has HP
echo ($A > 0 ? 'A' : 'B') . " w\n";

1

Баш, 178 байт

A=10 B=10 e=echo
a(){ $e $1 a $2;d=$((RANDOM%6+1));$e $1 r $d;eval $2=$((${!2}-$d));$e $2 h ${!2};[ ${!2} -gt 0 ];}
while a A B && a B A;do cd;done;[ $A -gt 0 ]&&$e A w||$e B w

1

F #, 238 235 байт

Я думав, що у мене все добре, але ти мене далеко перевершив!

let p=printfn
let mutable A=10
let mutable B=A
let x h a d=
 p"%s a %s"a d
 let i=(new System.Random()).Next(1,7)
 let j=h-i
 p"%s r %i"a i
 p"%s h %i"d j
 if j<=0 then p"%s w"a
 j
while A*B>0 do
 B<-x B"A""B"
 if B>0 then A<-x A"B""A"

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

Дякую Роґему за чудову пораду використовувати A * B> 0 замість A> 0 && B> 0 (знімає 3 байти).

Дякую також офіційноімму, який натяк на попередньо визначений printf у відповіді Python допоміг мені також відрізати кілька байтів.


1
Порада, яку я отримав від @OlivierGregoire: A*B>0заощадить вам ще пару.

Це абсолютно геніально. Любіть це. Велике спасибі!
Ciaran_McCarthy

1

Haskell , 204 байти

Моя спроба з Haskell, я, на жаль, не зміг зробити це більш конкурентоспроможним

import System.Random
main=getStdGen>>= \g->putStr$q(randomRs(1,6)g)10(10::Int)"A ""B "
(!)=(++)
l="\n"
q(x:z)a b p o=p!"a "!o!l!p!"r "!show x!l!o!"h "!show n!l!if n<1then p!"w"else q z n a o p where n=b-x

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

Пояснення:

import System.Random  --import random module
main=                        --main function, program entry point
 getStdGen                   -- get the global random number generator
   >>= \g->                  --using the random generator g
       putStr $ q            --print the result of function q, passing in ..
          (randomRs (1,6) g) --an infinite list of random numbers, 1 to 6 generated by g
           10 (10::Int)      --the starting health of both players, 
                             --type annotation sadly seems to be required
           "A " "B "         --The names of the players,
                             --with an extra space for formatting
(!)=(++) --define the operator ! for list (String) concatenation, 
         -- we do this a lot so we save a bit by having a one byte operator
l="\n"   -- define l as the newline character

q      --define function q                         
 (x:z) --our list of random numbers, split into the next number (x) and the rest (z)
 a     -- the health of the active player
 b     -- the health of the player getting attacked
 p     -- the name of the active player
 o     -- the name of the player getting attacked
=
  p!"a "!o!l --create the attack action string with a newline
 !p!"r "!show x!l -- append the roll action
 !o!"h "!show n!l -- append the health remaining
 !           -- append the result of the following if
  if n<1     -- if the player being attacked has been defeated
  then p!"w" -- append the win string for the active player
  else q z n a o p  --otherwise append the result of calling q again with 
                    --rest of the random numbers, and the active players swapped
  where n=b-x -- define the attacked player's new health n
              -- their current health b - the random roll x

Ви можете ознайомитися з нашими порадами щодо гольфу в Хаскеллі . Наприклад , where m=b-xможна помістити в щиток: |m<-b-x=.
Лайконі

Ви можете втратити лямбда і один набір дужок переставивши деякі параметри: main=putStr=<<q"A "10"B "10.randomRs(1,6::Int)<$>getStdGen. Ви також можете скористатися списком і сформулювати його, щоб позбутися від переосмислення (++). Останнє, де, здається, не вигідно просто використовувати b-xвсюди.
Ангс

1

Джулія 0,6 , 175 байт

p=println()
f(l="AB",h=[10,10],a=1)=(while min(h...)>0;d=3-a;p(l[a]," a ",l[d]);r=rand(1:6);h[d]-=r;p(l[a]," r ",r);p(l[d]," h ",max(h[d],0));a=d;end;p(l[findmax(h)[2]]," w"))

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

Довга, безгольована версія:

function status(player, health)
    println("$player h $(max(0,health))")
end

function roll(player)
    x = rand(1:6)
    println("$player r $x")
    x
end

function play()
    players = ["A","B"]
    healths = [10, 10]
    attacker = 1

    while min(healths...) > 0
        println("$(players[attacker]) a $(players[3-attacker])")
        healths[3-attacker]-=roll(players[attacker])
        status(players[3-attacker], healths[3-attacker])

        attacker = 3 - attacker
    end

    winner = findmax(healths)[2]
    println("$(players[winner]) w")
end

Здається, у вашому TIO-посиланні немає жодного результату.
AJFaraday

Так, я не знаю, чому Тіо це не подобається. Це добре працює на моїй машині. Я розберуся, якщо встигну.
niczky12

1

VBA, 222 185 179 байт

Це рекурсивне рішення передбачає 3 під

  1. g - початок гри, що починається з першого повороту
  2. t викликається для кожного ходу . Тут використовується рекурсія.
  3. p коротше Debug.Print при використанні більш ніж у 3 рази (лише 4 у цьому рішенні) Редагувати: Тепер, коли я дізнався, що Debug.?це прийнятна альтернатива Debug.Print, Debug.?xкоротше, ніж викликати Sub для друку.
Sub g()
t "A",10,"B",10
End Sub
Sub t(i,j,x,h)
d=Int(Rnd()*6)+1
Debug.?i &" a "&x
Debug.?i &" r "&d
h=h-d
If h<1Then
Debug.?i &" w"
Else
Debug.?x &" h "&h
t x,h,i,j
End If
End Sub

Це було веселим викликом. Якщо ви знаєте онлайн-перекладача, наприклад TIO для VB6 / VBScript / VBA, залиште коментар. Тоді я можу розмістити посилання на робоче рішення.

Якщо ви хочете перевірити цей код і встановити Microsoft Excel, Word, Access або Outlook (лише для Windows), натисніть Alt + F11, щоб відкрити ID VBA. Вставте новий модуль коду (Alt + I, M) і очистіть опцію явного. Потім вставте код і натисніть F5, щоб запустити його. Результати повинні відображатися у вікні негайного натискання (натисніть Ctrl + G, якщо ви його не бачите).

Редагувати 1: Видалене пробіл, який редактор VBA автоматично додаватиме назад. Зменшено на 37 байт
Правка 2: Видалено Sub p () *, щоб зберегти 6 байтів після навчання Debug.?- прийнятна альтернатива Debug.Print. Виклик Sub для обробки Debug.?лише економить байти після більш ніж шести дзвінків.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.