# Wherre are the adjacent characters in the title? [3, 4]!

Title misspelled on purpose. Read more to find out why.

Your task: given a delimited string or list including the characters A,B,C,D, output the indexes of all the adjacent equal characters. Output can be multiple strings/integers on multiple lines, a list/array, or a delimited string.

All output should be in a list or string, or multiple printed lines. Each printed line, if there are multiple, should only contain 1 string or number. Trailing whatevers are okay.

Standard methods of input/output. Standard loopholes apply.

For example, the input 'ABCDDCBA' should output 3,4 or 4,5, depending on whether it is 0- to 1- indexed, because those numbers are the indexes of D and the D next to it.

Test cases:

Test cases have input given as a single string, and output as a ,-delimited string. Outputs are 0-indexed, add 1 to every outputted item to get it to be 1-indexed.

Input: 'ABCDCABCD'
Output: ''

Input: 'AABBCCDD'
Output: '0,1,2,3,4,5,6,7'

Input: 'ABCDDDCBA'
Output: '3,4,5'

Input: 'ABBCDD'
Output: '1,2,4,5'


This is , so shortest code wins!

• Can we have a trailing delimiter in the output? Apr 11, 2017 at 15:37
• @BasicSunset Sure Apr 11, 2017 at 15:38
• @JonathanAllan That is okay because it outputs only one list. Apr 11, 2017 at 17:25
• Can indices of consecutive characters appear multiple times? E.g. for the third test case, is 3,4,4,5 valid as well?
– Luke
Apr 11, 2017 at 18:18
• Can you add a test case that doesn't have symmetrical matches? E.g. AABBCD -> 1,2,3,4 Apr 11, 2017 at 18:25

# Retina, 3329 23 bytes

Saved 6 bytes thanks to Martin Ender

TL:(.)\1+
:
$.¶ TL  Outputs a linefeed-separated list of indices. Try it online! Explanation TL:(.)\1+  Transliterate runs of the same character into colons, to mark positions where there are duplicate characters. :$.¶


Then replace each colon with the length of the text before it, followed by a linefeed.

TL


Finally, delete any remaining letters.

# Jelly, 7 bytes

JṁŒgḊÐf


1-based; returns a list of lists of the runs of indexes as allowed by the OP.

Try it online!

### How?

JṁŒgḊÐf - Main link: char-list s       e.g. 'DCCABBBACCCD' (which is a python interpreted input of ['D','C','C','A','B','B','B','A','C','C','C','D'])
J       - range(length(s))                  [1,2,3,4,5,6,7,8,9,10,11,12]
Œg    - group-runs(s)                     [['D'],['C','C'],['A'],['B','B','B'],['A'],['C','C','C'],['D']]
ṁ      - mould left like right             [[1],[2,3],[4],[5,6,7],[8],[9,10,11],[12]]
Ðf - filter keep items that would be truthy (empty is not truthy) after applying:
Ḋ   -     dequeue (x[1:])               [    [2,3],    [5,6,7],    [9,10,11]     ]

• ṁ - Things I wish 05AB1E could do for 500, please. Apr 11, 2017 at 17:58
• I feel more and more like this language is kind-of like cheating here. :D Apr 11, 2017 at 22:25
• @ComradeSparklePony why the undo of the accept check? Jun 2, 2017 at 17:54

# Brain-Flak, 57 46 bytes

{({}[({})]<(([]<>)[()])>){(<{}{}{}>)}{}<>}<>


Includes +2 for -ar

Uses 0-based indexing.

Try it online!

# While true
{

# Subtract the second value on the stack from the first
({}[({})]

# Push the height of this stack (the main stack) on the other stack
<(([]<>)

# Push the height of the main stack - 1
[()])>

# Push the difference that we calculated a second ago
)

# If they weren't the same character
{

# Pop the difference and the two stack heights
(<{}{}{}>)

# End if
}

# Pop the difference (or the 0 to get out of the if)
{}

# Switch back to the main stack and end while
<>}

# Switch to the stack with the indexes and implicitly print
<>


# MATL, 8 7 bytes

d~ftQvu


Output is 1-based.

Try it online!

### Explanation with example

Consider input 'ABCDDDCBA'.

d     % Implicitly input a string. Consecutive differences
% STACK: [1  1  1  0  0 -1 -1 -1]
~     % Negate. Each character that equals the next gives true
% STACK: [0 0 0 1 1 0 0 0]
f     % Find: (1-based) indices of true elements
% STACK: [4 5]
tQ    % Duplicate, add 1 element-wise
% STACK: [4 5], [5 6]
v     % Concatenate vertically
% STACK: [4 5; 5 6]
u     % Unique (remove duplicates). This doesn't automatically sort, but the
% output will be sorted because the input, read in column-major order, is
% Implicitly display
% STACK: [4; 5; 6]


## Mathematica, 32 bytes

Union@@StringPosition[#,x_~~x_]&


Pure function which returns the 1-indexed positions of characters adjacent to an identical character.

## Explanation:

StringPosition["string","sub"] gives a list of the starting and ending character positions at which "sub" appears as a substring of "string". x_~~x_ is a StringExpression which matches two adjacent, identical characters. For example, StringPosition["ABCDDDCBA",x_~~x_] gives {{4, 5}, {5, 6}}. Applying Union joins the lists, sorts, and deletes duplicates.

# Brain-Flak, 69, 59, 56 bytes

{({}[({})]<(())>){((<{}{}>))}{}{([{}]([]<>))(<>)}{}}<>


Try it online!

+2 bytes for the -ar flags which enables ASCII input and reverses the stack.

Uses 0-based indexing. Saved 10 bytes by reducing my push-pop redundancy. Saved another 4 bytes by switching from 1 to 0-based indexing.

This is pretty much the only string based challenge that brain-flak is good at. That's because brain-flak is great at comparing consecutive characters, even though it's horrendous at string processing in general. Here is readable version of the code with comments to explain how it works:

#While True
{

#Determine if top two are equal
({}[({})]<(())>){((<{}{}>))}{}

#If so
{

#Pop the one, and negate it's value (giving us -1)
([{}]

#Push stack height over
([]<>)

#Then push stack height plus the negated pop (-1)
)

#Push a zero back onto the main stack
(<>)

#Endwhile
}

#Pop the zero
{}

#Endwhile
}

#Toggle back, implicitly display
<>

• A little friendly competition :) Apr 11, 2017 at 18:36
• @riley fixed! (And still one byte shorter :P) Apr 11, 2017 at 18:39
• I always forget about -r. That brings me down to 46. Apr 11, 2017 at 18:40

# Brachylog, 19 bytes

l⟦k:?z{sĊtᵐ=∧Ċ∋h}ᶠd


Try it online!

### Explanation

Brachylog is usually terrible with indexes, which again shows here.

If false. is an acceptable output in cases where there are no adjacent characters, then this would be 1 byte less by replacing ᶠd by ᵘ.

l⟦k                      The list [0, …, length(Input) - 1]
:?z                   Zip the Input with this list
{         }ᶠd      Find with no duplicates:
∧Ċ∋h           The heads of each element of Ċ = [A, B] (i.e. the indexes)…
Ċtᵐ=               …where the tails of both A and B are equal (i.e. the letters)…
sĊ                  …and where Ċ = [A, B] is a substring of the Input


# Octave, 35 bytes

@(s)unique([x=find(~diff(+s)),x+1])


Try it online!

Similar to my MATL answer. Here unique automatically sorts . The input to diff must be converted to double, which is done by the unary +.

# Cubix, 37 32 31 29 28 bytes

Thanks to ETHProductions for pointing me in the direction of a three-byte saving

$uO@(;Usoi?-!w>;.....S_o\;#O  Try it here! Note that the output indices are 1-based and not in ascending order. ### Expanded: $ u O
@ ) ;
U s o
i ? - ! w > ; . . . . .
S _ o \ ; # O . . . . .
. . . . . . . . . . . .
. . .
. . .
. . .


# Explanation

This works by reading the input character by character. To compare two characters, we simply subtract the their character codes, and if the result is 0, we print the current length of the stack, a space, the current length of the stack - 1 and another space. Then we clean up the stack a bit, and we start with the read loop again. If the end of the input string is reached, the program stops.

• Hmm, if you can keep the stack fairly clean, you may be able to use # to get the length of the stack when you need it. (Also, LOL'ed at the ;_; in the code ;) ) Apr 15, 2017 at 14:52
• A basic example (probably not fully golfed); ethproductions.github.io/cubix/… (Note: it's 1-indexed, not 0-indexed) Apr 15, 2017 at 15:04
• Thanks for the reminder. I golfed one byte of your version and added that. I might be able to get anoter byte or two off...
– Luke
Apr 15, 2017 at 20:54
• Idea: what if you did !$w instead of !w and moved part of the fifth row logic to the fourth row? (Can't try right now because I'm heading out the door) Apr 15, 2017 at 21:22 • I also thought of that, but I don't think it will save many bytes. I'll try it though. – Luke Apr 16, 2017 at 6:54 # C, 75 bytes i;f(char*s){for(i=0;*s;++s,++i)if(s[1]==*s|(i&&s[-1]==*s))printf("%d ",i);}  Uses spaces as delimiters. (A trailing comma doesn't look too good.) Try it online! ## C#, 115 bytes Golfed i=>{var o="";for(int x=1,l=i.Length;x<=l;x++)o+=(x<l&&i[x]==i[x-1])||(x>1&&i[x-1]==i[x-2])?(x-1)+" ":"";return o;};  Ungolfed i => { var o = ""; for( int x = 1, l = i.Length; x <= l; x++ ) o += ( x < l && i[ x ] == i[ x - 1 ] ) || ( x > 1 && i[ x - 1 ] == i[ x - 2 ] ) ? ( x - 1 ) + " " : ""; return o; };  Ungolfed readable i => { // List of positions var o = ""; // Cycle through the string for( int x = 1, l = i.Length; x <= l; x++ ) // Check if 'x' is below the string length // and if the current and previous char are the same... // ... or if 'x' is beyong the string length // and the 2 previous chars are the same. o += ( x < l && i[ x ] == i[ x - 1 ] ) || ( x > 1 && i[ x - 1 ] == i[ x - 2 ] ) // If true, add the index to the list of positions... ? ( x - 1 ) + " " // ...otherwise add nothing : ""; // Return the list of positions. return o; };  Full code using System; using System.Collections.Generic; namespace Namespace { class Program { static void Main( String[] args ) { Func<String, String> f = i => { // List of positions var o = ""; // Cycle through the string for( int x = 1, l = i.Length; x <= l; x++ ) // Check if 'x' is below the string length // and if the current and previous char are the same... // ... or if 'x' is beyong the string length // and the 2 previous chars are the same. o += ( x < l && i[ x ] == i[ x - 1 ] ) || ( x > 1 && i[ x - 1 ] == i[ x - 2 ] ) // If true, add the index to the list of positions... ? ( x - 1 ) + " " // ...otherwise add nothing : ""; // Return the list of positions. return o; }; List<String> testCases = new List<String>() { "ABCDCABCD", "AABBCCDD", "ABCDDDCBA", "", "A", "AA", "AAA", }; foreach( String testCase in testCases ) { Console.WriteLine($"{testCase}\n{f( testCase )}\n" );
}

}
}
}


Releases

• v1.0 - 115 bytes - Initial solution.

Notes

# Jelly, 8 bytes

=2\T’œ|$ Try it online! • Hmm, exactly the same algorithm I tried, though mine was slightly longer: Ṗ=ḊTµ2Ḷ+€ Apr 15, 2017 at 15:20 # k, 18 bytes {?,/-1 0+/:&:=':x}  Examples: k){?,/-1 0+/:&:=':x}"AABCDDDCBAA" 0 1 4 5 6 9 10 k){?,/-1 0+/:&:=':x}"ABCDCBA" ()  Translation to q is easier to understand: {distinct raze -1 0+/:where not differ x}  • This was my initial solution too! :D Apr 13, 2017 at 12:41 # JavaScript, 52 bytes Thanks @Neil for golfing off 1 byte x=>x.map((a,i)=>a==x[++i-2]|a==x[i]&&i).filter(a=>a)  Receives input as a 0-indexed array of characters Returns output as a 1-indexed array ## Explanation x.map()  For each character in the string (a,i)=>(a==x[++i-2]|a==x[i])*i  If it is equal to the previous character or the next character, return the index+1 otherwise do not return (leaves undefined in the array) .filter(a=>a)  Remove all undefined elements from the resulting array Try it online! • Would &&i save a byte over (...)*i? – Neil Apr 11, 2017 at 21:13 • @Neil && is faster than |, which would result in it always returning i Apr 11, 2017 at 21:15 • 0|0&&6 is 0, 1|0&&6 is 6, 0|1&&6 is 6, 1|1&&6 is 6. Isn't that what you want? – Neil Apr 11, 2017 at 21:23 • I think I was thinking I still had || instead of | Apr 11, 2017 at 21:36 • Ah yes, that would explain it. – Neil Apr 11, 2017 at 21:38 # Python 2, 55 54 bytes m=j=0 for i in input(): if m==i:print~-j,j, j+=1;m=i  Try it Online! Outputs indices separated by spaces (note that this displays some indices twice as allowed by OP) # Perl 5, 37 bytes 35 bytes of code + pl flags. s/(?<=(.))\1|(.)(?=\2)/print pos/ge  Try it online! (?<=(.))\1|(.)(?=\2) will match either between two repeted characters ((?<=(.))\1), or before a character that is repeated ((.)(?=\2)). Then, print pos prints the position of the match. (pos contains the index of the current match when used in a regex with /g modifier). # Perl 6, 66 57 bytes *.comb.rotor(2=>-1).kv.flatmap({($^a,$a+1)xx[eq]$^b[0,1]}).squish


Try it

{m:ex/[(.)<($0|(.))>$0]{make $/.from}/».ast.sort.squish}  Try it # PHP, 100 Bytes for(;$i<strlen($s=$argn);$i++)$s[$i]==$s[$i+1]||$s[$i]==$s[$i-1]&&$i?$r[$i]=+$i:0;echo join(",",$r);


# Ruby, 51+1 = 52 bytes

Uses the -n flag.

i=0;d=[];gsub(/./){$&==$_[i+=1]?d+=[i-1,i]:0};p d&d


Try it online!

## Batch, 139 bytes

@set/ps=
@set/ai=c=0
:l
@if %s:~,1%==%s:~1,1% set c=2
@if %c% gtr 0 echo %i%
@set/ai+=1,c-=1
@if not "%s:~1%"=="" set s=%s:~1%&goto l


Takes input on STDIN. Works by keeping track of how many numbers to print in the c variable, which is reset to 2 when a pair is detected. Note: At a cost of 6 bytes, could be hardened to work with most ASCII characters and not just ABCD.

# C#, 89 Bytes

using System.Linq;s=>string.Join("",s.Skip(1).Select((a,i)=>a==s[i]?i+" "+(i+1)+" ":""));


If there are three or more characters in a row the indexes are repeated. Which @Comrade SparklePony allowed in the comments.

### Ungolfed full program:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Namespace
{
class Class1
{
static void Main(string[] args)
{
Func<string, string> f2 =
s => string.Join("" ,         //Combine the results into one string
.Select(
(a, i) =>                 // 'a' is the current element, 'i' is the index of the element in the result of 'Skip'
a == s[i] ?               // therefore 's[i]' is the previous element; compare it with the current one
i + " " + (i + 1) + " " : //If true, return the indexes
""                        //Otherwise an empty string
));

var tests = new string [] {
"ABCDCABCD",
"AABBCCDD",
"ABCDDDCBA",
"ABBCDD"
};

foreach (var test in tests)
{
Console.WriteLine(test);
Console.WriteLine(string.Join("", f2(test)));
Console.WriteLine();
}

}
}
}


## QBIC, 42 bytes

;[2,_lA||~mid$(A,a-1,1)=mid$(A,a,1)|?a-1,a


Sample output:

Command line: AADCDBBD
1             2
6             7


Explanation:

;               Get A$from the cmd line [2, | FOR a% = 2 TO _lA| the length of A$
~mid$(A,a-1,1) IF the character at index a% =mid$(A,a,1)    equals the char at index a%-1
|               THEN
?a-1,a          PRINT both indexes, tab-separated
Any further doubles are printed on a separate line
The IF and FOR are closed implicitly


EDIT: QBIC now has Substring! This challenge can now be solved in 32 bytes:

;[2,_lA||~_sA,a-1|=_sA,a||?a-1,a


Where:

_s      This is the substring function; it takes 1, 2 or 3 arguments.
Arguments are comma-seperated, the list is delimited with |
In this answer we see Substring take 2 arguments:
A,    The string to take from
a|  Starting position (note:uppercase represents strings, lowercase is for nums)
Any omitted argument (in this case 'length to take') is set to 1.


# k, 14 bytes

This is a function, it takes in a string, and returns a list of indices.

&{x|1_x,0}@=':


Explanation:

           =': /compare each letter to the previous, return binary list
{       }@
1_x,0      /shift left
x|           /combine shifted and unshifted with binary or
&              /get indices of 1s


Try it online!

How to use:

&{x|1_x,0}@=':"STRINGGOESHERE"


# PHP, 70 bytes

for(;a&$c=$argn[$i];)$i++&&$argn[$i-2]==$c||$argn[$i]==$c?print\$i._:0;


takes input from STDIN; run with -R.