14
\$\begingroup\$

You're organizing a treasure hunt for your friends. To conduct things more easily, you want to draw a map of all locations where you hid the precious objects.

Input

Any form of input denoting a list of points consisting of (nonnegative) x- and y-coordinate, 0 0 being the upper left corner is permitted (Note: You may also use 1-based indexing in your answer, please comment on that if you do). Example:

1 2
3 0
0 1

Challenge

Your function or program should be able to construct a map denoting every given location with an x where the mark is found in row y + 1 and column x + 1 in the output. Unmarked locations are represented with a . The map also consists of a frame where the corners are +s, the vertical lines are |s and the horizontal lines are -s. Your solution should output the smallest possible frame. Map for the input example given above:

+----+
|   x|
|x   |
| x  |
+----+

Possible Test Cases


"0 0"
=>
+-+
|x|
+-+

"0 10
 5 5
 10 0"
=>
+-----------+
|          x|
|           |
|           |
|           |
|           |
|     x     |
|           |
|           |
|           |
|           |
|x          |
+-----------+

""
=>
++
++

"0 0
 0 2
 2 0"
=>
+---+
|x x|
|   |
|x  |
+---+

Of course, this is , meaning that the solution with the lowest byte count wins! Explanations of your solution are encouraged.

\$\endgroup\$
  • \$\begingroup\$ Not really, but i couldn't really think about another input format. But I'm willing to change that if it benefits the challenge. \$\endgroup\$ – racer290 May 19 '18 at 12:21
  • \$\begingroup\$ Can there be non square maps? \$\endgroup\$ – FrownyFrog May 19 '18 at 12:22
  • 4
    \$\begingroup\$ @racer290 I'd suggest just saying something like the input is a list of locations (e.g. nested list, list of tuples, space & newline separated, separate inputs, ect.) \$\endgroup\$ – dzaima May 19 '18 at 12:24
  • 1
    \$\begingroup\$ Can the output be a 2d array of characters? \$\endgroup\$ – ovs May 19 '18 at 16:14
  • 2
    \$\begingroup\$ Can I submit a function taking the x- and y-coordinates as two separate arguments? \$\endgroup\$ – ბიმო May 19 '18 at 17:01

14 Answers 14

7
\$\begingroup\$

J, 37 34 bytes

0<@|:' x'{~((i.@]e.#.~)1+>./) ::#:

Try it online!

                       1+>./          maximum for each coordinate + 1
             i.@]                     make an array with these dimensions filled with 0..x*y
                                      /* if the input is empty, 
                                         1+>./ is negative infinity
                                         and i.@] throws an error  */
                   #.~                mixed base conversion of input
                 e.                   replace the elements of i.@]
                                        with 1 if it's present in the
                                        converted input, 0 otherwise
           (                ) ::      if there's an error do the other thing instead
                                #:    "to binary", for empty input this returns a 0x0 matrix
0<@|:' x'{~                           index into character string, transpose and put in a box
\$\endgroup\$
  • 1
    \$\begingroup\$ I guess that output formatting is better than the one I proposed ;) \$\endgroup\$ – racer290 May 19 '18 at 13:02
  • \$\begingroup\$ Why is the ::empty so verbose? What's it do? Why can't it be simplified to 1 byte or so? (I have no knowledge of J) \$\endgroup\$ – Magic Octopus Urn Oct 19 '18 at 11:37
  • \$\begingroup\$ I ran it on TIO without ::empty and it seemed to work(dont know J either) \$\endgroup\$ – Quintec Oct 19 '18 at 11:56
  • \$\begingroup\$ Actually ::empty seems to handle the “” input case \$\endgroup\$ – Quintec Oct 19 '18 at 11:57
  • \$\begingroup\$ @MagicOctopusUrn I don’t know a shorter way to output a truly empty box, they are 1 row high by default. \$\endgroup\$ – FrownyFrog Oct 19 '18 at 12:19
4
\$\begingroup\$

JavaScript (ES6), 150 bytes

Takes input as a list of 1-indexed coordinates in [x,y] format. Returns a string.

a=>(g=w=>y<h?' |-+x'[4*a.some(a=>a+''==[x,y])|2*(-~y%h<2)|++x%w<2]+[`
`[x=x<w?x:+!++y]]+g(w):'')((M=i=>Math.max(2,...a.map(a=>a[i]+2)))(x=y=0),h=M(1))

Try it online!

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

Haskell, 127 123 bytes

This defines the operator (!) which takes a list of x-coordinates and a list of the corresponding y-coordinates:

x!y|l<-'+':('-'<$m x)++"+"=unlines$l:['|':[last$' ':['x'|(i,j)`elem`zip x y]|i<-m x]++"|"|j<-m y]++[l];m x=[1..maximum$0:x]

Try it online!

Ungolfed/Explanation

The helper function m expects a list and returns indices (1-based) up to the maximum, if the list is empty it returns []:

m x | null x    = []
    | otherwise = [1 .. maximum x]

The actual operator (!) is just a list-comprehension, traversing all the coordinates and choosing a or x character, which gets joined with newlines:

x ! y
  -- construct the top and bottom line
  | l <- "+" ++ replicate (maximum (0:x)) '-' ++ "+"
  -- join the list-comprehension with new-lines
  = unlines $ 
  -- prepend the top line
      [l]
  -- the actual map:
    -- begin the line with | and add the correct chars for each coordinate
      ++ [ "|" ++ [ if (i,j) `elem` zip x y then 'x' else ' '
    -- "loop" over all x-coordinates
                 | i <- m x
                 ]
    -- end the line with a |
           ++ "|"
    -- "loop" over all y-coordinates
         | j <- m y
         ]
  -- append the bottom line
      ++ [l]
\$\endgroup\$
3
\$\begingroup\$

Canvas, 22 bytes

ø╶{X;┤╋}l|*eL┤-×+e:└∔∔

Try it here!

Takes 1-indexed inputs.

Finally decided to fix a bug that's been annoying me for ages and golfed this down to 21 bytes.

Explanation (half-ASCII-fied for monospace):

ø╶{X;┤╋}l|*eL┤-×+e:└++  full program, implicitly outputting ToS at the end
ø                       push an empty Canvas - the map
 ╶{    }                for each array in the input array
   X                      push "X"
    ;┤                    and push the two coordinates separately on the stack
      ╋                   and overlap the "X" there in the map
        l               get the vertical length of the map
         |*             repeat "|" vertically that many times
           e            encase the map in two of those vertical bars
            L           get the horizontal length of the map
             ┤          subtract 2 (leave place for the "+"es)
              -×        repeat "-" that many times
                +e      encase that line in "+"es
                  :└    push a copy of that below the map
                    ++  and join the 3 items vertically
\$\endgroup\$
3
\$\begingroup\$

Python 2, 151 140 138 bytes

-2 bytes thanks to Jo King.

Input is 1-indexed.

m=input()
w,h=map(max,zip((0,0),*m))
b=['+'+'-'*w+'+']
M=b+['|'+' '*w+'|']*h+b
for x,y in m:M[y]=M[y][:x]+'x'+M[y][x+1:]
print'\n'.join(M)

Try it online!

\$\endgroup\$
  • \$\begingroup\$ I suspect that you're using 1-based indexing, please leave a note on that in your answer as stated in the challenge. \$\endgroup\$ – racer290 May 19 '18 at 12:54
2
\$\begingroup\$

Charcoal, 37 bytes

≔E²⁺²⌈Eθ§λιηB⊟⮌η⊟ηFθ«J⊟⮌ι⊟ιx

Try it online! Link is to verbose version of code. 1-indexed. Explanation:

¿¬LθUR²+«

Special-case empty input by drawing a 2x2 rectangle of +s.

≔E²⁺²⌈Eθ§λιη

Transpose the input, take the maximum of each column (now row) and add 2 to get the box size in Charcoal co-ordinates.

B⊟⮌η⊟η

Draw the box.

Fθ«

Loop over each co-ordinate.

J⊟⮌ι⊟ι

Jump to its position.

x

Mark with a cross.

\$\endgroup\$
  • \$\begingroup\$ Seems to fail for empty input: tio.run/… \$\endgroup\$ – wastl May 19 '18 at 16:45
  • \$\begingroup\$ @wastl Thanks, I've come up with a workaround. \$\endgroup\$ – Neil May 19 '18 at 17:04
2
\$\begingroup\$

Stax, 32 31 24 bytes

╩╠ee%╙æM■↓^⌐╧ΩΓ¡c¥èf¢○ [

Run and debug it

Takes 0-based indices as array of [y, x] pairs.

Explanation:

zs'X&|<cM%'-*'+|S]s{'||Smn++m Unpacked program, implicit input
zs                            Tuck empty array under input
  'X                          Push "X"
    &                         Assign element at all indices (create map)
                                As the indexing arrays are an array of arrays, treat them as a path to navigate a multidimensional array.
                                Extend array if needed.
     |<                       Left-align all to the length of the longest.
       cM%                    Copy, transpose, length (width)
          '-*                 Repeat "-"
             '+|S             Surround with "+"
                 ]s           Make a singleton and tuck it below the map
                   {    m     Map:
                    '||S        Surround with "|"
                         n++  Surround with the above/below border (built above)
                            m Map:
                                Implicit output
\$\endgroup\$
  • 1
    \$\begingroup\$ Nicely done. You can get a little more mileage out of the |S surround instruction, and a trailing shorthand map. (m) Surround takes a and b from the stack and produces b+a+b. And you can use m instead of the final |J to iterate over the rows and produce output. For example \$\endgroup\$ – recursive May 21 '18 at 15:52
  • 1
    \$\begingroup\$ One more thing: you can replace z]n+H% with cM%. This is the piece that gets the map width, but has a special case for empty maps. If you transpose the map before measuring it, the special case goes away. \$\endgroup\$ – recursive May 21 '18 at 15:58
  • \$\begingroup\$ @recursive I had been looking for something like surround, but I searched for the wrong keywords \$\endgroup\$ – wastl May 21 '18 at 16:00
  • \$\begingroup\$ What would you naturally call that operation? I may add it to the docs so the next person can find it. \$\endgroup\$ – recursive May 21 '18 at 16:02
  • \$\begingroup\$ @recursive I don't remember what it was, and I would naturally call it surround now \$\endgroup\$ – wastl May 21 '18 at 16:04
2
\$\begingroup\$

R, 133 125 122 bytes

function(m)cat(z<-c("+",rep("-",u<-max(m[,1])),"+","
"),rbind("|",`[<-`(matrix(" ",u,max(m[,2])),m,"x"),"|","
"),z,sep="")

Try it online!

1-indexed. Takes a matrix as argument. Saved 8 bytes thanks to digEmAll, 3 thanks to Giuseppe! Explanation (earlier version of code):

function(m){                           #x and y are the 1st and 2nd col of m
s=matrix(32,u<-max(m[,1]),max(m[,2]))  #s (treasure map) has dim max(x), max(y) 
s[m]=120                               #place the X's on the map
cat(                                   #print:
    z<-c("+",rep("-",u),"+","\n"),     #the top line
    intToUtf8(rbind(124,s,124,13)),    #the map
    z,                                 #the bottom line.
    sep="")
}
\$\endgroup\$
1
\$\begingroup\$

coords taken of the format [y,x]

JavaScript (Node.js), 191 184 bytes

c=f=a=>{a.map(([y,x])=>(c[M<++y?M=y:y]=c[y]||[])[m<++x?m=x:x]="x",M=m=0)
m++
M++
s=""
for(i=0;i<=M;s+=`
`,i++)for(j=0;j<=m;j++)s+=(c[i]||0)[j]||(j%m?i%M?" ":"-":i%M?"|":"+") 
return s}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ I think you accidentally swapped the x- and y-coordinates somewhere.. \$\endgroup\$ – racer290 May 19 '18 at 12:55
  • \$\begingroup\$ @racer290 could you be more specific? \$\endgroup\$ – DanielIndie May 19 '18 at 13:01
  • \$\begingroup\$ Trying your solution, I found that changing the x coordinate in the test cases led to a change in the vertical direction of the coordinate. I guess the bug is in the first row (a.map(([y,x])) \$\endgroup\$ – racer290 May 19 '18 at 13:04
  • \$\begingroup\$ but x is the right paramter as can be seen by the test cases \$\endgroup\$ – DanielIndie May 19 '18 at 13:10
  • 2
    \$\begingroup\$ So in your solution you take the y coordinate first? I think it'd be better to leave a note on that in your answer then. \$\endgroup\$ – racer290 May 19 '18 at 13:15
1
\$\begingroup\$

JavaScript, 180 bytes

F = 

s=>s.map(([x,y])=>(t[y]=t[Y<y?Y=y:y]||[])[X<x?X=x:x]='x',t=[X=Y=0])&&[...t,0].map((_,y)=>[...Array(X+2)].map((_,x)=>[(t[y]||0)[x]||' ',...'-|+'][!(y%~Y)+2*!(x%~X)]).join``).join`
`


console.log(F([[1,11],[6,6],[11,1]]))

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

Java 10, 238 223 bytes

c->{var r="";int w=0,h=0,x,y;for(var l:c){w=(x=l.get(0))>w?x:w;h=(y=l.get(1))>h?y:h;}for(w++,h++,x=-1;++x<=w;r+="\n")for(y=-1;++y<=h;)r+=x%w+y%h<1?"+":x%w<1?"-":y%h<1?"|":(c+"").contains("["+x+", "+y+"]")?"x":" ";return r;}

1-indexed coordinates.

Try it online.

Explanation:

c->{                      // Method with 2D Lists as parameter and String return-type
  var r="";               //  Result-String, starting empty
  int w=0,h=0,            //  Width and height, starting at 0
      x,y;                //  Temp x,y coordinates
  for(var l:c){           //  Loop over the Inner Lists containing the coordinates
    w=(x=l.get(0))>w?x:w; //   Determine width based on max x-coordinate
    h=(y=l.get(1))>h?y:h;}//   Determine height based on max y-coordinate
  for(w++,h++,            //  Increase both the width and height by 1
      x=-1;++x<=w;        //  Loop `x` in the range [0, width]
      r+="\n")            //    After every iteration: append a new-line to the result
    for(y=-1;++y<=h;)     //   Inner loop `y` in the range [0, height]
      r+=                 //    Append the following character to the result-String:
        x%w+y%h<1?        //    If it's one of the corners:
          "+"             //     Append "+"
        :x%w<1?           //    Else-if it's the top or bottom row:
          "-"             //     Append "-"
        :y%h<1?           //    Else-if it's the right or left column:
          "|"             //     Append "|"
        :(c+"").contains("["+x+", "+y+"]")? 
                          //    Else-if the current `x,y` is part of the input-coordinates
          "x"             //     Append "x"
        :                 //    Else:
          " ";            //     Append " "
  return r;}              //  Return the result-String
\$\endgroup\$
  • \$\begingroup\$ rwhxy; lcwxlgetw? xw; hylgeth? yh; forwhxxwr. foryyhrxwyh? xwyhcxy? xr. \$\endgroup\$ – Magic Octopus Urn Oct 19 '18 at 15:03
  • \$\begingroup\$ @MagicOctopusUrn What are you naming all the variables and get/for for? :S XD \$\endgroup\$ – Kevin Cruijssen Oct 19 '18 at 18:29
1
\$\begingroup\$

C (gcc), 246 234 bytes

Thanks to ceilingcat for the suggestion.

Zero-indexed. The function takes a list of co-ordinates and buffer, finds the maximum x and y values, fills the buffer with spaces, generates the frame, and then plots the 'x's.

f(int*a,char*c){int*b=a,x,y=x=-1,i=0;for(;~*b;*++b>y?y=*b:0,++b)*b>x?x=*b:0;for(x+=4,y+=3,memset(c,32,x*y);++i<x;c[i]=c[y*x-i]=45);for(i=0;i<y;c[x*++i-1]=10*(i<=y))c[x*i]=c[x*i+x-2]=i&&y/i?124:43;for(b=a;~*b;b+=2)c[*b+1-~b[1]*x]='x';}

Try it online!

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

05AB1E, 44 42 bytes

ζεZ}>`UX'-×'+.ø©,F'|NVXF¹YN‚.å„ xè}'|J,}®,

Try it online!


 ζεZ}>`                                     # Push the max of X and Y to the stack +1.
       UX                                   # Store the max X.
         '-×'+.ø©,                          # Print the top border.
                  F                     }   # From 0 to Y...
                   '|                       # Push left border.
                     NV                     # Store current Y in Y.
                       XF          }        # From 0 to X...
                         ¹                  # Push input.
                          YN‚               # Group current X and Y.
                             .å             # Exists in original input ? 1 : 0
                               „ xè         # Exists ? 'X' : ' '
                                    '|J,    # Right border, join, print.
                                         ®, # Print bottom border.

X and Y may be reversed, didn't know if that mattered at all.


I think I have this in less bytes, but we'll see... Nope.

ζεZ}>`D'-×'+.øUð×'|.øs.D)X.ø©svy>`s®sUXès'xsǝXǝ}
\$\endgroup\$
  • 1
    \$\begingroup\$ It's not much, but you can save 1 byte by changing the first F to Lv, remove NV and change Y to y. 41 bytes \$\endgroup\$ – Kevin Cruijssen Oct 19 '18 at 19:51
  • 1
    \$\begingroup\$ As mentioned by @Emigna in the chat, εZ} can be €à. \$\endgroup\$ – Kevin Cruijssen Oct 19 '18 at 22:47
  • \$\begingroup\$ Hate editing this on mobile will wait until near pc. \$\endgroup\$ – Magic Octopus Urn Oct 21 '18 at 0:57
  • 1
    \$\begingroup\$ @KevinCruijssen Ýv not Lv, but still a good edit :). \$\endgroup\$ – Magic Octopus Urn Oct 22 '18 at 16:36
  • \$\begingroup\$ Ah, you're right. Ýv instead of Lv. My bad. \$\endgroup\$ – Kevin Cruijssen Oct 22 '18 at 16:43
0
\$\begingroup\$

C (gcc), 229 220 216 bytes

-9 bytes thanks to ceilingcat.

Zero-indexed. Takes coordinates as list of numbers, where even numbers are X and odd numbers are Y.

X,Y,i,j,k,x,z;f(l,n)int*l;{for(X=Y=0,i=n*=2;i--;X=fmax(l[i],X))Y=fmax(l[i--],Y);n&&X++-Y++;for(--i;i++<Y;puts(""))for(j=-1;j<=X;z=i<0|i==Y,putchar(j++<0|j>X?z?43:'|':x?z?45:32:'x'))for(x=k=n;k--;)x*=l[k--]-i|l[k]-j;}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ @ceilingcat Cheers! \$\endgroup\$ – gastropner Oct 19 '18 at 9:16
  • \$\begingroup\$ Suggest for(n&&X++-Y++;i<=Y;i+=puts("")) instead of n&&X++-Y++;for(--i;i++<Y;puts("")) \$\endgroup\$ – ceilingcat Jan 1 at 21:37

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.