Find all the coordinates on a path

21

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.

Rɪᴋᴇʀ

Posted 2017-01-04T18:39:31.197

Reputation: 7 410

Can we assume the input only contains hashes and spaces? – James – 2017-01-04T18:48:11.980

@DJMcMayhem yes, editing that into the question. – Rɪᴋᴇʀ – 2017-01-04T18:49:29.247

Would this or this be valid output formats?

– Zgarb – 2017-01-04T19:00:30.413

@Zgarb basically with the extra 1,1 and the hash? Eh, sure. – Rɪᴋᴇʀ – 2017-01-04T19:03:52.337

Would my alternate format be valid?

– ETHproductions – 2017-01-04T19:06:43.700

@FlipTack define flat list? i.e. [1, 2, 3, 4] where [1,2] and [3,4] are the coordinates? No. – Rɪᴋᴇʀ – 2017-01-04T19:41:52.200

What about [[(0, 0)], [(1, 0), (1, 1), (1, 2), (1, 3)], [(2, 3)]] - a list for each row, containing its coordinates? – FlipTack – 2017-01-04T19:48:09.647

@FlipTack that works, yes. – Rɪᴋᴇʀ – 2017-01-04T19:51:06.400

@EasterlyIrk Would this.. "format" qualify as input?

– devRicher – 2017-01-05T19:20:03.327

@devRicher that test case won't happen at all, but I may allow that input format. I'll ping you in chat. – Rɪᴋᴇʀ – 2017-01-05T20:10:49.937

Answers

10

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!

Adnan

Posted 2017-01-04T18:39:31.197

Reputation: 41 965

1I think we have a winner – Adám – 2017-01-04T19:33:21.833

Any explanation? – Rɪᴋᴇʀ – 2017-01-04T20:05:13.493

@EasterlyIrk The backtick escapes a single character as string. The flag requests positional results. – Adám – 2017-01-04T20:20:41.367

@Adám oh, cool! – Rɪᴋᴇʀ – 2017-01-04T20:57:35.630

8

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!

flawr

Posted 2017-01-04T18:39:31.197

Reputation: 40 560

3You 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) – James – 2017-01-04T18:50:51.080

Oh, great, thank you very much!=) – flawr – 2017-01-04T18:51:11.570

8

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

Zgarb

Posted 2017-01-04T18:39:31.197

Reputation: 39 083

7

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

FlipTack

Posted 2017-01-04T18:39:31.197

Reputation: 13 242

5

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

ETHproductions

Posted 2017-01-04T18:39:31.197

Reputation: 47 880

5

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.

Zgarb

Posted 2017-01-04T18:39:31.197

Reputation: 39 083

4

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

Lynn

Posted 2017-01-04T18:39:31.197

Reputation: 55 648

3

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.

Adám

Posted 2017-01-04T18:39:31.197

Reputation: 37 779

Pretty sure in Dyalog APL encoding 1 char = 1 byte, no? – devRicher – 2017-01-05T01:26:40.067

@devRicher Normally, but is not included in the single byte version. See the "bytes" link. – Adám – 2017-01-05T06:02:46.493

3

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

Neil

Posted 2017-01-04T18:39:31.197

Reputation: 95 035

2

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.

James

Posted 2017-01-04T18:39:31.197

Reputation: 54 537

2Okay, the whole "shows each pair of coordinates at the location of the hash" is pretty darn cool. +1 – Rɪᴋᴇʀ – 2017-01-05T00:05:45.987

2

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

nimi

Posted 2017-01-04T18:39:31.197

Reputation: 34 639

2

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?

devRicher

Posted 2017-01-04T18:39:31.197

Reputation: 1 609

1

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)

Magic Octopus Urn

Posted 2017-01-04T18:39:31.197

Reputation: 19 422

Why split the input into lines, when the task description allows taking an already split list of lines? – smls – 2017-01-24T13:57:55.503

1

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

ngenisis

Posted 2017-01-04T18:39:31.197

Reputation: 4 600

The way I read the task description, I don't think taking a 2D array of characters is allowed for languages that support strings. – smls – 2017-01-24T13:59:55.083

@smls http://meta.codegolf.stackexchange.com/a/2216/61980

– ngenisis – 2017-01-24T14:20:00.833

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. – smls – 2017-01-24T15:08:18.427

@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. – ngenisis – 2017-01-24T19:58:05.963

1

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,

user59178

Posted 2017-01-04T18:39:31.197

Reputation: 1 007

1

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

devRicher

Posted 2017-01-04T18:39:31.197

Reputation: 1 609

Can you provide a valid i/o example? – Rɪᴋᴇʀ – 2017-01-05T20:38:21.597

@EasterlyIrk There, edited the answer. – devRicher – 2017-01-05T20:56:21.873

1

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!

betseg

Posted 2017-01-04T18:39:31.197

Reputation: 8 493

1

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

smls

Posted 2017-01-04T18:39:31.197

Reputation: 4 352

1

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!

Jordan

Posted 2017-01-04T18:39:31.197

Reputation: 5 001

0

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

Karl Napf

Posted 2017-01-04T18:39:31.197

Reputation: 4 131

178 bytes: x,y;f(char*s){for(x=y=0;*s;*s++==10?++y,x=0:++x)*s==35&&printf("%d,%d ",x,y);} – gastropner – 2017-12-27T15:20:20.777