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

21

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!

Comrade SparklePony

Posted 2017-04-11T15:20:00.807

Reputation: 5 784

Can we have a trailing delimiter in the output? – Business Cat – 2017-04-11T15:37:02.893

@BasicSunset Sure – Comrade SparklePony – 2017-04-11T15:38:18.697

Must output indices be in order? – Luis Mendo – 2017-04-11T15:39:41.930

@LuisMendo No, they do not. – Comrade SparklePony – 2017-04-11T15:49:07.473

"If you chose to output multiple strings/integers, each must only have one number in them" - so, specifically, is an output of a list of lists separating the runs not acceptable (for example [[0,1],[2,3],[4,5],[6,7]] for your example 2), or is that OK since there is a single containing list? – Jonathan Allan – 2017-04-11T17:23:48.840

1@JonathanAllan That is okay because it outputs only one list. – Comrade SparklePony – 2017-04-11T17:25:11.793

2Can indices of consecutive characters appear multiple times? E.g. for the third test case, is 3,4,4,5 valid as well? – Luke – 2017-04-11T18:18:30.877

@Luke Yes, that is okay. – Comrade SparklePony – 2017-04-11T18:19:48.067

1Can you add a test case that doesn't have symmetrical matches? E.g. AABBCD -> 1,2,3,4 – Riley – 2017-04-11T18:25:44.313

@fəˈnɛtɪk Sorry, but this is not allowed. – Comrade SparklePony – 2017-04-11T20:04:35.967

Can it output as a list – fəˈnɛtɪk – 2017-04-11T20:06:08.213

@fəˈnɛtɪk "Output can be multiple strings/integers on multiple lines, a list/array, or a delimited string." Yes, it can output as a list. – Comrade SparklePony – 2017-04-11T20:09:39.213

Is it OK for the resulting list to contain empty elements? – raznagul – 2017-04-12T12:12:08.097

@raznagul Sorry, but that is not okay. – Comrade SparklePony – 2017-04-12T12:27:31.567

Answers

5

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]

Luis Mendo

Posted 2017-04-11T15:20:00.807

Reputation: 87 464

8

Retina, 33 29 23 bytes

Saved 6 bytes thanks to Martin Ender

T`L`:`(.)\1+
:
$.`¶
T`L

Outputs a linefeed-separated list of indices.

Try it online!

Explanation

T`L`:`(.)\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.

T`L

Finally, delete any remaining letters.

Business Cat

Posted 2017-04-11T15:20:00.807

Reputation: 8 927

7

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]     ]        

Jonathan Allan

Posted 2017-04-11T15:20:00.807

Reputation: 67 804

2 - Things I wish 05AB1E could do for 500, please. – Magic Octopus Urn – 2017-04-11T17:58:43.713

1I feel more and more like this language is kind-of like cheating here. :D – Avamander – 2017-04-11T22:25:53.070

@ComradeSparklePony why the undo of the accept check? – Jonathan Allan – 2017-06-02T17:54:47.813

7

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
<>

Riley

Posted 2017-04-11T15:20:00.807

Reputation: 11 345

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.

ngenisis

Posted 2017-04-11T15:20:00.807

Reputation: 4 600

5

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
<>

James

Posted 2017-04-11T15:20:00.807

Reputation: 54 537

A little friendly competition :) – Riley – 2017-04-11T18:36:15.350

@riley fixed! (And still one byte shorter :P) – James – 2017-04-11T18:39:54.773

I always forget about -r. That brings me down to 46. – Riley – 2017-04-11T18:40:54.887

5

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

Fatalize

Posted 2017-04-11T15:20:00.807

Reputation: 32 976

4

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 +.

Luis Mendo

Posted 2017-04-11T15:20:00.807

Reputation: 87 464

4

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.

Luke

Posted 2017-04-11T15:20:00.807

Reputation: 4 675

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 ;) ) – ETHproductions – 2017-04-15T14:52:00.630

A basic example (probably not fully golfed); https://ethproductions.github.io/cubix/?code=Li53QC47Li5vaT8tIXU7Li4uLi4uT18oIztcTylzb1M=&input=QUJDREREQ0JB&speed=20 (Note: it's 1-indexed, not 0-indexed)

– ETHproductions – 2017-04-15T15:04:30.417

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 – 2017-04-15T20:54:00.120

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) – ETHproductions – 2017-04-15T21:22:43.290

I also thought of that, but I don't think it will save many bytes. I'll try it though. – Luke – 2017-04-16T06:54:19.520

3

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!

Steadybox

Posted 2017-04-11T15:20:00.807

Reputation: 15 798

3

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" );
         }

         Console.ReadLine();
      }
   }
}

Releases

  • v1.0 - 115 bytes - Initial solution.

Notes

Nothing to add

auhmaan

Posted 2017-04-11T15:20:00.807

Reputation: 906

2

Jelly, 8 bytes

=2\T’œ|$

Try it online!

Dennis

Posted 2017-04-11T15:20:00.807

Reputation: 196 637

Hmm, exactly the same algorithm I tried, though mine was slightly longer: Ṗ=ḊTµ2Ḷ+€ – ETHproductions – 2017-04-15T15:20:21.923

2

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}

skeevey

Posted 2017-04-11T15:20:00.807

Reputation: 4 139

This was my initial solution too! :D – zgrep – 2017-04-13T12:41:43.527

2

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!

fəˈnɛtɪk

Posted 2017-04-11T15:20:00.807

Reputation: 4 166

Would &&i save a byte over (...)*i? – Neil – 2017-04-11T21:13:47.510

@Neil && is faster than |, which would result in it always returning i – fəˈnɛtɪk – 2017-04-11T21:15:34.177

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 – 2017-04-11T21:23:16.370

I think I was thinking I still had || instead of | – fəˈnɛtɪk – 2017-04-11T21:36:11.293

Ah yes, that would explain it. – Neil – 2017-04-11T21:38:36.243

2

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)

math junkie

Posted 2017-04-11T15:20:00.807

Reputation: 2 490

1

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).

Dada

Posted 2017-04-11T15:20:00.807

Reputation: 8 279

1

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);

Jörg Hülsermann

Posted 2017-04-11T15:20:00.807

Reputation: 13 026

1

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

Brad Gilbert b2gills

Posted 2017-04-11T15:20:00.807

Reputation: 12 713

1

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!

Value Ink

Posted 2017-04-11T15:20:00.807

Reputation: 10 608

1

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.

steenbergh

Posted 2017-04-11T15:20:00.807

Reputation: 7 772

1

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.

Neil

Posted 2017-04-11T15:20:00.807

Reputation: 95 035

1

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
                s.Skip(1)                     //Start with the second element
                .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();
            }

            Console.ReadLine();
        }
    }
}

raznagul

Posted 2017-04-11T15:20:00.807

Reputation: 424

0

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"

zgrep

Posted 2017-04-11T15:20:00.807

Reputation: 1 291

0

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.

Titus

Posted 2017-04-11T15:20:00.807

Reputation: 13 814