17
3
Roll for Initiative!
Introduction
In tabletop games like Dungeons and Dragons, when you begin a battle, all involved parties roll for initiative. In DnD 5e, this is 1d20 + DEX + Other bonuses
, where DEX
is the bonus given by your Dexterity stat. The characters that roll higher numbers go first. We'll use a similar, deterministic system in this challenge.
The Challenge
Write a program or function that, when given a list of characters, will output a list of characters in order of initiative.
A character is defined as this:
character = {
name: "name" // a string
statblock: [SPD, DEX, WHT] // a list of numbers
// DEX = dexterity, SPD = speed, WHT = weight
}
The formula for initiative is the following: $$\text{Initiative} = \left\lfloor{ \frac{\text{SPD}^2}{\sqrt{\lvert\text{DEX}\rvert}} }\right\rfloor - \text{WHT}$$
Input
A list of characters, unsorted. This can be a JSON object, a list of lists, a list of dictionaries, a series of strings etc.
It is guaranteed that all names will be unique.
Output
A list of characters, or character names, sorted by initiative order from highest to lowest, based on the above formula.
Rules
- IO can be used with any convenient method.
- Standard loopholes are forbidden.
- This is code-golf, so smallest program wins!
Sample IO
Input --> Output
[[Name, SPD, DEX, WHT], ...]
--> [[Name, SPD, DEX, WHT], ...] (or [Name, Name, ...])
---------
[[Alice,1,2,3],[Bob,10,5,0],[Charlie,3,2,1]]
--> [Bob, Charlie, Alice]
// Alice = -3, Bob = 44, Charlie = 5
[[Z,1,1,1],[B,1,1,1],[XY,5,1,1]]
--> [XY, Z, B]
// Retain the order of characters from the input if they have the same initiative.
// Z = 0, B = 0, XY = 24
[[Neg,-3,-3,-1],[SomeNeg,5,-2,-4],[NoNeg,4,6,8]]
--> [SomeNeg, Neg, NoNeg]
// Negative values are valid.
// Neg = 6, SomeNeg = 21, NoNeg = -2
[[Flo,1.5,2.5,3.5],[MoreFlo,2,2.5,3.5]]
--> [[MoreFlo,2,2.5,3.5], [Flo,1.5,2.5,3.5]]
// Floats are also valid.
// Flo = -2.5, MoreFlo = -1.5
[[Lonely,1,2,3]]
--> [[Lonely,1,2,3]]
// Input with 1 item.
[]
--> []
// Empty input leads to empty output.
[[Foo,2,1,4], [Baz,5,5,4], [Bar,5,1,4]]
--> [Bar, Baz, Foo]
// Foo = 0, Bar = 21, Baz = 7
[['Adam', 2, 4, 1], ['Eve', 2, 3, 1]]
--> [Adam, Eve]
// Adam = 2, Eve = 2
// If you do not floor, you'll end up with [Eve, Adam] (Adam = 2, Eve ~= 2.3)
Curious - where did this initiative formula come from? – Quintec – 2019-12-08T16:52:59.223
1Something I came up with on the fly while writing this, it's not really based on anything. – bigyihsuan – 2019-12-08T17:12:30.840
So it is. Thanks for catching it! – bigyihsuan – 2019-12-08T19:48:29.577
Can we sort the input in place (i.e whatever is passed into the function will be sorted when the function finishes)? – Noodle9 – 2019-12-08T21:54:10.073
So small dexterity is good here? – Paŭlo Ebermann – 2019-12-09T00:08:41.320
For some reason ignoring
DEX
parameter does not affect the final result. – game0ver – 2019-12-09T13:51:15.033I just added a new test case. You should not ignore
DEX
. If you look atBaz
in the last test case, you'll get7
if you useDEX
, and21
if you don't. – bigyihsuan – 2019-12-09T13:57:14.977@bigyihsuan But you get
– game0ver – 2019-12-09T14:17:22.757Bar, Baz, Foo
even if ignore it: check here, or do I miss something here?@game0ver Your formula fails for
[['A', 1, 1, 5], ['B', 2, 50, 5]]
. With the correct formula, you get[A, B]
, your formula returns[B, A]
– Black Owl Kai – 2019-12-09T15:09:28.427@BlackOwlKai thanks, your are right, didn't check that... Also I ended up doing some math and it turned out that the formula I used was completely arbitrary. There is an alternative way to write the formula but it doesn't save bytes unfortunately... – game0ver – 2019-12-09T15:23:48.773
Suggested testcase:
[['Adam', 2, 4, 1], ['Eve', 2, 3, 1]]
. Both have an initiative of 2, so input order should be retained and the output should be['Adam', 'Eve']
. But if a solution does not round down the first part, Adam stays at 2, but Eve gets to ~2.3, therefore the solution outputs['Eve', 'Adam']
– Black Owl Kai – 2019-12-10T08:56:09.857