Terra Mystica: Велоспорт

28

В настольной игре Terra Mystica есть очень интересная механика для одного из основных ресурсов - силы. Вместо того чтобы набирать и расходовать единицы мощности из банка, каждый игрок начинает игру с ровно 12 единицами мощности, которые распределены по трем «чашам», которые обозначены как I, II и III. Приобретая и тратя власть тогда просто перемещает власть между этими чашами:

  • Чтобы потратить единицу энергии, переместите ее из чаши III в чашу I (при условии, что у вас есть юнит в чаше III).
  • Когда вы получаете единицу энергии, если в миске I есть блок, переместите его в миску II. Если в чаше I нет ни одной единицы, а в чаше II есть единица, переместите ее в чашу III. Если все юниты уже находятся в чаше III, ничего не происходит.
  • Когда вы получаете или тратите несколько единиц одновременно, они обрабатываются по одной единице за раз.

Вот пример. Скажем, игрок начинает со следующего распределения мощности (приведенного по порядку I | II | III):

5 | 7 | 0

Их сила меняется следующим образом, если они получают и расходуют энергию несколько раз:

               5 |  7 |  0
Gain  3  ==>   2 | 10 |  0
Gain  6  ==>   0 |  8 |  4   (move 2 power from I to II, 
                              then the remaining 4 from II to III)
Gain  7  ==>   0 |  1 | 11
Spend 4  ==>   4 |  1 |  7
Gain  1  ==>   3 |  2 |  7
Spend 7  ==>  10 |  2 |  0
Gain 12  ==>   0 | 10 |  2   (move 10 power from I to II,
                              then the remaining 2 from II to III)
Gain 12  ==>   0 |  0 | 12   (the two excess units go to waste)

Ваша задача - вычислить результат одного из таких выигрышных или расходных событий.

Соревнование

Вам дают четыре целых числа в качестве входных данных. Первые три, I, II, III, представляют собой количество энергии в каждом из трех чаш. Они будут неотрицательными, и их сумма составит 12. Четвертое число P- это количество полученной или потраченной энергии, которое будет находиться в включенном диапазоне [-III, 24](поэтому вы можете предположить, что игрок никогда не попытается потратить больше энергии чем они в настоящее время могут, но они могли бы получить больше энергии, чем им нужно, чтобы перенести всю силу в чашу III).

Вы можете использовать эти числа в любом последовательном порядке, в качестве отдельных аргументов, в виде списка целых чисел или в виде строки, содержащей эти целые числа. Вы также можете взять в Pкачестве одного аргумента, а I, II, IIIкак отдельный список аргументов.

Выведите три целых числа I', II', III'которые представляют собой количество энергии в каждой чаше после P единицы были получены или потрачены, следуя правилам пояснено выше.

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

Вы можете использовать любой язык программирования , но учтите, что эти лазейки по умолчанию запрещены.

Это , поэтому самый короткий действительный ответ - измеренный в байтах - выигрывает.

Тестовые случаи

I II III P => I' II' III'
5 7 0 3    => 2 10 0
2 10 0 6   => 0 8 4
0 8 4 7    => 0 1 11
0 1 11 -4  => 4 1 7
4 1 7 0    => 4 1 7
4 1 7 1    => 3 2 7
3 2 7 -7   => 10 2 0
10 2 0 12  => 0 10 2
0 10 2 12  => 0 0 12
Мартин Эндер
источник
1
Я рекомендую удалить специфичные для пола местоимения и заменить их нейтральными по отношению к полу (или реструктурировать предложения): геймеры не обязательно должны быть мужчинами.
Грег Мартин
1
@GregMartin Конечно. Я поймал их всех?
Мартин Эндер
2
Похож на это; спасибо, что подумали об этом! Кроме того, Terra Mystica так хороша, как я слышал?
Грег Мартин
4
@GregMartin да. :)
Мартин Эндер
5
Нет энергии горит из чаши 2? Это просто кажется настолько неполным.
подробнее

Ответы:

6

Mathematica, 52 байта

{x=#-#4~Min~#,y=Max[#2+#-Abs[#4~Max~0-#],0],12-x-y}&

Это безымянная функция, которая принимает список в {I, II, III, P}качестве входных данных и возвращает список {I', II', III'}.

Решение в закрытой форме. Это еще не совсем оптимально ...

Мартин Эндер
источник
Думал, что могу сократить, но {##,12-+##}&[#-#4~Min~#,Max[#2+#-Abs[#4~Max~0-#],0]]&это на байт длиннее. Мне нравится, 12-+##хотя.
Грег Мартин
1
@GregMartin Я попробовал то же самое :)
Мартин Эндер
6

C 97 94 байта

f(i,j,k,n){for(;n;n-=n/abs(n))n<0?k?++i+--k:0:i?++j+--i:j?++k+--j:0;printf("%d %d %d",i,j,k);}

В разряженной форме:

f(i, j, k, n) {
    while (n) {
        if (n < 0) {
            if (k) {
                ++i; --k;
            }
            ++n;
        } else {
            if (i) {
                ++j; --i;
            }
            else if (j) {
                ++k; --j;
            }
            --n;
        }
    }
    printf("%d %d %d", i, j, k);
}
Steadybox
источник
5

Python 2, 104 байта

def f(i,d,t,g):
 x=min(i,g);i-=x;q=g>0;g-=x
 if q:d+=x;x=min(d,g);g-=x;d-=x;t+=x
 else:t+=x
 print i,d,t

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

Ungolfed:

def f(i,d,t,g):
 if g>0:
    x=min(i,g)
    g-=x
    i-=x
    d+=x    
    x=min(d,g)
    g-=x
    d-=x
    t+=x
 else:
    x=min(i,g)
    g-=x
    i-=x
    t+=x
 print(i,d,t)
mbomb007
источник
5

Haskell, 58 байт

f(a,b,c)d|m<-min a d,z<-min(c+d-max 0 m)12=(a-m,b+c+m-z,z)

Промежуточное значение mобозначает количество энергии, идущей от (или, если отрицательно) к первой чаше, zобозначает количество энергии в третьей чаше после действия. В последнюю минуту оптимизация одного байта изменила старое выражение для второй чаши от 12-a+m-zиспользования идентификатора a+b+c=12.

Тип естественного результата - тройка для мисок, поэтому входные данные также принимают чаши как тройки, а изменение мощности - как второй аргумент. Это позволяет обрабатывать все тестовые случаи с помощью одного приложения scanl:

*Main> scanl f (5,7,0) [3,6,7,-4,0,1,-7,12,12]
[(5,7,0),(2,10,0),(0,8,4),(0,1,11),(4,1,7),(4,1,7),(3,2,7),(10,2,0),(0,10,2),(0,0,12)]
Кристиан Сиверс
источник
5

Röda , 100 94 байта

f a,b,c,p{{c+=p;a-=p}if[p<0]else{{a--;b++;p--}while[p*a>0];{b--;c++;p--}while[p*b>0]};[a,b,c]}

Ungolfed:

f a,b,c,p {
    if [ p < 0 ] do
        c += p
        a -= p
    else
        { a-=1; b+=1; p-=1 } while [ p > 0 and a > 0 ]
        { b-=1; c+=1; p-=1 } while [ p > 0 and b > 0 ]
    done
    return a, b, c
}
fergusq
источник
Разве у Röda нет операторов ++and --?
Kritixi Lithos
@KritixiLithos Спасибо! Да, это так.
fergusq
3

GNU sed , 66 байт

Включает +1 для -r

/-/!{:
s/1,(.* )1/,1\1/
t}
s/(.*)(1+) -\2/\2\1/
s/(,,1{12}).*/\1/

Использует одинарный (см. Этот консенсус ).

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

/-/!{                  # If there is not a '-'
  :                    # start loop
  s/1,(.* )1/,1\1/     # move a 1 from before a ',' to after the ',' for every 1 after the space
                       # sed reads left to right, so this takes everything from the first bowl before starting on the second
  t                    # loop if something changed
}                      # end if
s/(.*)(1+) -\2/\2\1/   # take all of the 1s from after a '-' and move them to the begining.
                       # at the same time, remove that many 1s from the 3rd bowl
s/(,,1{12}).*/\1/      # remove everything after 12 1s in the third bowl
Райли
источник
3

Сетчатка ,  46  41 39 38 байт

Спасибо Мартину Эндеру за несколько полезных предложений!

+`1,(.*¶)1
,1$1
(.*)(1+)¶-\2$
$2$1
G`,

Принимает участие в одинарных. Первая строка содержит количество энергии в трех чашах, разделенных запятой, вторая строка - количество энергии для цикла.

Набор тестов - принимает все входные данные в одной строке и преобразует из десятичного в унарный и наоборот для удобства использования.

объяснение

+`1,(.*¶)1
,1$1

Положительный случай: мы многократно удаляем ведущий 1из второй строки и перемещаем a 1из первой непустой чаши в следующую, пока возможна эта операция (т. Е. Число циклов питания не равно нулю, а не все сила в третьем шаре). В sмодифицирующие средства single-line, что позволяет , .чтобы соответствовать также символ новой строки.

(.*)(1+)¶-\2$
$2$1

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

G`,

Оставляйте (grep) только строки, содержащие запятую. Это избавит от возможных остатков первой линии.

Лео
источник
3

Python 2, 91 байт

На основании этого ответа

def f(i,d,t,g):
 x=min(i,g);i-=x
 if g>0:y=min(d+x,g-x);d+=x-y;t+=y
 else:t+=x
 print i,d,t

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

Ungolfed:

def f(i,d,t,g):
 if g>0:
    x=min(i,g)
    y=min(d+x,g-x)
    i-=x
    d+=x-y
    t+=y
 else:
    x=min(i,g)
    i-=x
    t+=x
 print(i,d,t)
Алехандро Кастильо
источник
Добро пожаловать на сайт!
DJMcMayhem
2

Пакет, 87 байт

@set/a"i=%4-%1,j=%4*(-%4>>5)-%2-2*i*(-i>>5),i*=i>>5,j*=j>>5,k=12-i-j
@echo %i% %j% %k%

Используйте следующие формулы:

I' = min(I - P, 0)
II' = min(II + min(P, 0) - 2 * min(P - I, 0), 0)
III' = 12 - I' - II'

Так как у Batch нет оператора меньше чем, я вычисляю, i = min(-i, 0)используя i*=i>>5.

Нил
источник
2

Perl 6 , 99 байт

->\a,\b,\c,\d{d>0??[»+»] (a,b,c),|(|((-1,1,0)xx a),|((0,-1,1)xx a+b),|(0 xx*))[^d]!!(a- d,b,c+d)}

Позвольте a, bи cбудет количество начальных токенов в чашах I, II и III соответственно. Затем для случая добавления мощности создается список, содержащий aкопии триплета (-1, 1, 0), затем a + bкопии триплета (0, -1, 1)и бесконечные копии 0. Первые dэлементы этого списка, dявляющиеся количеством добавляемой мощности, поэлементно добавляются к начальному распределению мощности.

Для вычитания мощности (отрицательный d), используется простая замкнутая форма: (a - d, b, c + d).

Шон
источник
2

тинилисп , 134 байта

(d f(q((x y z p)(i p(i(l p 0)(f(s x p)y(a z p)0)(i x(f(s x 1)(a y 1)z(s p 1))(i y(f x(s y 1)(a z 1)(s p 1))(f x y z 0))))(c x(c y(c z(

Определяет функцию, fкоторая принимает четыре аргумента, три чаши ( x y z) и количество передаваемой мощности ( p), и возвращает список трех чаш после транзакции. Вот правильно размещенная версия со всеми тестами: попробуйте онлайн!

(d f                         Define f to be
 (q(                          a quoted two-item list (which acts as a function):
  (x y z p)                    Arglist: the three bowls x y z and power p
  (i p                         If p is nonzero
   (i (l p 0)                   then if p is negative (spending power)
    (f(s x p)y(a z p)0)          then take -p from z, add -p to x, and recurse with p=0
    (i x                         else (gaining power), if x is nonzero
     (f(s x 1)(a y 1)z(s p 1))    then take 1 from x, add to y, decrement p and recurse
     (i y                         else if y is nonzero
      (f x(s y 1)(a z 1)(s p 1))   then take 1 from y, add to z, decrement p and recurse
      (f x y z 0))))               else no moves possible; recurse with p=0
   (c x(c y(c z())))))))        else (p=0), cons x y z into a list and return it
DLosc
источник