23
\$\begingroup\$

(Inspired by an early draft of PhiNotPi's fractal line challenge.)

You're given a width W > 1, a height H > 1 and string consisting of 2(W+H-2) printable ASCII characters. The task is to print this string wrapped around a rectangle of the given width and height, starting in the top left corner, in a clockwise sense. The rectangle's inside is filled with spaces. The test cases should hopefully make this very clear.

You may write a program or function, taking input via STDIN (or closest alternative), command-line argument or function argument, and either printing the result to STDOUT (or closest alternative) or returning it as a string.

There must be no leading or trailing spaces (apart from those that might be in the input string). You may optionally output a single trailing newline.

This is code golf, so the shortest submission (in bytes) wins.

Test Cases

Each test case is "String" W H followed by the expected output.

"Hello, World! "
5 4
Hello
    ,
!    
dlroW

"+--+|||+--+|||"
4 5
+--+
|  |
|  |
|  |
+--+

">v<^"
2 2
>v
^<

"rock beats scissors beats paper beats "
11 10
rock beats 
          s
s         c
t         i
a         s
e         s
b         o
          r
r         s
epap staeb 

Note that the following string contains an escaped '"'.
"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
46 3
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN
~                                            O
}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQP

Leaderboards

Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

# Ruby, <s>104</s> <s>101</s> 96 bytes

function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function getAnswers(){$.ajax({url:answersUrl(page++),method:"get",dataType:"jsonp",crossDomain:true,success:function(e){answers.push.apply(answers,e.items);if(e.has_more)getAnswers();else process()}})}function shouldHaveHeading(e){var t=false;var n=e.body_markdown.split("\n");try{t|=/^#/.test(e.body_markdown);t|=["-","="].indexOf(n[1][0])>-1;t&=LANGUAGE_REG.test(e.body_markdown)}catch(r){}return t}function shouldHaveScore(e){var t=false;try{t|=SIZE_REG.test(e.body_markdown.split("\n")[0])}catch(n){}return t}function getAuthorName(e){return e.owner.display_name}function process(){answers=answers.filter(shouldHaveScore).filter(shouldHaveHeading);answers.sort(function(e,t){var n=+(e.body_markdown.split("\n")[0].match(SIZE_REG)||[Infinity])[0],r=+(t.body_markdown.split("\n")[0].match(SIZE_REG)||[Infinity])[0];return n-r});var e={};var t=0,c=0,p=-1;answers.forEach(function(n){var r=n.body_markdown.split("\n")[0];var i=$("#answer-template").html();var s=r.match(NUMBER_REG)[0];var o=(r.match(SIZE_REG)||[0])[0];var u=r.match(LANGUAGE_REG)[1];var a=getAuthorName(n);t++;c=p==o?c:t;i=i.replace("{{PLACE}}",c+".").replace("{{NAME}}",a).replace("{{LANGUAGE}}",u).replace("{{SIZE}}",o).replace("{{LINK}}",n.share_link);i=$(i);p=o;$("#answers").append(i);e[u]=e[u]||{lang:u,user:a,size:o,link:n.share_link}});var n=[];for(var r in e)if(e.hasOwnProperty(r))n.push(e[r]);n.sort(function(e,t){if(e.lang>t.lang)return 1;if(e.lang<t.lang)return-1;return 0});for(var i=0;i<n.length;++i){var s=$("#language-template").html();var r=n[i];s=s.replace("{{LANGUAGE}}",r.lang).replace("{{NAME}}",r.user).replace("{{SIZE}}",r.size).replace("{{LINK}}",r.link);s=$(s);$("#languages").append(s)}}var QUESTION_ID=47710;var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";var answers=[],page=1;getAnswers();var SIZE_REG=/\d+(?=[^\d&]*(?:&lt;(?:s&gt;[^&]*&lt;\/s&gt;|[^&]+&gt;)[^\d&]*)*$)/;var NUMBER_REG=/\d+/;var LANGUAGE_REG=/^#*\s*([^,]+)/
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script><link rel=stylesheet type=text/css href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><div id=answer-list><h2>Leaderboard</h2><table class=answer-list><thead><tr><td></td><td>Author<td>Language<td>Size<tbody id=answers></table></div><div id=language-list><h2>Winners by Language</h2><table class=language-list><thead><tr><td>Language<td>User<td>Score<tbody id=languages></table></div><table style=display:none><tbody id=answer-template><tr><td>{{PLACE}}</td><td>{{NAME}}<td>{{LANGUAGE}}<td>{{SIZE}}<td><a href={{LINK}}>Link</a></table><table style=display:none><tbody id=language-template><tr><td>{{LANGUAGE}}<td>{{NAME}}<td>{{SIZE}}<td><a href={{LINK}}>Link</a></table>

\$\endgroup\$
  • 8
    \$\begingroup\$ Your leaderboards are so cool. \$\endgroup\$ – Alex A. Mar 13 '15 at 21:31
  • 2
    \$\begingroup\$ Did you golf your leaderboard script? \$\endgroup\$ – mbomb007 Mar 13 '15 at 21:35
  • 2
    \$\begingroup\$ @mbomb007 No, I ran the code through minifiers, so it wouldn't take up much space when expanded. (I guess removing line breaks would have been sufficient.) I've still got an unminified version on my hard drive. \$\endgroup\$ – Martin Ender Mar 13 '15 at 21:38
  • 2
    \$\begingroup\$ If you renamed this to "The Chars in the String Go Round and Round", it fits the rhythm of the song better. \$\endgroup\$ – Justin Mar 14 '15 at 19:01

24 Answers 24

9
\$\begingroup\$

CJam, 27 bytes

Nl~:L/(os\2-{)L2-S*@(N@}*W%

I don't really CJam, but I think this beats Martin. The main difference is that we push a newline before reading input and print the first line immediately, negating the need to store the height.

Takes input in the order

H "String" W

Try it online.

\$\endgroup\$
10
\$\begingroup\$

Python 2, 95 bytes

s,m,n=input()
print s[:n]
for i in range(m-2):print s[~i]+' '*(n-2)+s[n+i]
print s[1-m::-1][:n]

Prints the first line, then the two vertical lines, then the last line.

There's got to be something shorter than writing print three times, but everything I've tried so far with saving to a variable and '\n'.join has been longer.

\$\endgroup\$
  • \$\begingroup\$ You could switch to Python 3 and store print in a variable... \$\endgroup\$ – Omar Mar 13 '15 at 2:20
  • 1
    \$\begingroup\$ @Omar That winds up being longer because you have to use eval on the input and bracket the print statements. \$\endgroup\$ – FryAmTheEggman Mar 13 '15 at 2:46
  • \$\begingroup\$ Oh, I hadn't taken eval into account! The parenthesis shouldn't be too much of a problem since print in Python 2 needs a space after it. Going from print blah to p(blah) still saves 3 characters. \$\endgroup\$ – Omar Mar 13 '15 at 16:37
9
\$\begingroup\$

CJam, 31 30 bytes

At Optimizer's insistence, here is my own attempt. I'm not a fan of winning my own challenges, so I'm counting the APL family (or someone better at CJam) to beat this. ;)

l~:H;:V/(N@s{)V2-S*@(N@}H2-*W%

Takes input in the same order as given in the question:

"Hello, World! " 5 4

Test it here.

One byte saved thanks to Optimizer.

Explanation

Originally, I had a really nice idea for starting with the rectangle of spaces and then literally wrapping the string around it while rotating the entire grid four times. However, I couldn't seem to get that to work in case where width or height or both are 2. So I tried the naive approach (print top, loop over sides, print bottom), and surprisingly it turned out to be really short.

l~                             "Read and evaluate the input.";
  :H;                          "Store the height in H and discard it.";
     :V/                       "Store the width in V and split the input into chunks of size V.";
        (N                     "Slice off the first such chunk and push a newline.";
          @s                   "Pull up the other chunks and join them back together.";
            {          }H2-*   "Repeat this block H-2 times, printing the sides.";
             )                 "Slice off the last character of the string.";
              V2-S*            "Push V-2 spaces.";
                   @(          "Pull up the remaining string and slice off the first character.";
                     N@        "Push a newline and pull up the remaining string.";
                            W% "Reverse the remainder of the string, which is the bottom row.";
\$\endgroup\$
  • \$\begingroup\$ Because we can get the length of the string and we have V, there is no need to save H. Just repeat the block until only V characters remain. l~;:V/(N@s{)V2-S*@(N@_,V-}gW% saves 1 char. \$\endgroup\$ – DocMax Mar 13 '15 at 20:17
  • \$\begingroup\$ @DocMax Unfortunately, that doesn't work for height 2. It's a good idea though, I'll look into whether I can make use of it in a different way somehow. \$\endgroup\$ – Martin Ender Mar 13 '15 at 20:19
  • \$\begingroup\$ D'oh! You even mentioned to H=2 problem and I still forgot to guard against it. \$\endgroup\$ – DocMax Mar 13 '15 at 20:21
9
\$\begingroup\$

Pyth, 47 46 45 40 37 36 bytes

This is the obvious approach implemented in Pyth. It prints the first line by indexing 0:width and then the middle, then the end.

Thanks to @Jakube for the tip with using z and Q for two inputs and using p.

AkYQ<zkV-Y2p*d-k2@zt_N@z+kN;<_<z-2Yk

Takes input from stdin as a string and as a tuple of dimensions, newline separated:

Hello, World! 
5, 4

and writes to stdout.

Try it here.

A              Double assignment
 kY            The vars k and Y
 Q             The dimension tuple
<zk            Prints out first line by doing z[:width]
V-Y2           For N in height-2
 p             Print out everything
  *d           Repeat " "
   -k2         Width-2 times
  @z           Index z
   -_N1        At index -N-1
  @z           Index z
   +kN         At index k+N
;              Close out loop
<_<z-2Yk       Print last line
\$\endgroup\$
  • \$\begingroup\$ Using z for reading the string saves quite a lot of chars. Also t_N is the same thing as -_N1. \$\endgroup\$ – Jakube Mar 13 '15 at 1:55
  • \$\begingroup\$ 37 chars are possible with our approach. \$\endgroup\$ – Jakube Mar 13 '15 at 2:12
  • \$\begingroup\$ @Jakube thanks for the tips! \$\endgroup\$ – Maltysen Mar 13 '15 at 4:12
  • \$\begingroup\$ One more char saving. Instead of ++ use p and switch the zt_N with *d-k2. \$\endgroup\$ – Jakube Mar 13 '15 at 11:44
5
\$\begingroup\$

J, 61 bytes

Method:

Starting from a (height-2)*(width-2) block of spaces we take the necessary amount of characters from the end of the string and add it to the current block. We repeat this 4 times. The total 5 states illustrated with the 'Hello, World! ' 5 4 example (spaces replaced with Xs for readability):

XXX   !_   orld   ,_W   Hello
XXX   XX   XXX!   XXo   _XXX,
      XX   XXX_   XXr   !XXX_
      XX          XXl   dlroW
                  _!d   

The code:

4 :'|:>{:((}.~{:@$);({.~{:@$)|.@|:@,])&>/^:4(|.x);'' ''$~y-2'

Explicit function definition. The two-operand function takes a string as left argument and a list of two integers as right argument.

Example usage:

   wrap_on=.4 :'|:>{:((}.~{:@$);({.~{:@$)|.@|:@,])&>/^:4(|.x);'' ''$~y-2'

   'Hello, World! ' wrap_on 5 4
Hello
    ,
!    
dlroW

   '>v<^' wrap_on 2 2
>v
^<

Try it online here.

\$\endgroup\$
  • \$\begingroup\$ Wow, I'm impressed that this works for width and height 2 in J. \$\endgroup\$ – Martin Ender Mar 15 '15 at 11:28
4
\$\begingroup\$

Pyth, 38 37

AGHQ<zGFNC,_>z_ttH>zGj*dttGN)<>_zttHG

I originally had a different 38 solution, but it was basically golfed solution of Maltysen's answer. So I decided to go a little bit different.

Try it online.

              implicit: z=string from input, Q=pair of numbers from input
AGHQ          G=Q[0] (width), H=Q[1] (height)
<zG           print z[:G]
    _>z_ttH     last H-2 chars reversed
    >zG         all chars from the Gth position to end
  C,           zip these 2 strings to pairs
FN            for each pair N:
  j*dttGN       seperate the two chars by (G-2) spaces and print
)             end for
<>_zttHG     print last line z[::-1][H-2:][:G]
\$\endgroup\$
  • \$\begingroup\$ _>z_ttH is equivalent to <_zttH. \$\endgroup\$ – isaacg Mar 13 '15 at 10:37
  • \$\begingroup\$ @isaacg Thanks, already seen something similar in Maltysen's answer. \$\endgroup\$ – Jakube Mar 13 '15 at 11:41
4
\$\begingroup\$

JavaScript (ES6), 110 115

Function with 3 parameters, returning a string

F=(s,w,h,q=h+(w-=2),t=b='')=>
[for(c of s)q?t+=q<h?c+'\n'+s[w+h+w+q--]+' '.repeat(q&&w):(b+=s[w+q--],c):q]
&&t+b

Chrome version 119: no short format for functions, no default parameters. No reason to use for(of) even if it is supported

function F(s,w,h){
  for(q=h+(w-=2),t=b=i='';
      q;
      q<h?t+='\n'+s[w+h+w+q--]+' '.repeat(q&&w):b+=s[w+q--])
    t+=s[i++];
  return t+b
}

ES5 version 126: no for(of), no string.repeat

function F(s,w,h){
  for(q=h+(w-=2),t=b=i='';
      q;
      q<h?t+='\n'+s[w+h+w+q--]+Array(q&&-~w).join(' '):b+=s[w+q--])
    t+=s[i++];
  return t+b
}

Ungolfed

F=(s,w,h)=>
{
  var q = h+(w-=2), // middle length 
      t = '', // top and body
      b = ''; // bottom row
  for(c of s)
    if (q > 0)
    {
      if (q < h)
      {
        t += c+'\n'; // right side, straight
        t += s[w+h+w+q]; // left side, backwards 
        if (q > 1) // body fill, except for the last line
          t += ' '.repeat(w)
      }
      else
      {
        t+=c, // top, straight
        b+=s[w+q] // bottom, backwards
      }
      --q
    }
  return t+b

Test In Firefox/FireBug console

;[["Hello, World! ", 5, 4],["+--+|||+--+|||",4,5],[">v<^",2,2]
,["rock beats scissors beats paper beats ",11,10]
,["!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~",46,3]]
.forEach(test => console.log(F(...test)))

Output

Hello
    ,
!    
dlroW

+--+
|  |
|  |
|  |
+--+

>v
^<

rock beats 
          s
s         c
t         i
a         s
e         s
b         o
          r
r         s
epap staeb 

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN
~                                            O
}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQP
\$\endgroup\$
3
\$\begingroup\$

Python 2, 97 bytes

def f(s,w,h):print s[:w];i=0;exec'print s[~i]+" "*(w-2)+s[w+i];i+=1;'*(h-2);print s[1-h:w+h-3:-1]

Taking the direct approach.

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

Haskell, 164 156 bytes

import Data.List
r=replicate
p w h(s:t)=unlines$fst$n$n$n$n(r h$r w ' ',(w,h,s:t++[s]))
n(_:b,(w,h,s))=(transpose$map reverse$(take w s):b,(h,w,drop(w-1)s))

The function p doesn't print the output, but returns it as a string, e.g p 4 5 "+--+|||+--+|||" -> "+--+\n| |\n| |\n| |\n+--+\n". For better display use putStr:

putStr $ p 4 5 "+--+|||+--+|||"

+--+
|  |
|  |
|  |
+--+

How it works: I create a w x h block of spaces and replace the first line with the beginning of the input string. Then I rotate the block counterclockwise and repeat replacing the first line another three times.

To prevent cutting of the first character again after turn #4, I append it to the input string before starting.

"Hello World" example, 5 x 4


         |  Start               Turn #1          Turn #2     Turn #3   Turn #4
---------+--------------------------------------------------------------------
String   |  "Hello, World! H"   "o, World! H"    "World! H"  "d! H"    ""
left     | 
         |
Block    |  <empty>             Hello            o, W        World     d! H
before   |                                       l                     l  e
rotating |                                       l           ,         r  l
         |                                       e           olleH     o  l
         |                                       H                     W ,o

Edit: found a better way to solve the cut-off-first-character-after-turn-#4 problem.

\$\endgroup\$
  • \$\begingroup\$ Ah nice... this is similar to what I tried in CJam, except it works. ;) \$\endgroup\$ – Martin Ender Mar 14 '15 at 14:52
3
\$\begingroup\$

Postscript, 62 bytes

This of course uses binary tokens, but it is equivalent to:

/Courier findfont setfont

0 h moveto

s [
    w {1 0} repeat pop pop
    h {0 -1} repeat pop pop
    w {-1 0} repeat pop pop
    h {0 1} repeat
] xyshow

Here is a hexdump of the file (xxd round.ps):

0000000: 91c7 9243 9295 3020 6892 6b73 5b77 7b31  ...C..0 h.ks[w{1
0000010: 2030 7d92 8392 7592 7568 7b30 202d 317d   0}...u.uh{0 -1}
0000020: 9283 9275 9275 777b 2d31 2030 7d92 8392  ...u.uw{-1 0}...
0000030: 7592 7568 7b30 2031 7d92 835d 92c3       u.uh{0 1}..]..

Run as:

gs -dw=11 -dh=10 -ss="rock beats scissors beats paper beats " round.ps

The output is really small (as a result of not scaling the font at all), so you need to zoom in a fair bit to see it.

This takes advantage of the xyshow operator to write out the string using custom character spacings. In this case, I use the negative vertical spacing to write down, then negative horizontal space to write backwards, then positive vertical space to write upward. Because of this, I don't need to use any sort of string manipulation.

\$\endgroup\$
3
+100
\$\begingroup\$

><>, 82 80 + 3 = 83 bytes

:2-&\
v!?:<oi-1
/?(0:i
\~ao{2-{~}
\{:?!v1-}o&:&
>:?v!~{{o}ao4.
^  >" "o1-
o;!?l<

Esolang page for ><> (Fish)

This turned out to be shorter than I expected. It uses the straightforward approach of printing the first line, then the columns padded with the central spaces, then the last line.

Input the string via STDIN and the height and width via command line with the -v flag, like so:

py -3 fish.py round.fish -v <height> <width>

Explanation

:2-&           Put W-2 in the register
:?!v1-io       Directly print the first W characters of the input
i:0(?/         Read the rest of the input
~ao{2-{~}      Pop a few leftovers 0s from above, decrement H by 2 and print a newline
               Stack now consists of H = H-2 at the bottom and the rest of the input reversed

[loop]

{:?!v          If H is 0...
  ~                Pop the 0
  l?!;o            Print the rest of the (reversed) input

               Otherwise...
  1-}              Decrement H
  o                Output the top of stack
  &:&              Copy I = W-2 from the register
  :?               If I is nonzero...
    " "o1-             Print a space and decrement I, then repeat from the previous line
  {{o}ao           Print the bottom input character and output a newline
  4.               Jump to the start of the loop (note that I = 0 is leftover from above)
\$\endgroup\$
2
\$\begingroup\$

Bash+coreutils, 124

A shell script to get you started:

echo "${3:0:$1}"
fold -1<<<"${3:$1*2+$2-2}"|tac|paste - <(fold -1<<<"${3:$1:$2-2}")|expand -t$[$1-1]
rev<<<"${3:$1+$2-2:$1}"

Pass input as command-line args:

$ ./roundnround.sh 5 4 "Hello, World! "
Hello
    ,
!    
dlroW
$ 
\$\endgroup\$
2
\$\begingroup\$

JavaScript, 161 160 158 bytes

The method I've come up with turned out way too long, but oh well, it's been practice. (Also, I got it to spell out r+o[u]+'\n':d.)

function f(o,w,n){s=o.slice(0,w)+'\n';o=o.slice(w);n-=2;r='';for(u=w-2;u--;)r+=' ';for(u=d=0;d=o[2*n+w+~u],u<w+n;u++)s+=(u<n)?(d||' ')+r+o[u]+'\n':d;return s}

For input that doesn't make sense the output is undefined (literally, and a bunch of times), but it works for all the test cases.

\$\endgroup\$
  • \$\begingroup\$ slice is shorter than substr, it's not exactly the same but in this case you can use it \$\endgroup\$ – edc65 Mar 13 '15 at 11:26
2
\$\begingroup\$

Groovy, 140

f={a,x,y->println a.substring(0,x);(1..y-2).each{println a[a.length()-it]+' '*(x-2)+a[it+x-1]}println a.substring(x+y-2,2*x+y-2).reverse()}

call:

f('rock beats scissors beats paper beats ',11,10)

output:

rock beats 
          s
s         c
t         i
a         s
e         s
b         o
          r
r         s
epap staeb 
\$\endgroup\$
2
\$\begingroup\$

K, 55 54 bytes

Using the same approach as randomra's J implementation; Start with a block of spaces and add from the tail of the string to the edge while rotating four times:

f:{`0:*4{((,r#*|x),|:'+*x;(r:-#*x)_*|x)}/((y-2)#" ";x)}

And some examples:

  f["Hello,_World!_";4 5]
Hello
_   ,
!   _
dlroW

  f[">v<^";2 2]
>v
^<

Breaking it down a little for readability,

Generate an NxM block:

  t:2 3#!6
(0 1 2
 3 4 5)

Rotate 90 degrees by using transpose(+) and reverse-each (|:'):

  |:'+t
(3 0
 4 1
 5 2)

So if we have a block of spaces t and a string s, we can prepend a slice of the tail of s to t:

  s: 12 18 17 8 9
12 18 17 8 9
  (,(-#t)#s),|:'+t
(8 9
 3 0
 4 1
 5 2)

We use the form 4 {[x] ... }/( ... ) to repeatedly apply a function to a tuple consisting of the string and the matrix we're building. Each time we do this rotate-and-concatenate step we also chop down the string.

edit:

Another idea is to try splitting the input string into the fragments we want at each rotation, which simplifies the main body of the program. Unfortunately this works out to be slightly longer at 56 bytes:

f:{`0:((y-2)#" "){|:'(,y),+x}/(+\(0,y[0 1 0]-2 1 1))_|x}

If there's a better way to calculate those split points I'm open to suggestions.

edit2:

Rearranging slightly lets me remove a pair of parentheses. 54 bytes!

f:{`0:((y-2)#" "){|:'(,y),+x}/(0,+\y[0 1 0]-2 1 1)_|x}
\$\endgroup\$
2
\$\begingroup\$

K, 80 68 bytes

f:{[s;y;n]`0:(,n#s),({s[(#s)-x+2],((n-2)#" "),s@n+x}'!y-2),,n#|-4!s}

Shortened from 80 thanks to @JohnE.

Original:

f:{s:x;n:z;`0:(,s@!n),({s[(#s)+-2-x],({" "}'!n-2),s@n+x}'!y-2),,(|s@!-4+#s)@!n}

I barely even know how this thing works.

Example usage:

f["Hello, world! ";5;4]

There are some possible optimizations, but I keep making Kona segfault...

\$\endgroup\$
  • \$\begingroup\$ You can improve this a bit by using 'take' (dyadic #) and an explicit argument list: f:{[s;y;n]`0:(,n#s),({s[(#s)-x+2],((n-2)#" "),s@n+x}'!y-2),,n#|-4!s}. 68 characters by my count. \$\endgroup\$ – JohnE Mar 15 '15 at 2:24
  • \$\begingroup\$ @JohnE Thanks! I knew about the explicit argument list, but it somehow slipped my mind; I had no clue about dyadic #, though. \$\endgroup\$ – kirbyfan64sos Mar 15 '15 at 18:32
2
\$\begingroup\$

R, 178

This is an unnamed function taking s, w, h as parameters. I wish there was a nicer way to split the string.

function(s,w,h){W=w+h-1;H=w+W-1;S=strsplit(s,'')[[1]];O=array(" ",c(h,w+1));O[,w+1]="\n";O[1:h,c(w,1)]=c(S[w:W],S[(W+W-1):H]);O=t(O);O[1:w,c(1,h)]=c(S[1:w],S[H:W]);cat(O,sep='')}

Ungolfed

W=w+h-1;                                 # additional index points
H=w+W-1;                                 # additional index points
S=strsplit(s,'')[[1]];                   # vectorize the string
O=array(" ",c(h,w+1));                   # create an array of spaces
O[,w+1]="\n";                            # set newlines
O[1:h,c(w,1)]=c(S[w:W],S[(W+W-1):H]);    # build middles lines
O=t(O);                                  # transpose array
O[1:w,c(1,h)]=c(S[1:w],S[H:W]);          # build top and bottom lines
cat(O,sep='')                            # cat out results

Test run

> (function(s,w,h){W=w+h-1;H=w+W-1;S=strsplit(s,'')[[1]];O=array(" ",c(h,w+1));O[,w+1]="\n";O[1:h,c(w,1)]=c(S[w:W],S[(W+W-1):H]);O=t(O);O[1:w,c(1,h)]=c(S[1:w],S[H:W]);cat(O,sep='')})("Hello, World! ",5,4)
Hello
    ,
!    
dlroW
> (function(s,w,h){W=w+h-1;H=w+W-1;S=strsplit(s,'')[[1]];O=array(" ",c(h,w+1));O[,w+1]="\n";O[1:h,c(w,1)]=c(S[w:W],S[(W+W-1):H]);O=t(O);O[1:w,c(1,h)]=c(S[1:w],S[H:W]);cat(O,sep='')})("+--+|||+--+|||",4,5)
+--+
|  |
|  |
|  |
+--+
> (function(s,w,h){W=w+h-1;H=w+W-1;S=strsplit(s,'')[[1]];O=array(" ",c(h,w+1));O[,w+1]="\n";O[1:h,c(w,1)]=c(S[w:W],S[(W+W-1):H]);O=t(O);O[1:w,c(1,h)]=c(S[1:w],S[H:W]);cat(O,sep='')})(">v<^",2,2)
>v
^<
> (function(s,w,h){W=w+h-1;H=w+W-1;S=strsplit(s,'')[[1]];O=array(" ",c(h,w+1));O[,w+1]="\n";O[1:h,c(w,1)]=c(S[w:W],S[(W+W-1):H]);O=t(O);O[1:w,c(1,h)]=c(S[1:w],S[H:W]);cat(O,sep='')})("rock beats scissors beats paper beats ",11,10)
rock beats 
          s
s         c
t         i
a         s
e         s
b         o
          r
r         s
epap staeb
> # Escaped the \ as well 
> (function(s,w,h){W=w+h-1;H=w+W-1;S=strsplit(s,'')[[1]];O=array(" ",c(h,w+1));O[,w+1]="\n";O[1:h,c(w,1)]=c(S[w:W],S[(W+W-1):H]);O=t(O);O[1:w,c(1,h)]=c(S[1:w],S[H:W]);cat(O,sep='')})("!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~",46,3)
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN
~                                            O
}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQP
> 
\$\endgroup\$
2
\$\begingroup\$

T-SQL, 307

While still horrendously long, this turned out to be quite a bit easier (and shorter) than I thought in a query. Implemented as an inline table valued function for T-SQL.

CREATE FUNCTION f(@S VARCHAR(MAX),@ INT,@H INT)RETURNS TABLE RETURN WITH R AS(SELECT 2i,LEFT(@S,@)S,STUFF(@S,1,@,'')+'|'R UNION ALL SELECT i+1,CASE WHEN i<@H THEN LEFT(RIGHT(R,2),1)+REPLICATE(' ',@-2)+LEFT(R,1)ELSE REVERSE(LEFT(R,@))END,STUFF(STUFF(R,LEN(R)-1,1,''),1,1,'')FROM R WHERE i<=@H)SELECT S FROM R

This recurses through the string @h times. First recursion clips @W characters from the string. The middle recursions take the last and first from remaining string with string padding between. The last recursion reverses what is left. There is a few lost characters dealing with the way SQL Server treats trailing spaces on VARCHARS.

Test Run

WITH TestSet AS (
    SELECT *
    FROM (VALUES
        ('Hello, World! ',5,4),
        ('+--+|||+--+|||',4,5),
        ('>v<^',2,2),
        ('rock beats scissors beats paper beats ',11,10),
        ('!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~andfoure',50,3)
        ) Test(S,W,H)
)
SELECT x.S 
FROM TestSet 
    CROSS APPLY (
        SELECT S FROM dbo.F(S,W,H)
        )x

S
----------------------------
Hello
    ,
!    
dlroW
+--+
|  |
|  |
|  |
+--+
>v
^<
rock beats 
          s
s         c
t         i
a         s
e         s
b         o
          r
r         s
epap staeb 
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR
e                                                S
ruofdna~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUT

(24 row(s) affected)
\$\endgroup\$
2
\$\begingroup\$

Pyth, 33 bytes

J-vw2<zQFkC,_z<>zQJj*-Q2dk;<>_zJQ

Demonstration.

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

MATLAB, 101

function f(H,W,S)
w=1:W;h=(0:H-3).';n=W+H-2;S(3*n)=' ';S([w;[2*n-h,3*n*ones(H-2,W-2),h+W+1];n-w+W+1])
\$\endgroup\$
1
\$\begingroup\$

C++, 398 bytes

Compiler used - GCC 4.9.2 with -std=c++14 flag

#include<bits/stdc++.h>
using namespace std;string s;vector<vector<char>> M;int w,h,p,i,j;void F(int x,int y){if(p<s.size()&&(((!y||y==h-1)&&x>=0&&x<w)||((!x||x==w-1)&&y>=0&&y<h))&&!M[y][x])M[y][x]=s[p++],F(x+1,y),F(x,y+1),F(x-1,y),F(x,y-1);}int main(){getline(cin,s);cin>>w>>h;M.resize(h,vector<char>(w,0));F(0,0);while(i<h){j=0;while(j<w){if(!M[i][j])M[i][j]=32;cout<<M[i][j++];}i++;cout<<endl;}}

Test it here.

Explanation

#include<bits/stdc++.h>
using namespace std;

string s; // input string
vector<vector<char>> M; // output matrix
int w, h, p, i, j;
// w = width
// h = height
// p = iterator over s
// i, j = iterators used later for printing answer

void F( int x, int y )
{
    // If the coordinates (x, y) are either on the first row/column or the last row/column and are not already populated with the input characters, populate them
    if ( p < s.size() && ( ( ( y == 0 || y == h - 1 ) && x >= 0 && x < w ) || ( ( x == 0 || x == w - 1 ) && y >= 0 && y < h ) ) && !M[y][x] )
    {
        M[y][x] = s[p++];
        F( x + 1, y );
        F( x, y + 1 );
        F( x - 1, y );
        F( x, y - 1 );
    }
}

int main()
{
    getline( cin, s );
    cin >> w >> h;
    // Input taken !!

    M.resize( h, vector<char>( w, 0 ) ); // Fill the matrix with null characters initially

    F( 0, 0 ); // This function does all the work

    // Now printing the matrix
    while ( i < h )
    {
        j = 0;
        while ( j < w )
        {
            if ( !M[i][j] )
            {
                M[i][j] = ' ';  // Replace '\0' with ' '
            }
            cout << M[i][j++];
        }
        i++;
        cout << endl;
    }

}
\$\endgroup\$
  • \$\begingroup\$ Couldn't you save characters by using char[][] instead? \$\endgroup\$ – corsiKa Mar 13 '15 at 23:20
  • \$\begingroup\$ No, vector<vector<char>> M;M.resize(h,vector<char>(w,0)); is slightly shorter than char** M;M=new char*[h];while(i<h)M[i++]=new char[w](); \$\endgroup\$ – Anmol Singh Jaggi Mar 14 '15 at 12:17
1
\$\begingroup\$

Perl, 193 195 bytes

($s,$w,$h,$i,$y)=(@ARGV,0,2);
$o.=substr$s,$i,$w;
$i+=$w;
$o.=sprintf"\n%s%*s",substr($s,2*($w+$h)-$y++-3,1)||' ',$w-1,substr($s,$i++,1)while$y<$h;
print$o."\n".reverse(substr($s,$i,$w))."\n";

I'm sure this can be greatly improved. I'm a noob. >,<

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

Java 11, 180 bytes

(s,w,h)->{var r=s.substring(0,w)+"\n";int i=w;for(var S=s.split("");i<w+h-2;)r+=S[3*w+2*h-i-5]+" ".repeat(w-2)+S[i++]+"\n";return r+new StringBuffer(s.substring(i,i+w)).reverse();}

Try it online (NOTE: String.repeat(int) is emulated as repeat(String,int) for the same byte-count, because Java 11 isn't on TIO yet.)

Explanation:

(s,w,h)->{               // Method with String & 2 int parameters and String return-type
  var r=s.substring(0,w)+"\n";
                         //  Result-String, starting at the the first row of output,
                         //  which is a substring in the range [0, `w`)
  int i=w;               //  Index-integer, starting at `w`
  for(var S=s.split(""); //  Split the input-String into a String-array of characters
      i<w+h-2;)          //  Loop `i` in the range [`w`, `w+h-2`)
    r+=                  //   Append the result-String with:
       S[3*w+2*h-i-5]    //    The character at index `2*w+2*h-4 - i+w-1`
       +" ".repeat(w-2)  //    Then append `w-2` amount of spaces
       +S[i++]           //    Then append the character at index `i`
       +"\n";            //    And a trailing new-line
  return r               //  After the loop, return `r` as result
         +new StringBuffer(s.substring(i,i+w)).reverse();
                         //  Appended with the last row of output,
                         //  which is a substring in the range [`i`, `i+w`) reversed
\$\endgroup\$
0
\$\begingroup\$

Charcoal, 4 bytes

BNNS

Try it online (verbose) or try it online (pure).

Explanation:

Basically a builtin for this challenge. Take the first two integer-inputs as width and height, and prints a box with the third input-string as border:

Box(InputNumber(), InputNumber(), InputString())
BNNS
\$\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.