21
\$\begingroup\$

Given a 2D string as input, either as a string with newlines or a list of lines, output the coordinates (x, y) of all the hashes (#) in the list. The input will only contain hashes and spaces. (and newlines, if you choose to take input as a 2D string)

If there are no hashes, you can output anything.

Output should be unambiguous as to which numbers are paired with which.

Example:

##

Should output:

(0,0), (1,0)

That assumes 0-based indexing, starting from the top left. You may start from any corner, use 0 or 1-based indexing, and/or output y first. (e.g. in the form y,x).

More test cases (again, all using 0-based top-left (x, y) indexing):

    #
#####
#

(4, 0), (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (0, 2)


# ###
### #

(0, 0), (2, 0), (3, 0), (4, 0), (0, 1), (1, 1), (2, 1), (4, 1)

Note that these test cases all list by rows, not by following the path.

You may assume the hashes will form a continuous trail, i.e. # # will never be the input. (probably won't matter, but in case somebody wants to regex this)

You also can output the coordinates in any order you want, i.e. vertical columns, horizontal rows, or just an unsorted list.

\$\endgroup\$
10
  • \$\begingroup\$ Can we assume the input only contains hashes and spaces? \$\endgroup\$
    – DJMcMayhem
    Jan 4, 2017 at 18:48
  • \$\begingroup\$ @DJMcMayhem yes, editing that into the question. \$\endgroup\$
    – Riker
    Jan 4, 2017 at 18:49
  • \$\begingroup\$ Would this or this be valid output formats? \$\endgroup\$
    – Zgarb
    Jan 4, 2017 at 19:00
  • \$\begingroup\$ @Zgarb basically with the extra 1,1 and the hash? Eh, sure. \$\endgroup\$
    – Riker
    Jan 4, 2017 at 19:03
  • \$\begingroup\$ Would my alternate format be valid? \$\endgroup\$ Jan 4, 2017 at 19:06

21 Answers 21

10
\$\begingroup\$

Slip, 2 + 1 = 3 bytes

+1 byte for the p flag. Code:

`#

Explanation:

The p-flag returns the position of each occurence of the following:

`#      // The character '#'

Try it here!

\$\endgroup\$
4
  • 1
    \$\begingroup\$ I think we have a winner \$\endgroup\$
    – Adám
    Jan 4, 2017 at 19:33
  • \$\begingroup\$ Any explanation? \$\endgroup\$
    – Riker
    Jan 4, 2017 at 20:05
  • \$\begingroup\$ @EasterlyIrk The backtick escapes a single character as string. The flag requests positional results. \$\endgroup\$
    – Adám
    Jan 4, 2017 at 20:20
  • \$\begingroup\$ @Adám oh, cool! \$\endgroup\$
    – Riker
    Jan 4, 2017 at 20:57
8
\$\begingroup\$

Grime, 5 bytes

pa`\#

Try it online! The output format is a bit funky, but OP has stated that it's valid.

Explanation

Grime is my 2D pattern matching language. The part after ` is the pattern, in this case a 1×1 square containing a #-character. Grime will search the input grid for a match, and prints the first one it finds by default. The part before ` contains options, in this case signifying that all matches (a) should be printed, along with their positions and sizes (p).

\$\endgroup\$
8
\$\begingroup\$

MATL, 7 6 5 bytes

This is using 1-based indexing with (1,1) in the top left corner.

oo&fh

Explanation:

o        % convert char to double 
 o       % remainder mod 2 ('#' == 35, ' '==32) makes spaces falsy
  &f     % apply `find` with 2d-output 
    h   % concatenate outputs to display x- and y-coordinates side by side

Thanks @DJMcMayhem and @LuisMendo for each -1 byte!

Try it online!

\$\endgroup\$
2
  • 3
    \$\begingroup\$ You could do ooH#fh to save one byte. (convert to integers, mod2) Since space is even (mod 2 == 0, falsy) and # is odd (mod 1 == 1, truthy) \$\endgroup\$
    – DJMcMayhem
    Jan 4, 2017 at 18:50
  • \$\begingroup\$ Oh, great, thank you very much!=) \$\endgroup\$
    – flawr
    Jan 4, 2017 at 18:51
7
\$\begingroup\$

Python, 67 bytes

This is actually just a golf of my Stack Overflow answer on a similar topic.

lambda a,e=enumerate:[[(i,j)for j,B in e(A)if'!'<B]for i,A in e(a)]

Try it online!

The loops through the 2D list, recording the hash characters, and returns the result. We save a byte by using char > '!' rather than char == '#', because the input will only consist of hashes and spaces, and so hashes (0x23) will be the only characters larger than exclamation marks (0x21).

\$\endgroup\$
5
\$\begingroup\$

JavaScript (ES6), 70 67 bytes

s=>s.replace(/./g,(c,i)=>c>' '?[i%l,i/-l|0]+' ':'',l=~s.indexOf`
`)

Outputs a newline-and-space-separated list of coordinates, e.g.

4,0
0,1 1,1 2,1 3,1 4,1
0,2

You can get much shorter with a weird output format:

s=>s.replace(/#/g,(c,i)=>[i%l,i/-l|0]+c,l=~s.indexOf`
`)

This outputs

    4,0#
0,1#1,1#2,1#3,1#4,1#
0,2#

for the second test case. It's still clear which numbers are paired with which...

\$\endgroup\$
5
\$\begingroup\$

J, 12 bytes

$#:'#'I.@:=,

Try it online!

Explanation

$#:'#'I.@:=,  Input is y.
           ,  Flatten y
   '#'    =   and form bit vector of equality with #.
      I.@:    Compute positions of 1s
 #:           and convert each to base
$             shape of y.
\$\endgroup\$
4
\$\begingroup\$

Dyalog APL 16.0, 5 chars = 9 bytes or 6 chars = 8 bytes

Gives list of (y,x) pairs from top left.

⍸⎕='#'

where

input

= equals

'#' this character*

* It is possible to save a character at the cost of one byte by replacing '#' with ⍕# (format the root namespace)

TryAPL online! Note that has been emulated with i  because TryAPL runs version 14.0.

\$\endgroup\$
2
  • \$\begingroup\$ Pretty sure in Dyalog APL encoding 1 char = 1 byte, no? \$\endgroup\$
    – devRicher
    Jan 5, 2017 at 1:26
  • \$\begingroup\$ @devRicher Normally, but is not included in the single byte version. See the "bytes" link. \$\endgroup\$
    – Adám
    Jan 5, 2017 at 6:02
4
\$\begingroup\$

Jelly, 8 bytes

n⁶T€,€"J

Try it online!

Given a 2D array of characters (= a list of strings):

            Implicit input (example):
               [[' ', ' ', ' ', ' ', '#']
               ,['#', '#', '#', '#', '#']
               ,['#', ' ', ' ', ' ', ' ']]
n⁶          Not-equal to space (⁶).
               [[0, 0, 0, 0, 1]
               ,[1, 1, 1, 1, 1]
               ,[1, 0, 0, 0, 0]]
  T€        Indices of 1s in each row
               [[5], [1,2,3,4,5], [1]]
    ,€"J    Pair each, vectorizing, with y-indices
               [[[5,1]], [[1,2],[2,2],[3,2],[4,2],[5,2]], [[1,3]]]
\$\endgroup\$
3
\$\begingroup\$

JavaScript (Firefox 30-57), 61 bytes

s=>[for(c of(x=0,y=1,s))if(c<' '?(y++,x=0):(x++,c>' '))[y,x]]

Returns 1-based coordinates. Easily switchable between [y, x] and [x, y] ordering. Ungolfed:

function coords(s) {
    var x = 0;
    var y = 1;
    for (Var c of s) {
        if (c == "\n") {
            y++;
            x=0;
        } else {
            x++;
        }
        if (c == "#") {
            console.log(y, x);
        }
    }
}
\$\endgroup\$
2
\$\begingroup\$

Vim, 37 bytes

:%s/#/\=line('.').','.col('.').' '/g<cr>

Since V is mostly backwards compatible, you can Try it online!

A straightforward regex solution, where it replaces each '#' with the location it was found in (one-based indexing). I was a little bit worried while writing this that the location would change after substituting the first one on a line, but that doesn't seem to be an issue. TBH I'm pleasantly shocked by how simple this solution ended up being.

Unfortunately, vimscript is very verbose, so most of the bytes come from separating the results so that is still legible. Otherwise, we could do

:%s/#/\=line('.').col('.')/g

But this creates output that's pretty hard to interpret. Additionally, it will only work it the grid is always 9x9 or smaller.

This is a really fun solution because it shows each pair of coordinates at the location of the hash it represents. For example, the input

# ###
### #

outputs

1,1  1,3 1,4 1,5 
2,1 2,2 2,3  2,5 

Of course, if we were using V, we could remove the trailing newline, and compress the regex. Then it could simply be

Í#/½line('.').','.col('.').' '/g

(32 bytes)

But since this is the exact same approach and still painfully verbose, it doesn't seem worth it to use a golfing language.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Okay, the whole "shows each pair of coordinates at the location of the hash" is pretty darn cool. +1 \$\endgroup\$
    – Riker
    Jan 5, 2017 at 0:05
2
\$\begingroup\$

Haskell, 53 bytes

concat.zipWith(\y l->[(x,y)|(x,'#')<-zip[0..]l])[0..]

Input is taken as a list of strings. The output is a list of (x,y) pairs (0 indexed), e.g.

*Main> concat.zipWith(\y l->[(x,y)|(x,'#')<-zip[0..]l])[0..] $ ["# ###","### #"]
[(0,0),(2,0),(3,0),(4,0),(0,1),(1,1),(2,1),(4,1)]
\$\endgroup\$
2
\$\begingroup\$

Lua, 141 bytes

w=io.read()x=w:sub(1,w:find("\n")-1):len()_,c=w:gsub("\n","")for i=0,x do for j=0,c+1 do if w:sub(c*x+i,c*x+i)=="#"then print(i,j)end end end

It's 2:30 AM, I'm in bed, on my phone. Why am I doing this?

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

Mathematica, 12 bytes

Position@"#"

Operator form of Position. Assumes a 2D array of characters. 1-indexed starting at the top left entry. Outputs a list of coordinates in the form {row,column}.

\$\endgroup\$
4
  • \$\begingroup\$ The way I read the task description, I don't think taking a 2D array of characters is allowed for languages that support strings. \$\endgroup\$
    – smls
    Jan 24, 2017 at 13:59
  • \$\begingroup\$ @smls meta.codegolf.stackexchange.com/a/2216/61980 \$\endgroup\$
    – ngenisis
    Jan 24, 2017 at 14:20
  • \$\begingroup\$ I'm not convinced. For one thing, that question focuses on char[], which is actually a common way to store strings in C-based languages. Also, this task description specifically mentions "either as a string with newlines or a list of lines", and doesn't mention list-of-lists-of-characters or 2D matrix of characters. \$\endgroup\$
    – smls
    Jan 24, 2017 at 15:08
  • \$\begingroup\$ @smls Exactly. The consensus was that if a question specifies a string, it means a sequence of characters, and if your language has more than one way of expressing that, then you are free to choose the one that suits your golfing needs. Specifying "either as a string with newlines or a list of lines" does nothing to change that since if you represent each line as an array of characters then you get exactly a 2D array of characters. \$\endgroup\$
    – ngenisis
    Jan 24, 2017 at 19:58
1
\$\begingroup\$

PHP, 69 bytes

for(;$a=$argv[++$i];)for($j=0;""<$c=$a[$j++];)echo$c>" "?"$j $i,":"";

Uses 1-based indexing starting from the top left.
Use like:

php -r 'for(;$a=$argv[++$i];)for($j=0;""<$c=$a[$j++];)if($c>" ")echo"$j $i,";' '    #' '#####' '#    '

Will output:

5 1,1 2,2 2,3 2,4 2,5 2,1 3,
\$\endgroup\$
1
\$\begingroup\$

C, 113 bytes

i,j,k,l;f(char**p){i=strlen(*p);l=strlen(p);for(j=0;j<l;j++)for(k=0;k<i;k++)if(p[j][k]==35)printf("%d,%d ",k,j);}

Outputs from test cases:

0,0 2,0 3,0 4,0 0,1 1,1 2,1 4,1 
4,0 0,1 1,1 2,1 3,1 4,1 0,2 

Try it online!

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

RBX.Lua, 131 bytes

Has to assume input is valid (Z is the flat axis, whitespaces are White tiles, hashes can be any other color, top-left part is located at 0, 0, 0) and all parts are part of the same model M, and the model is otherwise empty.

for k,v in pairs(workspace.M:GetChildren())do if v.BrickColor~=BrickColor.new("White")then print(v.Position.X,-v.Position.Y)end end

Sample input/output:

Example

\$\endgroup\$
2
  • \$\begingroup\$ Can you provide a valid i/o example? \$\endgroup\$
    – Riker
    Jan 5, 2017 at 20:38
  • \$\begingroup\$ @EasterlyIrk There, edited the answer. \$\endgroup\$
    – devRicher
    Jan 5, 2017 at 20:56
1
\$\begingroup\$

Perl 6, 25 bytes (22 characters)

{^∞ZX@_».indices("#")}

Takes input as a list of lines.
Outputs one list per line, each containing (y, x) tuples for the coordinates.
Try it online!

How it works

{                    }  # A lambda.
{    @_»             }  # For each input line:
        .indices("#")   #    get x-coordinates.  (4) (0 1 2 3 4) (0)
 ^∞                     # Range from 0 to Inf.    0   1           2 ...
   Z                    # Zip with:              (0 (4)) (1 (0 1 2 3 4)) (2 (0))
    X                   #    Cartesian product.  ((0 4)) ((1 0) (1 1) (1 2) (1 3) (1 4)) ((2 0))
\$\endgroup\$
1
\$\begingroup\$

Groovy, 80 68 bytes

{y=0;it.each{it.eachWithIndex{x,i->print(x=='#'?"($i,$y)":"")};y++}}

Example input:

[#   #,#   #,#####]

Example Output:

(0,0)(4,0)(0,1)(4,1)(0,2)(1,2)(2,2)(3,2)(4,2)
\$\endgroup\$
1
  • \$\begingroup\$ Why split the input into lines, when the task description allows taking an already split list of lines? \$\endgroup\$
    – smls
    Jan 24, 2017 at 13:57
1
\$\begingroup\$

Ruby, 24 + 1 = 25 bytes

+1 byte for -n flag. Coordinates are 1-based, one number per line.

gsub(/#/){p$`.size+1,$.}

Try it online!

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

C, 80 bytes

x,y;f(char*s){for(x=y=0;*s;printf(*s-35?"":"%d,%d ",x,y),*s++==10?++y,x=0:++x);}

Requires input as newline-delimited char array, prints output to screen.

Ungolfed & usage:

x,y;

f(char*s){
 for(
  x = y = 0;             //init coordinates
  *s;                //iterate until end
  printf(*s-35 ? "" : "%d,%d ", x, y),     //print coordinates or empty string
  *s++==10 ? ++y, x=0 : ++x              //advance to the right or the next line
 );
}


main(){
 f("    #\n#####\n#    ");
 puts("");
 f("# ###\n### #");
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ 78 bytes: x,y;f(char*s){for(x=y=0;*s;*s++==10?++y,x=0:++x)*s==35&&printf("%d,%d ",x,y);} \$\endgroup\$
    – gastropner
    Dec 27, 2017 at 15:20
0
\$\begingroup\$

APL (Dyalog Extended), 2 bytes

⍸<

Try it online!

I win. (Though it's technically tie because we don't count flags in bytes anymore...)

Basically works like the existing APL answer, but it doesn't test for equality with '#'; it tests if each char is non-blank.

\$\endgroup\$

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.