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\$
13
  • \$\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\$ Commented May 19, 2018 at 12:21
  • \$\begingroup\$ Can there be non square maps? \$\endgroup\$ Commented May 19, 2018 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\$ Commented May 19, 2018 at 12:24
  • 1
    \$\begingroup\$ Can the output be a 2d array of characters? \$\endgroup\$ Commented May 19, 2018 at 16:14
  • 2
    \$\begingroup\$ Can I submit a function taking the x- and y-coordinates as two separate arguments? \$\endgroup\$ Commented May 19, 2018 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\$
6
  • 1
    \$\begingroup\$ I guess that output formatting is better than the one I proposed ;) \$\endgroup\$ Commented May 19, 2018 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\$ Commented Oct 19, 2018 at 11:37
  • \$\begingroup\$ I ran it on TIO without ::empty and it seemed to work(dont know J either) \$\endgroup\$ Commented Oct 19, 2018 at 11:56
  • \$\begingroup\$ Actually ::empty seems to handle the “” input case \$\endgroup\$ Commented Oct 19, 2018 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\$ Commented Oct 19, 2018 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\$
0
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\$
1
  • \$\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\$ Commented May 19, 2018 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\$
3
  • \$\begingroup\$ Seems to fail for empty input: tio.run/… \$\endgroup\$ Commented May 19, 2018 at 16:45
  • \$\begingroup\$ @wastl Thanks, I've come up with a workaround. \$\endgroup\$ Commented May 19, 2018 at 17:04
  • \$\begingroup\$ Better workaround: ≔E²⁺²∨⌈Eθ§λι⁰ηB⊟⮌η⊟ηFθ«J⊟⮌ι⊟ιx. \$\endgroup\$ Commented May 26, 2024 at 6:43
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\$
7
  • 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\$ Commented May 21, 2018 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\$ Commented May 21, 2018 at 15:58
  • \$\begingroup\$ @recursive I had been looking for something like surround, but I searched for the wrong keywords \$\endgroup\$ Commented May 21, 2018 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\$ Commented May 21, 2018 at 16:02
  • \$\begingroup\$ @recursive I don't remember what it was, and I would naturally call it surround now \$\endgroup\$ Commented May 21, 2018 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\$
3
  • \$\begingroup\$ If you use normal chars instead of utf8 codes you save 8 characters : tio.run/##ZU7NDoIwDL7zFEu9tKEzDONF4UkMhzmGchgYNhKC@uwIaozRpG36/… \$\endgroup\$ Commented May 21, 2018 at 16:59
  • \$\begingroup\$ 122 bytes by using [<- directly to remove the braces. \$\endgroup\$ Commented May 22, 2018 at 13:32
  • \$\begingroup\$ @Giuseppe indeed! I knew there had to be a way. \$\endgroup\$ Commented May 22, 2018 at 14:09
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\$
5
  • \$\begingroup\$ I think you accidentally swapped the x- and y-coordinates somewhere.. \$\endgroup\$ Commented May 19, 2018 at 12:55
  • \$\begingroup\$ @racer290 could you be more specific? \$\endgroup\$ Commented May 19, 2018 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\$ Commented May 19, 2018 at 13:04
  • \$\begingroup\$ but x is the right paramter as can be seen by the test cases \$\endgroup\$ Commented May 19, 2018 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\$ Commented May 19, 2018 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\$

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\$ fix bug in bottom row 235 bytes \$\endgroup\$ Commented Jan 1, 2019 at 22:28
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\$
7
  • 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\$ Commented Oct 19, 2018 at 19:51
  • 1
    \$\begingroup\$ As mentioned by @Emigna in the chat, εZ} can be €à. \$\endgroup\$ Commented Oct 19, 2018 at 22:47
  • \$\begingroup\$ Hate editing this on mobile will wait until near pc. \$\endgroup\$ Commented Oct 21, 2018 at 0:57
  • 1
    \$\begingroup\$ @KevinCruijssen Ýv not Lv, but still a good edit :). \$\endgroup\$ Commented Oct 22, 2018 at 16:36
  • \$\begingroup\$ Ah, you're right. Ýv instead of Lv. My bad. \$\endgroup\$ Commented Oct 22, 2018 at 16:43
1
\$\begingroup\$

Java 10, 238 223 220 219 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+r).contains("["+x+", "+y+"]")?"x":" ";return r;} 

-3 bytes thanks to @ceilingcat.

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+r).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\$
2
  • \$\begingroup\$ rwhxy; lcwxlgetw? xw; hylgeth? yh; forwhxxwr. foryyhrxwyh? xwyhcxy? xr. \$\endgroup\$ Commented Oct 19, 2018 at 15:03
  • \$\begingroup\$ @MagicOctopusUrn What are you naming all the variables and get/for for? :S XD \$\endgroup\$ Commented Oct 19, 2018 at 18:29
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\$
2
  • \$\begingroup\$ @ceilingcat Cheers! \$\endgroup\$ Commented Oct 19, 2018 at 9:16
  • \$\begingroup\$ Suggest for(n&&X++-Y++;i<=Y;i+=puts("")) instead of n&&X++-Y++;for(--i;i++<Y;puts("")) \$\endgroup\$ Commented Jan 1, 2019 at 21:37

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.