In the original Shantae game, there are transformation dances that you have to input in time using the D-Pad, A, and B. If you complete a predefined sequence while dancing, you will transform into the corresponding form (or teleport or heal). Your task is to output the corresponding effect when given an input. The catch is that you may get extraneous dance moves in the input, both before and after, and there may not even be a dance in the input.

The Dances

Using UDLRAB for dance moves:

  • Monkey: DR
  • Elephant: DL
  • Spider: DA
  • Harpy: DB
  • Tinkerbat: DUU
  • Heal: DUA
  • Scuttle Town: DULR
  • Water Town: DURLAB
  • Oasis Town: DURRBA
  • Zombie Caravan: DULLBA
  • Bandit Town: DUBLBR


Input: a sequence of dance moves. This can contain Up, Down, Left, Right, B, A, and Wait values. Use any convenient encoding.

Output: a value corresponding to the first matching dance in the sequence or a distinct value if there is no match. You can encode this in any convenient way.


Using . for waiting:

  • DR → Monkey
  • UUU.DLUAB → Elephant
  • L.DDBALL → Harpy
  • DUBLBR → Bandit Town
  • DURLBANo match
  • DDUDR → Monkey
  • RLABNo match
  • .DUUBBB → Tinkerbat
  • DADRDL → Spider
  • .DURRBADR → Oasis Town
  • DURR.BANo match

Other Rules/Notes

  • Standard rules on loopholes and IO methods apply
  • Describe your encoding for dance moves and matching dances.
  • There may be more than one dance in the input. If that is the case, match only the first one that appears in the input.
  • Waiting interrupts dances.
  • 1
    \$\begingroup\$ Related \$\endgroup\$
    – Beefster
    May 1 '19 at 17:45
  • \$\begingroup\$ Now testcase 4 ends in DURLAB, which is Water Town \$\endgroup\$
    – Mayube
    May 1 '19 at 18:11
  • \$\begingroup\$ @Skidsdev. Good catch. I meant to make that a no match test case there. \$\endgroup\$
    – Beefster
    May 1 '19 at 18:11
  • 1
    \$\begingroup\$ You can encode this in any convenient way: may we return the matching sequence, e.g. "DURRBA" for Oasis Town? \$\endgroup\$
    – Arnauld
    May 1 '19 at 18:39
  • 1
    \$\begingroup\$ Random: Longish ago, using only 'input' and 'wait' (ie timed coin entries) the casinos (in a country that I won't mention and which you are unlikely to guess and which isn't my country)(connected to me only by "internet") had their slot machine software hacked at source such that a player could multiply their input pot by a largish number. They then played, won or lost and cashed out with far more than they had input. It was in due course discovered and fixed. I identified the method based on a general description of what was happening overall - supplied by a puzzled security investigator. \$\endgroup\$ May 1 '19 at 20:22

JavaScript (ES6),  92 88 61  59 bytes

Saved 2 bytes thanks to a suggestion from @tsh

Expects UdLRAB for the dance moves and . for waiting. Outputs either undefined if there's no match, or the sequence of the matching dance (e.g. dR for Monkey or dURLAB for Water Town).


Try it online!

or Try it with enhanced output

  • \$\begingroup\$ R|L|A|B -> [RLAB]? \$\endgroup\$
    – tsh
    May 2 '19 at 4:44
  • \$\begingroup\$ @tsh Actually, d([A-R]|U...) is apparently fine since any convenient encoding may be used for the input as well. Thanks! \$\endgroup\$
    – Arnauld
    May 2 '19 at 11:45

JavaScript (Node.js), 179 164 153 148 137 115 bytes

d=>{for(;d;d=d.slice(1))for(z of "R.L.A.B.UU.UA.ULR.URLAB.URRBA.ULLBA.UBLBR".split`.`)if(!d.search('D'+z))return z}

Try it online!

-11 bytes thanks to Arnauld's answer making me realize output can be simplified
-8 bytes thanks to flawr in chat helping me golf array empty checks
-12 bytes thanks to Shaggy

Takes input as a string in same formatting as OP test cases.

Outputs the matched dance string minus the leading D for a match, or undefined for no match.

The integer corresponds to the match's index in this array (0-indexed):

0  - Monkey: DR
1  - Elephant: DL
2  - Spider: DA
3  - Harpy: DB
4  - Tinkerbat: DUU
5  - Heal: DUA
6  - Scuttle Town: DULR
7  - Water Town: DURLAB
8  - Oasis Town: DURRBA
9  - Zombie Caravan: DULLBA
10 - Bandit Town: DUBLBR

Probably room for golfing, especially in compressing the dance move set.


General approach

Iterate through the input string, removing the first character each time and checking if the resulting string starts with a valid dance string.

The whole thing is just a for loop inside a for loop, I'll break it down into 3 parts:
- Condition
- Inner Loop
- Outer Post


This is the termination condition for the outer loop, IE while this is true, keep looping.
Quite simple:


d is a string, in JS empty strings are falsey "d is not empty".

Inner Loop

This is the stuff that happens each loop:

for(z of "R.L.A.B.UU.UA.ULR.URLAB.URRBA.ULLBA.UBLBR".split`.`)

So first we define an array with:


This creates an array of all dance move strings, missing the D at the start of each of them (They all begin with D). We'll call this array x
There's probably significant golfing potential here.

We then iterate through each item in x (stored in z), and run the following:

if(!d.search('D'+z))return z

This uses d.search to return the index in the string of 'D'+z. If and only if d begins with 'D'+z, this will return 0, which is a falsey value in JS.
As such, !d.search will only be true when the string starts with 'D'+z.

Note: This is why we omit the Ds in x, as it saves us 10 bytes (1 per dance), and only costs us a single byte in this search

Then, if the search matches, we return z. This is the dance we've found, without the leading D.

If not, we keep looping.

Outer Post

This is stuff that happens at the end of each iteration of the outer loop:


Just remove the first character from d

No Match

If d becomes empty and no match has been found, the end of the function is reached. This implicitly returns undefined as per standard JavaScript behavior

  • \$\begingroup\$ @Shaggy I'd just made the substr -> slice change myself, and I keep forgetting that d is a string, not an array. Empty strings are falsey :P And good catch on the braces, I forgot about the whole 1 child statement thing \$\endgroup\$
    – Mayube
    May 1 '19 at 20:12
  • \$\begingroup\$ @Shaggy ah nice! I assume d.search will return 0 if the search string is at the start of d, which is of course a falsey value \$\endgroup\$
    – Mayube
    May 1 '19 at 20:25
  • \$\begingroup\$ Yep. It's kinda like indexOf but it supports RegEx, which is irrelevant here. \$\endgroup\$
    – Shaggy
    May 1 '19 at 20:27
  • \$\begingroup\$ And of course it's also 1 byte shorter ;) \$\endgroup\$
    – Mayube
    May 1 '19 at 20:29
  • \$\begingroup\$ 82 bytes \$\endgroup\$
    – Shaggy
    May 1 '19 at 20:56

Retina, 53 43 42 37 bytes


Try it online!

Slightly deviates from the standard input and output to make use of ;: as DU respectively. Inspiration from tsh, saving 5 bytes.

Matches the first dance and outputs it, after seeing Arnauld's answer. Saved 10 bytes thanks to Neil suggesting using the list stage L and limiting the output to the first match. Saved one byte thanks to tsh shortening the regex.

The header and footer just allow for multiple inputs and making the output readable, respectively.

  • \$\begingroup\$ 43 bytes. Can be translated to Retina 0.8.2 by using 1! instead of 0L, but in that case the footer won't work (1M! will work even with the footer). \$\endgroup\$
    – Neil
    May 1 '19 at 20:02
  • \$\begingroup\$ @Neil Thanks for the golf, I always forget about L. \$\endgroup\$ May 1 '19 at 20:21
  • \$\begingroup\$ Maybe R|L|A|B -> [RLAB]? \$\endgroup\$
    – tsh
    May 2 '19 at 7:12
  • \$\begingroup\$ @tsh Thanks! That was a holdover from my previous approach and I never checked it. \$\endgroup\$ May 2 '19 at 16:52
  • \$\begingroup\$ One more step, what about D[RLAB]|DU(...) instead? \$\endgroup\$
    – tsh
    May 3 '19 at 3:39

Perl 5 -p, 47 bytes


Try it online!

Returns the dance's code (allowed as per @Arnauld's comment) or blank if no match.


Charcoal, 48 bytes


Try it online! Link is to verbose version of code. Explanation:


Split the compressed string RDLDADBDUUDUADULRDURLABDURRBADULLBADUBLBR (which contains all of the dances except for the leading D) on D, and then prefix the D back to each entry.


For each dance, concatenate it to the input and find the first position of the dance in the concatenation, plus also take the length of the dance. For dances that weren't found this means that the result will be the length of the input string instead of -1.


Take the minimum of those results, i.e. the position and length of the dance that appeared first.


Extract that dance from the original string.


Jelly, 33 28 bytes


Try it online!

Takes as input a list of integers representing the moves:

0 D
1 U
2 R
3 B
4 L
5 A
6 .

Returns a wrapped integer for the answer, or a list of all these integers for no match:

1 Monkey
2 Harpy
3 Elephant
4 Spider
5 Tinkerbat
6 Heal
7 ScuttleTown
8 OasisTown
9 WaterTown
10 BanditTown
11 ZombieCaravan
1,2,3,4,5,6,7,8,9,10,11 NoMatch

TIO link includes code in the footer to translate these back to the strings in the question, but is not needed for the program to function using the integers specified here.


05AB1E, 104 bytes

'dð.•—Áå•«•¼L?D/8¢Am.Z¼ž•6BSèJ#«å.•g³ç¼…¬ÿ¬Õ‚YÙ•“ÆÚàæɾ ÿ“#.•664Îè¡HĆ∍•¸«“scuttle„©Ê´ bandit“#ð“‰à“«««sÏ

Try it online!

I wrote this monstrosity without realizing I could use numbers for name moves...


sfk, 119 91 bytes

xex -i -firsthit

Try it online!

Gives the first dance present as a sequence of moves.

(xex is just a stream editor, and in this case _<pattern>_ is search text)


05AB1E, 28 27 bytes

Saved 1 byte thanks to Grimy


Try it online!

Outputs either the match (i.e. 10 for Monkey) or -1 for no match

1 = D
0 = R
2 = L
3 = A
4 = B
5 = U
6 = .


Œ.Δ                           # Find the first substring of the input
                         Q    # that is equal to
                          Z   # any element in
   •1Λ*#$ß‘«∍@…9\÷•           # 29058694378496950170872579685936
                   6B         # converted to base-6
                     1¡       # split on 1's
                       1ì     # with a 1 prepended to each

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.