# Indexing Cha-Cha Slide

## Introduction:

Although I originally had a Dutch song in my head, where the lyrics are: "Doe 'n stapje naar voren, en 'n stapje terug" (which translated to "Take a little step forward, and a little step back"), when I searched for the full lyrics, I realized they only got back and forth, and never sideways.

So, instead I now use the lyrics of Mr C The Slide Man a.k.a. DJ Casper - Cha-Cha Slide for this challenge.

If we ignore everything else and only look at the words "left", "right", "back", and "hop" (I counted "hop" as forward) including the mentioned amounts, the full song will have the following list (I'm using the abbreviations LRBH here):

LBHRLLBHRLBHHRRLLLRLBHHHHRRLLLBHHHHHRLRLRLHRLLBHHLRLBHH


Here the full song lyrics in a hideable JavaScript code-snippet (to save space), where the moves and amounts are surrounded with blocked brackets:

To the [left], take it [back] now y'all
One [hop] this time, [right] foot let's stomp
[Left] foot let's stomp, cha cha real smooth

Turn it out, to the [left]
Take it [back] now y'all
One [hop] this time, [right] foot let's stomp
[Left] foot let's stomp, cha cha now y'all

Now it's time to get funky
To the [right] now, to the [left]
Take it [back] now y'all
One [hop] this time, one [hop] this time
[Right] foot [two] stomps, [left] foot [two] stomps
Slide to the [left], slide to the [right]
Criscross, criscross
Cha cha real smooth

Let's go to work
To the [left], take it [back] now y'all
[Two] [hops] this time, [two] [hops] this time
[Right] foot [two] stomps, [left] foot [two] stomps
Get funky with it, aahhhhhhhhhh yaaaa
Come on, cha cha now y'all

Turn it out, to the [left]
Take it [back] now y'all
[Five] [hops] this time
[Right] foot let's stomp, [left] foot let's stomp
[Right] foot again, [left] foot again
[Right] foot let's stomp, [left] foot let's stomp

Freeze, everybody clap yo hands
Come on y'all, check it out
How low can you go?
Can you go down low?
All the way to da floor?
How low can you go?
Can you bring it to the top?
Like it never never stop?
Can you bring it to the top?
One [hop], [right] foot now
[Left] foot now y'all
Cha cha real smooth

Turn it down, to the [left]
Take it [back] now y'all
One [hop] this time, one [hop] this time
Reverse, reverse
Slide to the [left], slide to the [right]
Reverse reverse, reverse reverse
Cha cha now y'all
Cha cha again
Cha cha now y'all
Cha cha again
Turn it down

To the [left], take it [back] now y'all
[Two] [hops] two hops, two hops two hops    EDIT: Made a mistake here, but bit to late to change it now..

## Challenge:

Now onto the challenge itself. We take one, two, or three inputs . One of them is a list of index-integers (so either non-negative for 0-indexed; or positive for 1-indexed). (The other inputs are optional and explained in the challenge rules.)

Every test case will start at a position {x=0, y=0}.
Now use the lyrics-list of moves and remove all moves at the given indices of the input-list. Then 'walk' over the moves (up to the largest index of the input-array) and output the position you'll end up at.

The moves will change the coordinates as follows:
- R: x+1
- L: x-1
- H: y+1
- B: y-1

## Challenge rules:

• The moves-list can be accessed any way you'd like. †: Can be an additional input; can be in a separated file on disk you'll read from; can be in a class-level variable you access. It will have to be in the form of L, R, B and H though (can be a string or character-list/array), so you cannot save the moves-list as 1s and -1s or integers.
• The moves-list given above is hard-coded and will always be the same. (Which is also why it's fine to put it as class-level field instead of taking it as an input if this helps the byte-count of your answer.)
• Input-list can be both 0-indexed or 1-indexed (up to you)
• We only 'walk' the moves up to and excluding the largest index of the list.
• †: You are also allowed to take this last item as separated integer input, instead of the last item of the input-array.
• Output of the x and y coordinates we end up at can be in any reasonable format (integer-array containing two items, delimited string, printed to STDOUT on two separated lines, etc.)
• You can assume the input-list is sorted from lowest to highest (or highest to lowest if that's what you prefer, in which case the first item is the initial size of the moves-list - if not taken as separated input). And it also won't contain any duplicated indices.
• If the largest index of the input-list is larger than the list of moves above (55 moves are in the moves-list above), we wrap around to the beginning of the list again (as many times as necessary depending on the largest index of the input).
• You are allowed to output y,x instead of x,y, but please specify this in your answer if you do.

## Example:

Input: [0,4,8,10,13,14,27,34,42,43,44,50,53,56,59,60,64]

Here the moves and (0-indexed) indices above one-another:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64
L, B, H, R, L, L, B, H, R, L, B, H, H, R, R, L, L, L, R, L, B, H, H, H, H, R, R, L, L, L, B, H, H, H, H, H, R, L, R, L, R, L, H, R, L, L, B, H, H, L, R, L, B, H, H, L, B, H, R, L, L, B, H, R, L


Removing the indices of the input-list, we'll have the following moves-list remaining:

1, 2, 3, 5, 6, 7, 9,11,12,15,16,17,18,19,20,21,22,23,24,25,26,28,29,30,31,32,33,35,36,37,38,39,40,41,45,46,47,48,49,51,52,54,55,57,58,61,62,63
B, H, R, L, B, H, L, H, H, L, L, L, R, L, B, H, H, H, H, R, R, L, L, B, H, H, H, H, R, L, R, L, R, L, L, B, H, H, L, L, B, H, L, H, R, B, H, R


Now if we walk from position {0, 0} over the remaining moves, we'll have the following new coordinates after every move:

{0,0};B,{0,-1};H,{0,0};R,{1,0};L,{0,0};B,{0,-1};H,{0,0};L,{-1,0};H,{-1,1};H,{-1,2};L,{-2,2};L,{-3,2};L,{-4,2};R,{-3,2};L,{-4,2};B,{-4,1};H,{-4,2};H,{-4,3};H,{-4,3};H,{-4,5};R,{-3,5};R,{-2,5};L,{-3,5};L,{-4,5};B,{-4,4};H,{-4,5};H,{-4,6};H,{-4,7};H,{-4,8};R,{-3,8};L,{-4,8};R,{-3,8};L,{-4,8};R,{-3,8};L,{-4,8};L,{-5,8};B,{-5,7};H,{-5,8};H,{-5,9};L,{-6,9};L,{-7,9};B,{-7,8};H,{-7,9};L,{-8,9};H,{-8,10};R,{-7,10};B,{-7,9};H,{-7,10};R,{-6,10}


So the final output will be: {-6, 10}

## General rules:

• This is , so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
• Default Loopholes are forbidden.

## Test cases:

0-indexed input: [0,4,8,10,13,14,27,34,42,43,44,50,53,56,59,60,64]
1-indexed input: [1,5,9,11,14,15,28,35,43,44,45,51,54,57,60,61,65]
Output: {-6, 10}

0-indexed input: [55]    (Note: There are 55 moves in the unmodified list)
1-indexed input: [56]    (Note: There are 55 moves in the unmodified list)
Output: {-6, 11}

0-indexed input: [0,1,4,5,6,9,10,15,16,17,19,20,27,29,30,37,38,39,41,44,45,46,49,51,52]
1-indexed input: [1,2,5,6,7,10,11,16,17,18,20,21,28,30,31,38,39,40,42,45,46,47,50,52,53]
Output: {10, 16}

0-indexed input: [2,3,7,8,11,12,13,14,18,21,22,23,24,25,26,31,32,33,34,35,36,38,40,42,43,47,48,50,53]
1-indexed input: [3,4,8,9,12,13,14,15,19,22,23,24,25,26,27,32,33,34,35,36,37,39,41,43,44,48,49,51,54]
Output: {-18, -7}

0-indexed input: [0]
1-indexed input: [1]
Output: {0, 0}

0-indexed input: [4,6,7,11,12,13,15,17,20,28,31,36,40,51,59,66,73,74,80,89,92,112,113,114,116,120,122,125,129,134,136,140,145,156,161,162,165,169,171,175,176,178,187,191,200]
1-indexed input: [5,7,8,12,13,14,16,18,21,29,32,37,41,52,60,67,74,75,81,90,93,113,114,115,117,121,123,126,130,135,137,141,146,157,162,163,166,170,172,176,177,179,188,192,201]
Output: {-17, 37}

0-indexed input: [25,50,75,100,125,150,175,200,225,250]
1-indexed input: [26,51,76,101,126,151,176,201,226,251]
Output: {-28, 49}

• Can we output the coordinates in reverse order? – Shaggy Jun 19 '18 at 13:56
• @Shaggy Umm, sure, why not. As long as you clearly specify it in your answer. – Kevin Cruijssen Jun 19 '18 at 14:04
• @Arnauld Yes, the moves are those displayed and will never change. I will perhaps clarify this more clearly if it wasn't clear yet. (Which is also why you can have it as a hardcoded class-level field if it would benefit your byte-count.) – Kevin Cruijssen Jun 19 '18 at 16:47
• Can the output be a pair of floats? – Jakob Jun 20 '18 at 19:53
• Very late to the challenge, but two of your test cases seem to have wrong input for the 1-indexed case: an extra 82 in the sixth one, and 29 instead of 39 in the third testcase (the sorting indicates you might have intended that to actually be 28/29, but the expected output shown is from using 38/39 there). – sundar - Reinstate Monica Jul 15 '18 at 16:21

# 05AB1E, 15 12 bytes

Saved 3 bytes thanks to Erik the Outgolfer

ÝsKèIêRS¢2ôÆ


Try it online! or as a Test suite

Explanation

Ý                 # push range [0 ... input_int]
sK               # remove all elements in input_list from this range
è              # cyclically index into the moves-list with the remaining elements
Iê            # push the unique chars of the move-list, sorted
R           # reverse
S¢         # count the occurrences of each char in "RLHB"
2ô       # split into 2 parts
Æ      # reduce each part by subtraction

• Nice answer! Didn't even knew about Æ. Smart way to just count all moves and use Æ to calculate the difference for the RL and BH pairs. – Kevin Cruijssen Jun 19 '18 at 9:50
• Æ has existed forever, hasn't it? I'd assume so, seeing as I didn't know about it. Seems like the commands I think are "new" have existed since inception, but I never knew how to use them lol. Oh, +1 – Magic Octopus Urn Jun 19 '18 at 23:52
• @MagicOctopusUrn: It has indeed existed forever ;) – Emigna Jun 20 '18 at 6:05

# Ruby, 98 ... 58 55 bytes

->a{([*0..a[-1]]-a).sum{|c|-1i**(m[c%55].ord%19)}.rect}


Try it online!

### Explanation:

The main trick is using complex numbers to represent moves: 'B' is -i, 'H' is +i, 'L' is -1 and 'R' is +1. If we convert all the moves into complex numbers, then with a single sum we get the right result.

I tried different ways, but then I found the magic number 19: we don't need to fiddle with regex matching because:

B  is ASCII 66; 66%19=9  and i^9  = i
H  is ASCII 72; 72%19=15 and i^15 =-i
L  is ASCII 76; 72%19=0  and i^0  = 1
R  is ASCII 82; 82%19=6  and i^6  =-1


So, put that all together, sum, invert the sign, and we're done.

Thanks Jakob for -3 bytes

• Clever use of complex numbers! Since the move string is fixed, you can replace (m*c+m)[c] with m[c%55]. – Jakob Jun 21 '18 at 16:00

# JavaScript (ES6), 85 bytes

As per the challenge rules, this code expects the global-scope string m to hold the list of moves. (Saving 3 bytes, as suggested by @KevinCruijssen.)

Takes input as a list of 0-based indices, ordered from lowest to highest.

a=>a.map(g=i=>j++<i&&g(i,p=m.search(m[~-j%55])*3%5,x+=--p%2,y-=--p%2),j=x=y=0)&&[x,y]


Try it online!

### How?

Each move character is converted to its position in the move string "LBHR...". We multiply the result by 3 and apply a modulo 5, which gives p. We then have:

• dx = ((p-1) mod 2)
• dy = -((p-2) mod 2)

Where the sign of a mod b is that of a.

 character | position | * 3 | mod 5 | dx | dy
-----------+----------+-----+-------+----+----
'L'    |     0    |  0  |   0   | -1 |  0
'B'    |     1    |  3  |   3   |  0 | -1
'H'    |     2    |  6  |   1   |  0 | +1
'R'    |     3    |  9  |   4   | +1 |  0


# Jelly, 14 bytes

Rḟị⁵ċⱮ⁵QṢṚ¤_2/


Try it online!

Argument 1/Left argument: Maximum 1-based index.
Argument 2/Right argument: 1-based indices.
Argument 3: Moves-list as a string. Function is still reusable if the third command-line argument is used for this purpose.

# Java 10, 129119112107100 86 bytes

a->m->{var r=new int[2];for(;m-->0;)r[s[m%55]/73]-=a.add(m)?s[m%55]*3%5-2:0;return r;}


Takes the maximum as additional input; moves-list is a character-array on class-level.

-7 bytes thanks to @Jakob.
-14 bytes thanks to @Geobits.

Try it online.

Explanation:

a->m->{              // Method with Integer-Set & int parameters and int-array return
var c=new int[2];  //  [x,y] result-array, starting at {0,0}
for(;m-->0;)       //  Use the m input as index, and loop in the range (m, 0]
r[s[m%55]/73]-=  //   Subtract from either x or y based on the character:
a.add(m)?       //    If the input-set doesn't contain the current index m:
s[m%55]*3%5-2  //     Modify the x or y coordinate based on the character
:               //    Else:
0;             //     Leave the x or y coordinate unchanged
return r;}         //  Return count(R)-count(L) and count(H)-count(B) as result


s[m%55]/73 maps to either the x or y coordinate depending on the character (Try it online):

Letter    Unicode value    /73

B         66               0
H         72               0
L         76               1
R         82               1


s[m%55]*3%5-2 maps to the correct +1 or -1 depending the character (Try it online):

Letter    Unicode value    *3     %5    -2

B         66               198    3     1
H         72               216    1     -1
L         76               228    3     1
R         82               246    1     -1

• If you take the index list as a mutable set you can use a.add(m) as the if condition. – Jakob Jun 19 '18 at 20:06
• And int c[] can be int[]c. – Jakob Jun 19 '18 at 20:23
• @Jakob Ah, int c[] was from a previous version where I still used an index i instead of using m. And smart of using a Set's add instead of !contains, thanks! – Kevin Cruijssen Jun 19 '18 at 21:36
• You can avoid the byte-hogging subtraction at the end by using c[2] for axis (with s[m%55]/73) and walking it with something like 3*s[m%55]%5-2 (I wish I could see a way to shorten that, but...). Along with a ternary, it's a->m->{var c=new int[2];for(;m-->0;)c[s[m%55]/73]-=a.add(m)?3*s[m%55]%5-2:0;return c[1]+","+c[0];} for 98. – Geobits Jun 20 '18 at 12:53
• @Geobits Thanks! And -12 bytes more by just returning the int[] instead of a String. :) – Kevin Cruijssen Jun 20 '18 at 13:38

# Python 3, 85 bytes

b is the index list (a set) and l is the end index. The move list (a string or character list) appears free as s. This is a port of G B's Ruby answer, and an explanation of the approach can be found there.

def f(b,l):r=sum(-1j**(ord(s[i%55])%19)for i in set(range(l))-b);print(r.real,r.imag)


Try It Online

## Ungolfed

def f(b, l):
r = sum(
-1j ** (ord(s[i % 55]) % 19)
for i in set(range(l)) - b
);
print(r.real, r.imag)


# MATL, 16 bytes

:wX-)Jw19\^s_&Zj


Try it online!

Takes 3 inputs like the Jelly answer, the largest index, the list of indices to skip, and the 55 character array.

# Clean, 148 ... 130 bytes

import StdEnv
$i=foldr(\a(x,y)|any((==)a)i=(x,y)=case m.[a rem 55]of'H'=(x,y+1);'B'=(x,y-1);'L'=(x-1,y);_=(x+1,y))(0,0)[0..last i]  Try it online! Defines the function $ :: [Int] -> (Int, Int), taking a list of (sorted from smallest to largest) indices to be removed from the moves before foldr-ing the applicable operations over (0,0).