42
\$\begingroup\$

Given a rectangular haystack of size at least 2x2 composed of all the same printable ASCII characters, output the location (counting from the top-left) of the needle which is a different character.

For example, if the following haystack is input:

#####
###N#
#####
#####

The output should be 3,1 when zero-indexed (what I'll be using in this challenge) or 4,2 when one-indexed.

The haystack can be composed of any printable ASCII character:

^^^
^^^
^N^
^^^
^^^
^^^

output: 1,2

and the needle will be any other printable ASCII character:

jjjjjj
j@jjjj
jjjjjj

output 1,1

It's also possible to have a needle in the corner:

Z8
88

output 0,0

88
8Z

output 1,1

or to have the needle at the edge:

>>>>>>>>>>
>>>>>>>>>:
>>>>>>>>>>

output 9,1

Rules and Clarifications

  • Input and output can be given by any convenient method. This means you can take input as a list of list of characters, as a single string, etc.
  • You can print the result to STDOUT or return it as a function result. Please state in your submission what order the output is in (i.e., horizontal then vertical, as used in the challenge, or vice versa).
  • Either a full program or a function are acceptable.
  • You do not get to pick which characters to use. That's the challenge.
  • The haystack is guaranteed to be at least 2x2 in size, so it's unambiguous which is the needle and which is the hay.
  • There is only ever one needle in the input, and it's only ever one character in size.
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.
\$\endgroup\$
16
  • \$\begingroup\$ Suggested test case: 88\n8Z (with any two characters of course). \$\endgroup\$ Feb 1, 2019 at 14:24
  • \$\begingroup\$ Can we take input as a multi-dimensional array? i.e. [ ['#','#','#','#','#'], ['#','#','#','N','#'], ['#','#','#','#','#'], ['#','#','#','#','#'] ]; \$\endgroup\$
    – 640KB
    Feb 1, 2019 at 14:39
  • 2
    \$\begingroup\$ @gwaugh Like a list of list of characters? Yes, that's fine (and explicitly called out as OK). \$\endgroup\$ Feb 1, 2019 at 14:40
  • 3
    \$\begingroup\$ Can we take input as a pair of a string without newlines and the width (or height) of the haystack? i.e. ("########N###########", 5) \$\endgroup\$ Feb 1, 2019 at 15:17
  • 3
    \$\begingroup\$ @someone Yes, though it doesn't have a real quorum, I feel that should be allowed. \$\endgroup\$ Feb 1, 2019 at 15:32

50 Answers 50

21
\$\begingroup\$

R, 49 47 44 bytes

function(m,`?`=which)m==names(?table(m)<2)?T

Try it online!

Takes input as a matrix, returns 1-indexed coordinates

\$\endgroup\$
2
  • 5
    \$\begingroup\$ That which assignment is disgracefully smooth. \$\endgroup\$ Feb 1, 2019 at 15:59
  • 5
    \$\begingroup\$ I was so excited to try this challenge in R, then I saw this and decided to cry in awe instead \$\endgroup\$
    – Sumner18
    Feb 1, 2019 at 18:41
9
\$\begingroup\$

Perl 6, 41 38 37 bytes

3 bytes saved thanks to @nwellnhof.

1 byte saved thanks to Jo King.

{map {[+] ^∞Z*!<<.&[Z~~]},$_,.&[Z]}

Try it online!

Explanation

It takes the input as a list of lists of characters and returns list of length 2 containing zero-based X and Y coordinates of the needle.

It works by applying the block {[+] ^∞ Z* !<<.&[Z~~]} on the input and on its transpose. .&[Z~~] goes through all columns of the argument and returns True if all the elements are the same, False otherwise. We then negate all the values (so we have a list with one bool per column, where the bool answers the question "Is the needle in that column?"), multiply them element-wise with a sequence 0,1,2,... (True = 1 and False = 0) and sum the list, so the result of the whole block is the 0-based number of the column where the needle was found.

Nwellnhof's better approach, Perl 6, 34 bytes

{map *.first(:k,*.Set>1),.&[Z],$_}

Try it online!

Explanation

Generally the same approach, just more effective. It still uses a block on the array and its transpose, but now the block converts all rows intoSets and checks for the number of elements. The first function then gives index (due to the :k) of the first row that contained more than 1 element. Because of that, the order of $_ and .&[Z] needed to be swapped.

\$\endgroup\$
3
  • \$\begingroup\$ Nice approach! 34 bytes with first(:k), Set and .&[Z]. \$\endgroup\$
    – nwellnhof
    Feb 1, 2019 at 15:59
  • \$\begingroup\$ @nwellnhof, very well done. You basically found what I wanted to find but failed to do that :—). (Also I had no idea that you could write .&[Z].) \$\endgroup\$
    – Ramillies
    Feb 1, 2019 at 16:31
  • \$\begingroup\$ In general, .&[op] doesn't seem to be equivalent to [op] $_ but it works with Z for some reason. \$\endgroup\$
    – nwellnhof
    Feb 1, 2019 at 18:35
9
\$\begingroup\$

Python 2, 57 bytes

lambda m:[map(len,map(set,a)).index(2)for a in zip(*m),m]

Try it online!


A port of this to Python 3 can be 62 bytes:

lambda m:[[len(set(v))for v in a].index(2)for a in(zip(*m),m)]

The list comprehension, [len(set(v))for v in a], is shorter than the double map by two bytes now as it would need to be cast to a list like list(map(len,map(set,a)))

Try it online!

\$\endgroup\$
6
\$\begingroup\$

Brachylog, 20 bytes

c≡ᵍ∋Ȯ&;I∋₎;J∋₎gȮ∧I;J

Try it online!

Outputs [I,J], where I is the row index and J the column index, both 0-indexed.

Stupidely long, but getting indexes in Brachylog is usually very verbose.

Explanation

c                       Concatenate the Input into a single string
 ≡ᵍ                     Group identical characters together
   ∋Ȯ                   Ȯ is a list of One element, which is the needle character
     &;I∋₎              Take the Ith row of the Input
          ;J∋₎          Take the Jth character of the Ith row
              gȮ        That character, when wrapped in a list, is Ȯ
                ∧I;J    The output is the list [I,J]
\$\endgroup\$
6
\$\begingroup\$

PHP, 99 85 bytes

Using string without newlines and the width (or height) ('########N###########', 5) as input.

  • -5 bytes by removing chr() call, props to @Titus
  • -9 bytes by taking input as two function args, also props to @Titus
function($a,$l){return[($p=strpos($a,array_flip(count_chars($a,1))[1]))%$l,$p/$l|0];}

Try it online!

Ungolfed:

function need_hay( $a, $l ) {

    // identify the "needle" by counting the chars and 
    // looking for the char with exactly 1 occurrence
    // note: this is 1 byte shorter than using array_search()
    $n = array_flip( count_chars( $a, 1 ) )[1];

    // find the location in the input string
    $p = strpos( $a, $n );

    // row is location divided by row length, rounded down
    $r = floor( $p / $l );

    // column is remainder of location divided by row length
    $c = $p % $l;

    return array( $c, $r );

}

Output:

#####
###N#
#####
#####
[3,1]

^^^
^^^
^N^
^^^
^^^
^^^
[1,2]

jjjjjj
j@jjjj
jjjjjj
[1,1]
\$\endgroup\$
2
  • 1
    \$\begingroup\$ 1) no need for chr: If the second parameter for strpos is an integer, it will be interpreted as an ASCII code. -> -5 bytes. 2) Two function parameters $s,$w can save another 9 bytes. \$\endgroup\$
    – Titus
    Feb 1, 2019 at 18:09
  • \$\begingroup\$ @Titus, removing the chr() that's brilliant. Thx! The func params did occur to me too, I just didn't want to run afowl of input req's. I'll clarify w/OP. \$\endgroup\$
    – 640KB
    Feb 1, 2019 at 19:17
5
\$\begingroup\$

05AB1E, 9 6 bytes

Saved 3 bytes switching input format.

Input is taken as a string and a row-length.
Output is a zero-based list of the form [y, x]

D.mks‰

Try it online! or as a Test Suite

Explanation

D           # duplicate the input string
 .m         # get the least frequent character
   k        # get its index in the string
    s       # swap the row length to the top of the stack
     ‰      # divmod the index of the least frequent char with the row length
\$\endgroup\$
2
  • \$\begingroup\$ Dang, you beat me to it. Was working on an answer. Had just finished a 13-byter. But yours is way better, so +1 instead. :) Completely forgot about .m.. \$\endgroup\$ Feb 1, 2019 at 14:14
  • \$\begingroup\$ @KevinCruijssen: Yeah. I don't think I've ever used .m before, but I was reasonably sure I'd seen it at some point :) \$\endgroup\$
    – Emigna
    Feb 1, 2019 at 14:16
5
\$\begingroup\$

Python 3 + NumPy, 75 66 bytes

-9 bytes thanks to @ASCII-only

lambda x:where(x.view('i')-median(x.view('i')))
from numpy import*

Try it online!

This assumes that the input is a NumPy array. The output is zero-indexed, and first vertical, then horizontal.

It converts the input from char to int then calculates the median of the array, which will be the haystack character. We subtract that from the array, which makes the needle the only non-zero element. Finally, return the index of that element with numpy.where().

\$\endgroup\$
10
  • 1
    \$\begingroup\$ Since you know the input will be ASCII (i.e. fits in a byte) why not use uint8 for one byte less? \$\endgroup\$
    – Draconis
    Feb 1, 2019 at 20:49
  • 1
    \$\begingroup\$ Language has to be "Python 3 + numpy" here since numpy isn't included with the normal Python distribution \$\endgroup\$
    – ASCII-only
    Feb 2, 2019 at 8:39
  • \$\begingroup\$ @Draconis that was actually my plan, but that introduced zeros between the correct uint8 ASCII-codes. I assume this is because Python3 uses Unicode as standard input format for strings. \$\endgroup\$
    – hbaderts
    Feb 4, 2019 at 7:02
  • 1
    \$\begingroup\$ 66 \$\endgroup\$
    – ASCII-only
    Feb 4, 2019 at 8:15
  • 1
    \$\begingroup\$ It's fine, after all it's not only based off your solution, but also I don't normally use numpy anyway. Plus, it's kinda unavoidable that a solution might be very similar anyway given that all solutions are public and this is a relatively easy challenge \$\endgroup\$
    – ASCII-only
    Feb 4, 2019 at 8:31
4
\$\begingroup\$

Jelly, 5 bytes

Outputs [height, width] (1-indexed).

ŒĠLÐṂ

Try it online!

ŒĠLÐṂ – Monadic link / Full program. Takes a list of strings M as input.
ŒĠ    – Group the multidimensional indices by their values (treating M as a matrix).
  LÐṂ – And retrieve the shortest group of indices (those of the unique character).

Jelly, 5 bytes

ŒĠḊÐḟ

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Jelly, 4 bytes

Maybe this could've just been a comment for Mr. Xcoder it is pretty similar...

ŒĠEƇ

A monadic link accepting the matrix of characters which yields a list of one item, the 1-indexed (row, column) co-ordinate from top-left.
(...As a full program given an argument formatted such that parsing results in a list of lists of characters -- that is a list of strings in Python format -- the single coordinate is printed.)

Try it online!

How?

ŒĠEƇ - Link: matrix, M
ŒĠ   - multi-dimensional indices grouped by Value
     -  ...due to the 2*2 minimum size and one needle this will be a list of two lists one
     -     of which will have length one (the needle coordinates as a pair) and the other
     -     containing all other coordinates as pairs
   Ƈ - filter keeping those for which this is truthy:
  E  -   all equal?
     -   ... 1 for the list of length 1, 0 for the list of at least 3 non-equal coordinates
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Well... this seems borderline, since the is clever. \$\endgroup\$ Feb 1, 2019 at 21:29
4
\$\begingroup\$

JavaScript (ES6), 55 bytes

Takes input as \$(s)(w)\$, where \$s\$ is a string and \$w\$ is the width of the matrix. Returns \$[x,y]\$.

s=>w=>[(i=s.indexOf(/(.)\1+(.)/.exec(s+s)[2]))%w,i/w|0]

Try it online!


JavaScript (ES6),  65  64 bytes

Saved 1 byte thanks to @Neil

Takes input as a matrix of characters. Returns \$[x,y]\$.

m=>m.some((r,y)=>r.some((c,x)=>!m[p=[x,y],~y&1].includes(c)))&&p

Try it online!

How?

We look for the first character \$c\$ located at \$(x,y)\$ which does not appear anywhere in another row \$r[Y]\$. We can perform this test on any row, as long as \$Y\ne y\$. Because the input matrix is guaranteed to be at least \$2\times 2\$, we can simply use \$Y=0\$ if \$y\$ is odd or \$Y=1\$ if \$y\$ is even.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ ~y&1 saves a byte over y&1^1. \$\endgroup\$
    – Neil
    Feb 1, 2019 at 16:39
4
\$\begingroup\$

Java 8, 132 111 bytes

m->{int c=m[0][0],i=0,j;for(c=m[1][0]!=c?m[1][1]:c;;i++)for(j=m[i].length;j-->0;)if(m[i][j]!=c)return i+","+j;}

-8 bytes (and -13 more implicitly) thanks to @dana.

Input as character-matrix.

Try it online.

Explanation:

m->{                    // Method with char-matrix parameter and String return-type
  int c=m[0][0],        //  Character to check, starting at the one at position 0,0
      i=0,j;            //  Index integers
  for(c=m[1][0]!=c?     //  If the second character does not equal the first:
         m[1][1]        //   Use the character at position 1,1 instead
        :c;             //  Else: keep the character the same
      ;i++)             //  Loop `i` from 0 indefinitely upwards:
    for(j=m[i].length;j-->0;)
                        //   Inner loop `j` in the range (amount_of_columns, 0]:
      if(m[i][j]!=c)    //    If the `i,j`'th character doesn't equal our character to check:
        return i+","+j;}//     Return `i,j` as result
\$\endgroup\$
6
  • 1
    \$\begingroup\$ 124 - the final return statement should never get hit. There might be a better way to keep the outer loop going? \$\endgroup\$
    – dana
    Feb 2, 2019 at 19:26
  • \$\begingroup\$ @dana Thanks! As for: "There might be a better way to keep the outer loop going?", there certainly is; just removing it so it becomes an infinite loop. And then the return""; is unreachable and can be removed as well. :D So -21 bytes thanks to you. \$\endgroup\$ Feb 2, 2019 at 20:31
  • \$\begingroup\$ Interesting... I had tried removing the outer loop condition and was getting an unreachable code error. Didn't know that removing the final return was the fix. \$\endgroup\$
    – dana
    Feb 2, 2019 at 21:17
  • \$\begingroup\$ What exactly does the --> operator do in the inner loop? I was trying to find the java docs for that syntax but couldnt find anything \$\endgroup\$
    – KBusc
    Feb 4, 2019 at 13:24
  • 1
    \$\begingroup\$ @KBusc It's two operators: i-- and >. :) See this SO answer for more info. So the i > 0 is executed first, checking if i is larger than 0. And then i is decreased by 1 with i--, before it enters the body of the loop. \$\endgroup\$ Feb 4, 2019 at 13:29
3
\$\begingroup\$

MATL, 12 8 bytes

tX:XM-&f

Try it online!

Using the mode function as the majority-detector. Returns 1-based indices.

 t           % duplicate the input
  X:         % turn the copy into a linear array
    XM       % find the arithmetic mode of that (the 'haystack' character)
      -      % Subtract that from the original input
       &f    % find the position of the non-zero value in that result

-4 characters thanks to @LuisMendo

\$\endgroup\$
1
  • 1
    \$\begingroup\$ @LuisMendo Thanks. I don't think I knew about the 2 output version of find, even in MATLAB. (Hi, btw!) \$\endgroup\$
    – Sundar R
    Feb 1, 2019 at 17:35
3
\$\begingroup\$

Wolfram Language 37 58 bytes

My earlier entry did not correctly handle the case where the "odd character out" was at the upper left corner of the matrix. This does.

#~Position~Keys[TakeSmallest[Counts@Flatten@#,1]][[1]]&

Counts@Flatten@# lists how many of each character are in the array, #.

TakeSmallest[...,1] returns the least frequent count, in the form of an association rule such as <| "Z"->1|>

Keys...[[1]] returns the "key" to the only item in the association, that of the least used character. ("Z" in the present case)

#~Position~... returns then position of the key in the original matrix, #.

\$\endgroup\$
3
\$\begingroup\$

Perl 5 -p00, 52 45 bytes

/^(.)(\1*
)*(\1*)|^/;$_=$&=~y/
//.$".length$3

45 bytes

52 bytes

How

  • -p00 : like -n but also print, paragraph mode
  • /^(.)(\1* )*(\1*)|^/ : matches either
    • from start $1: first character, $2: repetition (not used), $3: characters before the "needle" in the line, $& whole match
    • or null string (position 0) no capture.
  • $_= : to assign the default input/argument variable
  • so $&=~y/ // the number of newlines of $&
  • .$". : concatenate with $" (space character by default) and concatenate
  • length$3 : the length of $3
\$\endgroup\$
3
\$\begingroup\$

R 42 bytes

function(m)which(ave(m,m,FUN=length)==1,T)

Try it online!

Input: a haystack matrix m

Output: (row,col) vector - index starting at 1

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Nice job, and welcome to PPCG! I believe this is 42 bytes, since the f= can be omitted from the byte count, but not the function(m)=. \$\endgroup\$
    – BLT
    Feb 6, 2019 at 19:01
  • \$\begingroup\$ @BLT I wasn't sure about that but thanks for the heads up :) \$\endgroup\$
    – niko
    Feb 6, 2019 at 22:49
2
\$\begingroup\$

C# (Visual C# Interactive Compiler), 109 108 107 bytes

First() => Last() for -1 byte

currying for -1 byte thanks to Embodiment of Ignorance

a=>w=>{var d=a.Where(b=>b!=a[0]).Select(b=>a.IndexOf(b));return d.Count()>1?(0,0):(d.Last()%w,d.Last()/w);}

Try it online!

\$\endgroup\$
0
2
\$\begingroup\$

J, 22 bytes

$#:(i.~.{~1 i.~#/.~)@,

Try it online!

NB. returns answer in (row, column) format.

\$\endgroup\$
2
\$\begingroup\$

Python 2, 53 47 bytes

lambda s,w:divmod(s.find(min(s,key=s.count)),w)

Try it online!

Call as f("########N###########", 5) (allowed in a comment). Outputs (y, x).

Erik saved 6 bytes, suggesting rearranging the output + using divmod. Thanks!

\$\endgroup\$
1
2
\$\begingroup\$

PowerShell, 107 98 82 77 bytes

$l=@{}
$args|%{if($_-10){$l.$_+=$x++,+$y}else{$x=0;++$y}}
$l|% v*|? c*t -eq 2

Try it online!

Takes a splatted string with LFs. Returns zero-indexed location x,y. Unrolled:

$locations=@{}                      # make a hashtable. key=char, value=location array
$args|%{
    if($_-10){                      # if current char is not LF
        $locations.$_+=$x++,+$y     # add $x,$y to hashtable value and move $x to next pos
    }else{
        $x=0;++$y                   # move $x,$y to next line
    }
}
$locations|% Values|? Count -eq 2   # find and output location array with 2 elements (x,y)
\$\endgroup\$
2
\$\begingroup\$

Scala, 98 bytes

Golfed version. Try it online!

def f(m:Seq[String])=m.transpose.map(_.toSet.size).indexOf(2)::m.map(_.toSet.size).indexOf(2)::Nil

Ungolfed version. Try it online!

object Main {
  def main(args: Array[String]): Unit = {
    val tests = Seq(
      """#####
        |###N#
        |#####
        |#####""".stripMargin,
      """^^^
        |^^^
        |^N^
        |^^^
        |^^^
        |^^^""".stripMargin,
      """jjjjjj
        |j@jjjj
        |jjjjjj""".stripMargin,
      """Z8
        |88""".stripMargin,
      """88
        |8Z""".stripMargin
    )
    
    val f: Seq[String] => Seq[Int] = m => m.transpose.map(_.toSet.size).indexOf(2) :: m.map(_.toSet.size).indexOf(2) :: Nil

    tests.foreach { test =>
      val v = test.split("\n")
      v.foreach(println)
      println("   -> " + f(v) + "\n")
    }
  }
}

\$\endgroup\$
2
\$\begingroup\$

Julia, 78 bytes

s->(n=argmin(x->count(x,'
's),s);q=split(s);~=findlast;b=~(n.∈q);(n~q[b],b))

Attempt This Online!

This function takes input as a single string, which probably isn't the most efficient approach. The output is 1-indexed.

-19 bytes thanks to MarcMush: add a newline to the haystack to guarantee that the needle is always the least frequent character, even in a 2x2 haystack.

Interestingly, concatenating a character literal with a string variable doesn't require an operator in Julia. Apparently, it's parsed just like numeric literal coefficients with variables. This saves a byte here, which is the best thing to come out of Julia's choice of concatenation operator.

\$\endgroup\$
1
2
\$\begingroup\$

Lua, 103 91 bytes

s,l=...s:gsub('.',load'c=...b=b or not s:find(c..c,1,1)and s:find(c,1,1)')print(b%l-1,b//l)

Try it online!

Ungolfed version:

s,l=...                                           --Take in haystack and line width as args
s:gsub('.',function (d)                           --For each character in s
    b=b or not s:find(c..c,1,1)and s:find(c,1,1)  --If there is only one instance of c, store location
end)
print(b%l-1,b//l)                                 --Print results
\$\endgroup\$
2
\$\begingroup\$

Stax, 15 bytes

this can probably be golfed down a bit as there's a lot of register shenanigans i'm not a huge fan of. takes an array of a single string with a width

Ç║æ░·╝;J╕╤¢ⁿÿì<

Try it online! (With test cases)

This is Packed Stax, which unpacks to the following:

Stax, 17 bytes

Nc|!IYxhX%yx/2l|u

Run and debug it

N                 # get the string
 c|!              # get the rarest element
    I             # get the first index in the string of this
     Y            # store that in register Y
      xh          # get the width
        X         # and store this value in register x
         %        # modulo with what was stored in register Y
          yx      # register y and register x from above
            /     # divide them
             2l   # create an array of the top two elements on the stack
               |u # and put it in a format which can be printed
\$\endgroup\$
1
\$\begingroup\$

Python 3, 93 bytes

def f(s):x=s.find("\n")+1;return[(i%x,i//x)for i,c in enumerate(s)if s.count(c)<2and" "<c][0]

Try it online!

Input is taken as a multiline string. Output is 0-indexed

\$\endgroup\$
1
\$\begingroup\$

Octave, 40 bytes

@(x){[r,c]=find(x-mode(+x(:))) [c,r]}{2}

Port of @sundar's MATL answer. Output is a two-element vector with 1-based column and row indices.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Retina 0.8.2, 41 bytes

s`(?=(.)+\1)(.*?¶)*(.*)(?!\1|¶).+
$.3,$#2

Try it online! 0-indexed. Explanation:

s`

Allow . to match newlines. This costs 3 bytes (3rd byte is the ? before the ) but saves 6 bytes.

(?=(.)+\1)

Look ahead for two identical characters. \1 then becomes the hay.

(.*?¶)*

Count the number of newlines before the needle.

(.*)

Capture the hay to the left of the needle.

(?!\1|¶)

Ensure that the needle isn't hay or a newline.

.+

Match the rest of the hay so that the result replaces it.

$.3,$#2

Output the width of the left hay and the number of newlines.

\$\endgroup\$
1
\$\begingroup\$

C# (Visual C# Interactive Compiler), 82 bytes

x=>w=>{int y=x.IndexOf(x.GroupBy(c=>c).Last(g=>g.Count()<2).Key);return(y%w,y/w);}

Thanks to dana for shaving off 6 bytes!

Try it online!

Old solution, 106 bytes

n=>m=>{var z=n.Distinct();int d=n.IndexOf(n.Count(c=>c==z.First())>1?z.Last():z.First());return(d%m,d/m);}

Both take input as a string and an integer specifying the amount of columns.

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ @dana never knew that Enumerable.Last() accepted a delegate, thanks \$\endgroup\$
    – Gymhgy
    Feb 2, 2019 at 17:34
1
\$\begingroup\$

C (clang), 74 bytes

h(char*s,z,x){for(s+=z--;*s==*--s|*s==s[-1];)z--;printf("%d,%d",z%x,z/x);}

Try it online!

DEGOLF

int h(char*s,int z,int x){// z = string size, x = row size

 for(s+=z--;
 // move pointer just over the end of the string 
 // and move z counter to the end of string

*s-*--s?   ==>  *s==*--s|  @ceilingcat suggestion 
 // if the previous element is different we will check if the next element is also different
 // if not the result is 1 and the iteration continue
 // in the first iteration it will be different because the pointer is just  over the end

 *s-s[-1]? ==> changed to *s==s[-1]   @ceilingcat suggestion 
 // the second check returns 0 if the char changed again so it was the needle
 // if not it's because in the first iteration the first check finded a difference just because the pointer was just over the end

 /*0:1*/   :1;)z--;


 printf("%d,%d",z%x,z/x);
}
\$\endgroup\$
0
1
\$\begingroup\$

Java 8, 104 Bytes

(x,w)->{int i=0,p=x.length;for(;i<p;i++)if(x[i]!=x[(i+1)%p]&&x[i]!=x[(i+2)%p])break;return i/w+","+i%w;}

Input is array of char, and integer indicating row width.

Output is zero-based, vertical then horizontal (i.e., row number then column number)

Explanation:

(x,w)->{
    int i=0, p=x.length;
    for (;i<p;i++)          //iterate through characters in x
      if (x[i]!=x[(i+1)%p] && x[i]!=x[(i+2)%p])    //compare x[i] with the two subsequent characters in array, wrapping around if necessary
        break;
    return i/w+","+i%w;}  //return row number then column number, zero-based
\$\endgroup\$
0
1
\$\begingroup\$

Python 3, 93 89 85 58 bytes

Complete rewrite taking input as concatenated string, width:

lambda g,w:divmod(g.index({g.count(c):c for c in g}[1]),w)

Try it online!


Original answer:

def k(g):t=''.join(g);return divmod(t.index({t.count(c):c for c in t}[1]),len(g[0]))

EDIT: Saved 4 bytes by swapping linebreak/indent for semicolons. Saved another 4 bytes by using divmod(thanks @JonathanFrech).

Try it online!

I know this could be a lot shorter, but I just wanted to try an approach around this dict comprehension.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Using divmod would save five bytes. \$\endgroup\$ Feb 7, 2019 at 0:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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