title: 1P5: Nested boxes

text:
# Question
Title: 1P5: Nested boxes
*This task is part of the First Periodic Premier Programming Puzzle Push.*

You get a hierarchy of items in the following format:

```
2
Hat
1
Gloves

```

which need to be put in boxes, like so:

```
.------------.
| Hat        |
| .--------. |
| | Gloves | |
| '--------' |
'------------'

```

In the input format the numbers start a box with as many items as the number specifies. The first box has two items in it (the Hat and the box that contains the Gloves), the second one only contains a single item – the gloves.

As can be seen, boxes can live inside boxes, too. And they are always rounded ... sort of (pointy corners are a wound hazard and we wouldn't want that).

*Below there are the nasty details for those that want to utilize every tiny bit of leeway the specification gives. Mind you, not reading the spec is no excuse for submitting wrong solutions. There is a test script and a few test cases at the very end.*

---

**Specification**

* Boxes are constructed from the following characters:

+ `|` (U+007C) is used to construct the vertical edges.
    + `-` (U+002D) is used to construct the horizontal edges.
    + `'` (U+0027) are the round lower corners.
    + `.` (U+002E) are the round upper corners.

A box therefore looks like this:

```
.--.
|  |
'--'

```

<sub>*Note that while Unicode also has round corners and proper box-drawing characters, this task is in ASCII only. As much as I love Unicode I realize that there are languages and environments out there that didn't quite arrive in the second to last decade.*</sub>
* Boxes can contain a sequence of items that are either text or other items. Individual items in a box are rendered from top to bottom. The sequence A, B, C thus renders as follows:

```
.---.
| A |
| B |
| C |
'---'

```

This of course applies to nested boxes too, which are an item just like text. So the sequence A, B, Box(C, Box(D, E)), F would render as follows:

```
.-----------.
| A         |
| B         |
| .-------. |
| | C     | |
| | .---. | |
| | | D | | |
| | | E | | |
| | '---' | |
| '-------' |
| F         |
'-----------'

```
* Boxes adjust their size to the content and nested boxes always extend to the size of their parent. There is always a space before and after the content, so that neither text nor nested boxes are too close to the outer box' edge. In short, the following is wrong:

```
.---.
|Box|
'---'

```

And the following is correct:

```
.-----.
| Box |
'-----'

```

Looks much nicer, too :-)
* Text items (see *Input* below) have to be reproduced exactly.
* There is always a single top-level box (cf. XML). However, one box can contain several other boxes.

**Input**

* Input is given on standard input; for easier testing likely redirected from a file.
* The input is given line-wise, with each line representing either a text item to put in the current box or opening a new box.
* Every line is terminated by a line break.
* Text items are marked by a line that does not consist of a number (see below). Text uses alphabetic characters, the space and punctuation (`.,-'"?!()`). Text will not start or end with a space and it will always have at least one character.
* A box starts with a single line with a number in it. The number tells the size of the box, i.e. the number of following items that are put into it:

```
2
A
B

```

yields a box with two text items:

```
.---.
| A |
| B |
'---'

```

A box will always contain at least one item.
* The end of boxes is not explicitly marked with a line; instead boxes are implicitly closed after the specified number of items are put into them.
* A box is always just a single item, regardless how many items are in it. E.g.

```
3
A
4
a
b
c
d
B

```

will yield a box with three items, the second of which is another box with four items.

Nesting also does not affect the fact that a box is just a single item.

**Limits**

* The maximum nesting level is **five**. I.e. there are at most five boxes inside of each other. This includes the outermost one.
* There is a maximum of **ten** items per box.
* Text items have a maximum length of **100** characters.

**Output**

* Output is the rendered box including all containing and nested items according to the rules outlined above.
* Output should be given on standard output and it has to match exactly. No leading or trailing whitespace is allowed.
* Each line must be terminated with a line break, including the last.

**Winning condition**

* Shortest code wins (i.e. gets the accepted answer).

**Sample input 1**

```
3
This is some text!
Oh, more text?
Just text for now, as this is a trivial example.

```

**Sample output 1**

```
.--------------------------------------------------.
| This is some text!                               |
| Oh, more text?                                   |
| Just text for now, as this is a trivial example. |
'--------------------------------------------------'

```

**Sample input 2**

```
4
Extreme
nesting
3
of
boxes
4
might
lead
to
2
interesting
1
visuals.
Indeed!

```

**Sample output 2**

```
.--------------------------.
| Extreme                  |
| nesting                  |
| .----------------------. |
| | of                   | |
| | boxes                | |
| | .------------------. | |
| | | might            | | |
| | | lead             | | |
| | | to               | | |
| | | .--------------. | | |
| | | | interesting  | | | |
| | | | .----------. | | | |
| | | | | visuals. | | | | |
| | | | '----------' | | | |
| | | '--------------' | | |
| | '------------------' | |
| '----------------------' |
| Indeed!                  |
'--------------------------'

```

**Sample input 3**

```
1
1
1
1
1
Extreme nesting Part Two

```

**Sample output 3**

```
.------------------------------------------.
| .--------------------------------------. |
| | .----------------------------------. | |
| | | .------------------------------. | | |
| | | | .--------------------------. | | | |
| | | | | Extreme nesting Part Two | | | | |
| | | | '--------------------------' | | | |
| | | '------------------------------' | | |
| | '----------------------------------' | |
| '--------------------------------------' |
'------------------------------------------'

```

**Sample input 4**

```
3
Foo
2
Bar
Baz
2
Gak
1
Another foo?

```

**Sample output 4**

```
.----------------------.
| Foo                  |
| .------------------. |
| | Bar              | |
| | Baz              | |
| '------------------' |
| .------------------. |
| | Gak              | |
| | .--------------. | |
| | | Another foo? | | |
| | '--------------' | |
| '------------------' |
'----------------------'

```

**Test Script**

Since getting details right can be difficult at times we (Ventero and me) have prepared a test script you can run your solution with to check whether it's correct. It's available as both a PowerShell script and a bash script. Invocation is: `<test-script> <program invocation>`.

**UPDATE:** *The test scripts have been updated; there were a number of test cases that did not honor the limits I defined. The PowerShell test script did not use case-sensitive comparison for checking the result. I hope everything is fine now. The number of test cases was reduced to 156, although the last one now is quite ... large.*

**UPDATE 2:** *I uploaded my test-case generator. Written in C#, targeting the .NET 2 runtime. It runs on Mono. It may help people to test their implementation. As a definitive worst-case given the limits in the task you can try:*

```
nb.exe 1 10 10 5 100 100 | my invocation

```

*which will generate only boxes up to the innermost level and utilize both the maximum number of items per box and the maximum length of text items. I didn't include this test case into the test script, though, since it's quite large and the output even larger.*

**UPDATE 3:** *I updated the PowerShell test script which was prone to throw errors depending on how the line endings were in the script and what line endings the solution printed. Now it should be agnostic to both. Sorry again for the confusion.*

# Answer
### GolfScript, 125 characters

```
n/):B;[(~{[B"."+"""-"]B"| "+:B;@@{(.10,`-{[B\" "]\}{~A}if}*B[2>:B"'"+"""-"]\}:A~;].{~;1$++,}%$-1=:§;{~§3$.+3$+,-*+1$-1%++}%n*

```

Using a similar approach as Keith's solution.
> 2 votes

# Answer
## Python, 204 chars

```
def P(n):x=raw_input();return eval('[(n+".","","-")]'+'+P(n+"| ")'*int(x))+[(n+"'",'','-')]if'0'<x<':'else[(n,x,' ')]
r=P('')
for q,t,f in r:print q+t+f*(max(len(2*x+y)for x,y,a in r)-len(2*q+t))+q[::-1]

```

`P` returns a list of triples, each of which is a line prefix/suffix (the suffix being the reverse of the prefix), some line text, and a line fill character. After calculating all the triples, they are printed using the right number of fill characters to make all the lines the same length.

Ungolfed version:

```
def get_lines(prefix):
  line=raw_input()
  result=[]
  if line.isdigit():
    result.append((prefix+'.', '', '-'))
    for i in xrange(int(line)):
      result += get_lines(prefix + '| ')
    result.append((prefix+"'", '', '-'))
  else:
    result.append((prefix, line, ' '))
  return result
lines=get_lines('')
width=max(2*len(prefix)+len(text) for prefix,text,fill in lines)
for prefix,text,fill in lines:
  print prefix+text+fill*(width-2*len(prefix)-len(text))+prefix[::-1]

```
> 26 votes

# Answer
## Ruby 1.9, 174 characters

```
r=->l{$*<<(l*2+i=gets.chop).size;/\d/?eval('[l+?.,p=?-,p,'+'*r["| "+l],'*i.to_i+"l+?',p,p]"):[l,i,?\s]}
r[""].each_slice(3){|a,b,c|puts a+b+c*($*.max-(a*2+b).size)+a.reverse}

```

Somewhat similar to Keith's solution.
> 13 votes

# Answer
## APL (78)

```
{∧/⎕D∊⍨I←⍞:{∆,('-'⍪⍵⍪'-'),∆←'.|'''/⍨1(⊃⍴⍵)1}⍕⍪/{⍵↑[2]⍨⌈/⊃∘⌽∘⍴¨∆}¨∆←∇¨⍳⍎I⋄⍉⍪I}⍬

```
> 6 votes

# Answer
## Python - 355 314 259 chars

```
w=0
def p(n,l):
 global w;f=[(l-1,0)]
 for k in' '*n:
  i=raw_input()
  try:f+=p(int(i),l+1)
  except:f+=[(l,i)];w=max(w,4*l+len(i))
 return f+[(l-1,1)]
for l,s in p(input(),1):p=w-4*l-2;print'| '*l+(".'"[s]+'-'*p+".'"[s]if s<2 else s+' '*(p+2-len(s)))+' |'*l

```
> 5 votes

# Answer
## C, 390 366 363 characters

```
#define F(n)for(int i=n;i--;)
#define H(n,s,a...)F(n)printf(s);printf(a);
#define I(s)H(v,"| ",s)H(l-2,"-",s)J
#define J H(v," |","\n")
S[1<<17][26],N[1<<17],P,a;E(p){int l=strlen(gets(S[p]));if(sscanf(S[p],"%d",N+p))F(N[p])l<(a=E(++P))?l=a:l;return l+4;}R(p,v,l){if(N[p]){I(".")F(N[p])R(++P,v+1,l-4);I("'")}else{H(v,"| ","%-*s",l,S[p])J}}main(){R(P=0,0,E(0)-4);}

```

Compile with `gcc -std=gnu99 -w file.c`

Not even close to Keith's version, but hey, it's good ol' C
> 5 votes

# Answer
## Ruby 1.9, 229 228 226 223 222

```
g=->n{(1..n).map{g[Integer l=gets.chop]rescue l}}
w=->b{b.bytesize rescue b.map{|e|w[e]}.max+4}
p=->b,c{r=c-2
[?.+?-*r+?.,*b.map{|i|p[i,c-4]}.flatten.map{|k|"| #{k} |"},?'+?-*r+?']rescue[b.ljust(c)]}
puts p[b=g[1][0],w[b]]

```
> 5 votes

# Answer
## Haskell, 297 characters

```
f§(a,b)=(f a,b)
h c=(c,'-',c)
b l=h".":map(\(p,f,q)->("| "++p,f,q++" |"))l++[h"'"]
y[]s z=([(s,' ',"")],z)
y[(n,_)]_ z=b§foldr(\_(l,w)->(l++)§x w)([],z)[1..n]
x(a:z)=y(reads a)a z
m(p,_,q)=length$p++q
n®a@(p,c,q)=p++replicate(n-m a)c++q++"\n"
o(l,_)=l>>=(maximum(map m l)®)
main=interact$o.x.lines

```

While golf'd, the method is pretty straight forward. Only limits are available memory.
> 4 votes

# Answer
very functional python, 460 characters

```
r=range
s=lambda x:isinstance(x,str)
w=lambda x:reduce(max,[len(i)if s(i)else w(i)+4 for i in x])
z=lambda b,x:''.join(b for i in r(x))
def g(n=1):
 t=[]
 for i in r(n):
  x=raw_input('')
  try:t+=[g(int(x))]
  except:t+=[x]
 return t
o=list.append
def y(c,m):
 f='| ';h=' |';e=z('-',m+2);a='.'+e+'.';b="'"+e+"'";t=[a]
 for i in c:
  if s(i):o(t,f+i+z(' ',m-len(i))+h)
  else:[o(t,f+j+h)for j in y(i,m-4)]
 return t+[b]
x=g()[0];m=w(x);print '\n'.join(y(x,m))

```
> 4 votes

# Answer
## C# -1005 859 852 782 characters

```
using c=System.Console;using System.Linq;class N{static void Main(){new N();}N(){var i=R();c.WriteLine(i.O(0,i.G().W));}I R(){var s=c.ReadLine();int l=0,i=0;if(int.TryParse(s,out l)){var b=new I(l);for(;i<l;){b.m[i++]=R();}return b;}else{return new I(0,s);}}class P{public int W;public int H;}class I{public I[]m;bool z;string t;public I(int l,string r=""){z=l!=0;m=new I[l];t=r;}public P G(){var s=new P();if(z){var d=m.Select(i=>i.G());s.W=d.Max(y=>y.W)+4;s.H=d.Sum(y=>y.H)+2;}else{s.W=t.Length;s.H=1;}return s;}public string O(int l,int w){if(z){string s=A(l,"."+"-".PadRight(w-2,'-')+"."),e=s.Replace(".","'");foreach(var i in m){s+="\n"+i.O(l+1,w-4);}s+="\n"+e;return s;}else{return A(l,t.PadRight(w));}}}static string A(int l,string o){while(l-->0){o= "| "+o+" |";}return o;}}

```

I need to take another look at this as I'm sure it can be improved, but this is my initial go third pass at it.

Ungolf'd:

```
using c=System.Console;
using System.Linq;

class NestedBoxes
{
    static void Main()
    {
        new NestedBoxes();
    }
    NestedBoxes()
    {
        var item = ReadItem();
        c.WriteLine(item.Print(0, item.GetSize().Width));
    }
    Item ReadItem()
    {
        var line = c.ReadLine();
        int count = 0, i = 0;
        if (int.TryParse(line, out count))
        {
            var box = new Item(count);
            for (; i < count;)
            {
                box.items[i++] = ReadItem();
            }
            return box;
        }
        else
        {

            return new Item(0,line);
        }
    }
    class Size
    {
        public int Width;
        public int Height;
    }
    class Item
    {
        public Item[] items;
        bool isBox;
        string text;
        public Item(int size,string word="")
        {
            isBox = size != 0; items = new Item[size]; text = word;
        }
        public Size GetSize()
        {
            var s = new Size();
            if (isBox)
            {
                var sizes = items.Select(i => i.GetSize());
                s.Width = sizes.Max(y => y.Width) + 4; s.Height = sizes.Sum(y => y.Height) + 2;
            }
            else
            {
                s.Width = text.Length;
                s.Height = 1;
            }
            return s;
        }
        public string Print(int level, int width)
        {
            if (isBox)
            {
                string output = AddLevels(level, "." + "-".PadRight(width - 2, '-') + "."),
                        bottomLine = output.Replace(".", "'");
                foreach (var item in items)
                {
                    output += "\n" + item.Print(level + 1, width - 4);
                }
                output += "\n" + bottomLine;
                return output;
            } else {return AddLevels(level, text.PadRight(width)); }
        }
    }
    static string AddLevels(int level, string output)
    {
        while(level-->0)
        {
            output = "| " + output + " |";
        }
        return output;
    }
}

```
> 4 votes

# Answer
# PHP, 403 388 306 chars

```
<?b((int)fgets(STDIN),'');foreach($t as $r)echo$r[0].str_pad($r[2],$w-2*strlen($r[0]),$r[1]).strrev($r[0])."\n";function b($c,$p){global$t,$w;$t[]=array($p.".","-");while($c--){if(($d=trim(fgets(STDIN)))>0)b($d,"| ".$p);else$t[]=array("| ".$p," ",$d);$w=max($w,strlen($d.$p.$p)+4);}$t[]=array($p."'","-");}

```

Ungolfed:

```
box((int)fgets(STDIN), '');

foreach($table as $row) {
    $prefix = $row[0];
    $pad = $row[1];
    $data = $row[2];
    echo $prefix . str_pad($data, ($width - 2*strlen($prefix)), $pad) . strrev($prefix)."\n";
}

function box($count,$prefix) {
    global $table, $width;
    $table[] = array($prefix.".","-");
    while($count--) {
        if(($data = trim(fgets(STDIN))) > 0) {
            box($data, "| ".$prefix);
        } else {
            $table[] = array("| ".$prefix, " ", $data);
        }
        $width = max($width,strlen($data.$prefix.$prefix)+4);
    }
    $table[] = array($prefix."'","-");
}
?>

```

I borrowed the prefix-idea from Keith (is that allowed at all?), otherwise this is pretty much as the original. Still couldn't get below 300. Stuck with this. Onwards.
> 4 votes

# Answer
## PHP, 806 769 721 653 619 chars

```
<?php function A($a,$b,$c,&$d){for($e=$b;$e>0;$e--){$f=fgets($a);if(false===$f){return;}$g=intval($f);if(0<$g){$h[]=A($a,$g,$c+1,$d);}else{$f=trim($f);$h[]=$f;$j=strlen($f)+4*$c;if($d<$j){$d=$j;}}}return $h;}$d=0;$h=A(STDIN,intval(fgets(STDIN)),1,&$d);function B($k,$c,$d){$f=str_pad('',$d-4*$c-2,'-',2);return C($k.$f.$k,$c,$d);}function C($f,$c,$d){$f=str_pad($f,$d-4*$c,' ');$f=str_pad($f,$d-2*$c,'| ',0);$f=str_pad($f,$d,' |');return $f;}function D($l,$c,$d){if(!is_array($l)){echo C($l,$c,$d)."\n";return;}echo B('.',$c,$d)."\n";foreach($l as $m){echo D($m,$c+1,$d);}echo B('\'',$c,$d)."\n";}D($h,0,$d);exit(0);?>

```

Ungolfed version:

```
<?php
function read_itemgroup($handle, $item_count, $depth, &$width) {

    //$items = array();

    for($i = $item_count; $i > 0; $i--) {
        $line = fgets( $handle );
        if(false === $line) {
            return;
        }

        $line_int = intval($line);
        if(0 < $line_int) {
            // nested group
            $items[] = read_itemgroup($handle, $line_int, $depth + 1, $width);
        }
        else {
            // standalone item
            $line = trim($line);
            $items[] = $line;

            // determine width of item at current depth
            $width_at_depth = strlen($line) + 4 * $depth;
            if($width < $width_at_depth) {
                $width = $width_at_depth;
            }
        }
    }

    return $items;
}
$width = 0;
$items = read_itemgroup(STDIN, intval(fgets( STDIN )), 1, &$width);

//var_dump($items, $width);

function render_line($corner, $depth, $width) {
    $line = str_pad('', $width - 4 * $depth - 2, '-', 2); // 2 = STR_PAD_BOTH
    return render_item($corner . $line . $corner, $depth, $width);
}

function render_item($line, $depth, $width) {
    $line = str_pad($line, $width - 4 * $depth, ' ');
    $line = str_pad($line, $width - 2 * $depth, '| ', 0); // 0 = STR_PAD_LEFT
    $line = str_pad($line, $width, ' |');
    return $line;
}

function render($item, $depth, $width) {
    if(!is_array($item)) {
        echo render_item($item, $depth, $width) . "\n";
        return;
    }
    echo render_line('.', $depth, $width) . "\n";
    foreach($item as $nested_item) {
        echo render($nested_item, $depth + 1, $width);
    }
    echo render_line('\'', $depth, $width) . "\n";
}

render($items, 0, $width);

exit(0);
?>

```
> 3 votes

# Answer
# Java - 681 668 chars

```
import java.util.*;public class b{static int m,h,i;public static void main(String[]a)throws Throwable{for(Object o:z("")){a=(String[])o;String s=a[0]+a[1];i=a[0].length();for(h=0;h<m-i*2-a[1].length();h++){s+=a[2];}for(h=i;h>0;h--){s+=a[0].charAt(h-1);}System.out.println(s);}}static List z(String p)throws Throwable{String b="",d="";List l=new ArrayList();while((i=System.in.read())>-1){if(10==i){if(d!=""){String[]v={p+".",b,"-"},t={p+"'",b,"-"};l.add(v);for(int u=0;u<Integer.parseInt(d);u++){l.addAll(z(p+"| "));}l.add(t);}else{h=b.length()+p.length()*2;if(m<h)m=h;String[]v={p,b," "};l.add(v);}break;}else if(i>47&&i<58){d+=(char)i;}else {b+=(char)i;}}return l;}}

```

essentially the same method as Keith Randall's Python code

Ungolfed version:

```
import java.util.*;

public class b {
    static int m, h, i;

    public static void main(String[] a) throws Throwable {
        for (Object o : z("")) {
            a = (String[]) o;
            String s = a[0] + a[1];
            i = a[0].length();
            for (h = 0; h < m - i * 2 - a[1].length(); h++) {
                s += a[2];
            }
            for (h = i; h > 0; h--) {
                s += a[0].charAt(h - 1);
            }
            System.out.println(s);
        }
    }

    static List z(String p) throws Throwable {
        String b = "", d = "";
        List l = new ArrayList();
        while ((i = System.in.read()) > -1) {
            if (10 == i) {
                if (d != "") {
                    String[] v = { p + ".", b, "-" }, t = { p + "'", b, "-" };
                    l.add(v);
                    for (int u = 0; u < Integer.parseInt(d); u++) {
                        l.addAll(z(p + "| "));
                    }
                    l.add(t);
                } else {
                    h = b.length() + p.length() * 2;
                    if (m < h)
                        m = h;
                    String[] v = { p, b, " " };
                    l.add(v);
                }
                break;
            } else if (i > 47 && i < 58) {
                d += (char) i;
            } else {
                b += (char) i;
            }
        }
        return l;
    }
}

```
> 3 votes

# Answer
## Perl - 200 199 chars

Same algorithm as Keith Randall's Python (nice design, Keith), but a tiny bit more compact in this Perl take on it.

```
sub P{$_=<>;chop;$m>($l=length"$_@_@_")or$m=$l;/^\d/?(["@_.","","-"],(map{P("| @_")}1..$_),["@_'","","-"]):["@_",$_," "]}map{($q,$t,$f)=@$_;print"$q$t",($f x($m-length"$q$t$q")).reverse($q),"\n"}(P);

```
> 3 votes

# Answer
## F# - 341 characters

```
let rec f(x,y)=[
 let l=stdin.ReadLine()
 let q,d=Core.int.TryParse l
 if q then
  yield x+".","",'-',"."+y
  for i=1 to d do yield!f(x+"| ",y+" |")
  yield x+"'","",'-',"'"+y
 else yield x,l,' ',y]
let l=f("","")
for w,x,y,z in l do printfn"%s"(w+x.PadRight(List.max(l|>List.map(fun(w,x,y,z)->2*w.Length+x.Length))-2*w.Length,y)+z)

```

An F# version of Keith's solution. Lists are immutable by default, so this version stuffs the entire recursive function into a list, returns the list, from which the items are extracted using the `for..do` loop and a `yield!`. I couldn't find a way to reverse the prefix concisely, so I just attached the suffix onto the triples.

FYI, the TryParse method returns a double `(bool,int)`.
> 3 votes

# Answer
# Clojure - 480 chars

```
(use '[clojure.contrib.string :only (repeat)])(let [r ((fn p[%](repeatedly % #(let [x (read-line)](try(doall(p(Integer/parseInt x)))(catch Exception e x))))) 1)]((fn z[m,n,o] (let[b #( let[p(dec o)](println(str(repeat p "| ")%(repeat(- m(* 4 p)2)"-")%(repeat p " |"))))](b \.)(doseq[i n](if(seq? i)(z m i(inc o))(println(str(repeat o "| ")i(repeat(- m(count i)(* o 4))" ")(repeat o " |")))))(b \')))((fn w[x](reduce max(map(fn[%](if(seq? %)(+ (w %)4)(count %)))x)))r)(first r) 1))

```

This is my first Clojure program as well as my first Clojure golf attempt, so, needless to say, this shouldn't be taken as representative of Clojure solutions in general. I'm sure it could be shortened significantly, especially if Keith Randall's method of parsing and building the boxes at once was implemented.
> 2 votes

# Answer
## Scala - 475 characters

```
object N2 extends App{type S=String;def b(x:List[S],t:Int,s:S,e:S):List[S]={var l=x;o=o:+(s+".-±-."+e+"-");for(i<-1 to t)if(l.head.matches("\\d+"))l=b(l.tail,l.head.toInt,s+"| ",e+" |")else{o=o:+(s+"| "+l.head+"±"+e+" | ");l=l.drop(1)};o=o:+(s+"'-±-'"+e+"-");return l};var o:List[S]=List();val l=io.Source.stdin.getLines.toList;b(l.tail,l.head.toInt,"","");(o map(x=>x.replaceAll("±",x.last.toString*((o sortBy((_:S).length)).last.length-x.length)).dropRight(1)))map println}

```
> 2 votes

# Answer
## C# - 472 470 426 422 398 characters

```
using System.Linq;using y=System.Console;class W{static void Main(){var c=new int[5];var s=new string[0].ToList();int n=0,i;var l="";do{try{c[n]=int.Parse(l=y.ReadLine());l=".{1}.";n++;i=1;}catch{l+="{0}";i=0;}G:while(i++<n)l="| "+l+" |";s.Add(l);if(n>0&&--c[n-1]<0){n--;l="'{1}'";i=0;goto G;}}while(n>0);s.ForEach(z=>y.WriteLine(z,l="".PadLeft(s.Max(v=>v.Length)-z.Length),l.Replace(' ','-')));}}

```
> 2 votes

# Answer
## C# 1198 1156 1142 689 671 634 Characters

```
using z=System.Console;using System.Collections.Generic;using System.Linq;
class T{bool U;List<T> a=new List<T>();string m;IEnumerable<string>R(int s){if(U){yield return ".".PadRight(s-1,'-')+".";foreach(var e in a.SelectMany(b=>b.R(s-4)))yield return ("| "+e).PadRight(s-e.Length)+" |";yield return "'".PadRight(s-1,'-')+"'";}else yield return m;}int L(){return U?a.Max(x=>x.L())+4:m.Length;}
static void Main(){var p=O(int.Parse(z.ReadLine()));z.WriteLine(string.Join("\r\n",p.R(p.L())));}
static T O(int n){var k=new T(){U=true};while(n-->0){var l=z.ReadLine();int c;k.a.Add(int.TryParse(l,out c)?O(c):new T{m=l});}return k;}}

```
> 1 votes

# Answer
# Java (1369 chars incl. EOLs)

Couldn't leave this without a Java implementation. Java is supposed to be more verbose that the slicks of Python and Ruby, so I went for an elegant, recursive solution.

The idea is a Tree (Graph) of objects (strings and boxes), containing one another starting from a "head" box. As you linearly parse the input file you add strings and boxes to the "current" box and while you are adding the maximum length of the container is adjusted. When a container reaches the amount of predefined items that it can hold you backtrack to the previous container. At the end of the input file, you have a "head" container that already has a "maxLength" calculated, so you simply call its print() method.

```
import java.io.*;import java.util.*;
public class N{private static String rPad(String s,int l){return s+str(l-s.length(),' ');}
private static String str(int l, char c){StringBuffer sb=new StringBuffer();while(l-->0){sb.append(c);}return sb.toString();}
private static class Box {Box prnt=null;String txt=null;int items;List<Box> c=new ArrayList<Box>();int maxLength=0;
public Box(Box p,int n){prnt=p;items=n;if(p!=null){p.c.add(this);}}
public Box(Box p,String s){prnt=p;txt=s;if(p!=null){p.c.add(this);p.notify(s.length());}}
public void print(String prefix,int l,String suffix){if (txt == null){System.out.println(prefix+"."+str(l-2,'-')+"."+suffix);for(Box b:c){b.print(prefix+"| ",l-4," |"+suffix);}System.out.println(prefix+"'"+str(l-2,'-')+"'"+suffix);}else{System.out.println(prefix+rPad(txt,l)+suffix);}}
protected void notify(int l){if (l+4>this.maxLength){this.maxLength=l + 4;if (this.prnt != null){this.prnt.notify(this.maxLength);}}}}
public static void main(String[] args)throws IOException{Box head=null;Box b=null;BufferedReader in=new BufferedReader(new InputStreamReader(System.in));String s;while ((s=in.readLine()) != null){try{int n=Integer.parseInt(s);b=new Box(b, n);}catch (NumberFormatException nfe){b=new Box(b, s);}if(head == null)head=b;while ((b != null) && (b.items == b.c.size())){b=b.prnt;}}head.print("",head.maxLength,"");}}

```

It is really an enjoyable solution to write. I liked the question a lot. As I mentioned earlier, I went for solution elegance not minimalist approach, sadly Java doesn't have Python's print "-"\*4 to produce "----" :-)

Here's the ungolfed version:

```
import java.io.*;
import java.util.*;

public class NestedBoxes
{

    private static String rPad ( String s, int l )
    {
        return s + str(l - s.length(), ' ');
    }

    private static String str ( int l, char c )
    {
        StringBuffer sb = new StringBuffer();
        while (l-- > 0)
        {
            sb.append(c);
        }
        return sb.toString();
    }

    private static class Box
    {

        Box parent = null;
        String text = null;
        int items;
        List<Box> contents = new ArrayList<Box>();

        int maxLength = 0;

        public Box ( Box p, int n )
        {
            parent = p;
            items = n;
            if (p != null)
            {
                p.contents.add(this);
            }
        }

        public Box ( Box p, String s )
        {
            parent = p;
            text = s;
            if (p != null)
            {
                p.contents.add(this);
                p.notify(s.length());
            }
        }

        public void print ( String prefix, int l, String suffix )
        {
            if (text == null)
            {
                System.out.println(prefix + "." + str(l - 2, '-') + "." + suffix);
                for (Box b : contents)
                {
                    b.print(prefix + "| ", l - 4, " |" + suffix);
                }
                System.out.println(prefix + "'" + str(l - 2, '-') + "'" + suffix);
            }
            else
            {
                System.out.println(prefix + rPad(text, l) + suffix);
            }
        }

        protected void notify ( int l )
        {
            if (l + 4 > this.maxLength)
            {
                this.maxLength = l + 4;
                if (this.parent != null)
                {
                    this.parent.notify(this.maxLength);
                }
            }
        }
    }

    public static void main ( String[] args ) throws IOException
    {
        Box head = null;
        Box b = null;
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String s;
        while ((s = in.readLine()) != null)
        {
            try
            {
                int n = Integer.parseInt(s);
                b = new Box(b, n);
            }
            catch (NumberFormatException nfe)
            {
                b = new Box(b, s);
            }

            if (head == null)
            {
                head = b;
            }

            while ((b != null) && (b.items == b.contents.size()))
            {
                b = b.parent;
            }
        }
        head.print("", head.maxLength, "");
    }
}

```
> 0 votes

# Answer
## Pip, 89 bytes (non-competing)

<sup>(The language is newer than the challenge. Also, I couldn't quite outgolf APL.)</sup>

Code is 87 bytes, +2 for `-rn` flags.

```
(z:{I+YPOi{Y{Vz}M,ym:MX#*Y$ALyY'|.s._.sX++m-#_.'|MyY".."J'-X++mALyAL"''"J'-Xm}yALl}i:g)

```

Try it online!

The function `z` processes the first item of the input list (`g`, copied into global variable `i` so as to be available inside function calls). If this is a number *n*, it calls itself recursively *n* times, pads the resulting list of lines to a full rectangle, wraps each line in `"| " " |"`, and adds `.---.` and `'---'` lines before returning the new list. If it is a string, it simply converts it to a one-item list and returns it. The final result is printed newline-separated (`-n` flag). More detail available on request.
> 0 votes

---
Tags: code-golf, ascii-art, 1p5
---


title: Decipher Neurotic Frogs

text:
# Question
Title: Decipher Neurotic Frogs
# Decipher Neurotic Frogs

Now that Puzzling.SE has finally cracked my amphibian-obsessed cipher, let's write a program or function to decrypt it!

**(If you want to look at the puzzle before having it spoiled for you, click the above link now.)**

---

### How the cipher works

In Neurotic Frogs *O*ught To Rel*a*x In *M*ud Baths ("Neurotic Frogs" for short), every letter is encrypted as one or two words:

* The length of a non-italicized word represents a letter.
    + `neurotic` =\> 8 letters =\> `H`
    + `frogs` =\> 5 letters =\> `E`
    + `perpendicular` =\> 13 letters = `M`
* A word that contains italics modifies the following word, adding 10 if the italicized word was odd in length or 20 if the italicized word was even in length. Any or all of the word may be italicized. An italicized word is always followed by a non-italicized word.
    + `*o*ught to` =\> odd, 2 =\> 12 =\> `L`
    + `lo*u*nging calms` =\> even, 5 =\> 25 =\> `Y`

Every word of plaintext corresponds to a sentence of ciphertext, and every sentence of plaintext corresponds to a paragraph of ciphertext.

### Input format

Your program or function shall input a message in Neurotic Frogs, formatted in Markdown. The input will consist only of printable ASCII and newlines.

* *Words* are runs of characters that match the regex `[A-Za-z0-9']`.
    + Numbers and letters both count toward the length of a word. `QB64` represents `D`.
    + NOTE: Apostrophes *do not count* toward the length of a word. `Isn't` represents `D`, not `E`.
* *Italicized letters* are wrapped in a pair of asterisks (`*letters*`).
    + One or more consecutive letters may be italicized, up to an entire word (`masseus*es*`, `*all*`); multiple non-consecutive letters in a word may also be italicized (`g*e*n*e*rates`).
    + Italics never span multiple words, never include punctuation, and never include apostrophes.
    + Unpaired asterisks and multiple adjacent asterisks will never occur.
* *Punctuation* is any of the following characters: `.,?!:;-()"`.
    + Words within a sentence are separated by one or more punctuation characters *and/or* a single space. Examples: `*all* welcomed`, `toad*s*, newts`, `Ever*y*one--frogs`, `cap... bliss`, `they're (I`
    + Sentences end with one or more punctuation characters and are separated by a double space: `Th*e* Montgomery A*m*phibian Salon! Come luxuriate today!`
    + Paragraphs are separated by a single newline. (The last sentence of a paragraph still has one or more punctuation characters at the end.)

Other characters will not appear in input and do not need to be handled.

Your code may, at your discretion, expect input to have a single trailing newline.

### Output format

The result of decrypting the input will be one or more sentences. Letters of plaintext may be any combination of upper- and lowercase. Words within a sentence must be separated by single spaces. Sentences must end with a period (`.`) and be separated by a single space. You may output a trailing space after the last sentence. Your output will all be on one line, but you may output a trailing newline.

### Miscellaneous details

Your code may use any of the standard input and output methods. It must receive input as a multiline string, not a list or other data structure, and it must output a string.

The shortest code in bytes wins!

### Test cases

```
-->
Neurotic Frogs *O*ught To Rel*a*x In *M*ud Baths!
<--
HELLO.

-->
Business standards all*o*w only *adult* amphibians.
<--
HINT.

-->
Rejoice, *a*ll frogs an*d* toads also!  Montgomery Sal*o*n opens up!  Ha*pp*y throng fill*s* street ecstatically!
<--
GOOD JOB PPL.

-->
I like 3.1415926535897.
IM*O*, it's a *b*la*st*, yeah!
<--
ADAM. MAN.

-->
*I*, happily, *th*anks 2 u *e*ditin*g* specific wor*ding*--clarifying a *bit*--betterment :D!
<--
QUARTATA.

-->
Perpendicular l*ou*nging calms.  *A* frog, a m*u*d cap... bliss!  Wallowing g*e*n*e*rates happiness.  Amphibian sp*a* isn't expensive--seventy d*o*llars--cheap!  That'*s* not *a* large e*x*pens*e* from an*y* discerning fr*o*g's money, unlik*e* Super 8.
Ever*y*one--frogs, toad*s*, newts, *a*nd salamanders!  G*e*t a wonderful shiat*s*u, or recei*v*e an other kind.  Masseus*es* are her*e* today!  Invite a fianc*e*e, supervisor, roommate, niece: *all* welcomed!
Y*o*u simply ne*v*er believed these p*o*ssibilitie*s*; they're (I *swear*) absolute truth!  Th*e* Montgomery A*m*phibian Salon!  Come luxuriate today!
<--
MY NAME IS INIGO MONTOYA. YOU KILLED MY FATHER. PREPARE TO DIE.

```

# Answer
# Perl, 72 bytes

```
#!perl -n
$x=/\*/?2-y/'//c%2:!print/ /?$':chr$x.0+y/'//c+64for/[\w*']+|  /g,' . '

```

Counting the shebang as one, input is taken from stdin.

**Sample Usage**

```
$ more in.dat
Neurotic Frogs *O*ught To Rel*a*x In *M*ud Baths!
Perpendicular l*ou*nging calms.  *A* frog, a m*u*d cap... bliss!  Wallowing g*e*n*e*rates happiness.  Amphibian sp*a* isn't expensive--seventy d*o*llars--cheap!  That'*s* not *a* large e*x*pens*e* from an*y* discerning fr*o*g's money, unlik*e* Super 8.
Ever*y*one--frogs, toad*s*, newts, *a*nd salamanders!  G*e*t a wonderful shiat*s*u, or recei*v*e an other kind.  Masseus*es* are her*e* today!  Invite a fianc*e*e, supervisor, roommate, niece: *all* welcomed!
Y*o*u simply ne*v*er believed these p*o*ssibilitie*s*; they're (I *swear*) absolute truth!  Th*e* Montgomery A*m*phibian Salon!  Come luxuriate today!

$ perl neurotic-frogs.pl < in.dat
HELLO. MY NAME IS INIGO MONTOYA. YOU KILLED MY FATHER. PREPARE TO DIE.

```
> 6 votes

# Answer
# JavaScript (ES6), ~~172~~ ~~169~~ ~~157~~ 150 bytes

*Saved 10 bytes thanks to @Neil*

```
x=>x.match(/[\w'*]+|\s+/g).map(y=>y[0]==" "?y[1]:y==`
`?". ":/\*/.test(y,l+=y.match(/\w/g).length)?(l=l%2*10+19,""):l.toString(36,l=9),l=9).join``+"."

```

Can probably be further improved. Outputs in all lowercase.
> 4 votes

# Answer
# Pip, ~~65~~ 64 bytes

The score is 62 bytes of code + 2 for the `-rs` flags.

```
Flg{O{{(zy*t+#a-1)X!Y'*Na&2-#a%2}MJa@`[\w*]+`}MlRM''^sX2O". "}

```

Try it online!

### Explanation

The `-r` flag reads all lines of stdin and stores a list of them in `g`. The `-s` flag sets the output format of lists to space-separated.

The easiest way to read this code is from the outside in:

```
Flg{...}                   For each line l in g, do:

O{...}MlRM''^sX2O". "      Translate a paragraph into a sentence of plaintext:
       lRM''               Remove apostrophe characters
            ^sX2           Split on "  " into sentences
 {...}M                    Map the below function to each sentence
O                          Output the result list, space-separated, without newline
                O". "      Output that string, without newline

{...}MJa@`[\w*]+`          Translate a sentence into a word of plaintext:
       a@`[\w*]+`          Find all matches of regex (runs of alphanumeric and *)
{...}MJ                    Map the below function to each word and join into string

(zy*t+#a-1)X!Y'*Na&2-#a%2  Translate a word into a letter of plaintext:
      #a-1                 Length of word minus 1
  y*t+                     Add 10 or 20 if y is set (see below)
(z        )                Use that number to index into lowercase alphabet
              '*Na&        Count * characters in word, logical AND with...
                   2-#a%2  2 if word is even length, 1 if odd
             Y             Yank that value into y, to modify the following word
           X!              String multiply the character by not(y)
                           If y is truthy, the word had italics, and we get ""
                           If y is falsy, the word had no italics, and we get a letter

```
> 4 votes

# Answer
# Python 2, ~~238~~ ~~221~~ ~~218~~ ~~214~~ ~~207~~ 205 bytes

```
from re import*
def f(x):
 d='';m=0
 for w in split(r"[^\w\d*'~\n]+",sub('  ','~',x))[:-1]:l=len(sub("[*'~\n]",'',w));q='*'in w;d+='. '[w[0]>'}':]*(w[0]in'~\n')+chr(64+l+m)[q:];m=(2-l%2)*10*q
 print d+'.'

```

Uses lots of regex to do the processing. We transform the double-space into `~` and use that to process it. `~` and `\n` are handled specially.

The biggest character gain comes from the preprocessing of the input in the `for` line; this can definitely be golfed further.

Ideone it! (all test cases)

*Saved 7 bytes thanks to DLosc!*
> 3 votes

# Answer
# PHP, ~~231~~ ~~226~~ 228 bytes

for a start

```
<?preg_match_all("#([\w\*']+)([^\w\*']*)#",$argv[1],$m,2);foreach($m as list(,$a,$b)){$e=strlen(strtr($a,["'"=>""]))+$d;if(!$d=strstr($a,'*')?$e%2*10:0)echo chr($e+64),strpos(".$b","
")?". ":(strpos(".$b","  ")?" ":"");}echo".";

```

Save to file, rund `php <scriptpath> <text>`. Escape newlines in the text to make it work in shell.
> 1 votes

# Answer
# Python 2.7, ~~390~~ ~~342~~ ~~341~~ ~~339~~ 335 bytes:

```
from re import*
def F(i):
 W=X="";S,s=split,sub;D='[^\w\s*]';Q=lambda c,t:len(s(D,X,c.group()).split()[t])
 for m in S('\W\n',s(D+"*\w*\*\w+\*.*?(?=\s) \w+",lambda v:"a"*([20,10][Q(v,0)%2]+Q(v,1)),s("'",X,s("--"," ",i)))):
  for g in S('\W  ',m):
   for q in S('\W',g):
    W+=chr(64+len(q))
   W+=" "
  W=W[:-1]+". "
 print s("@",X,W)

```

Takes input in the format:

`F('''Multi or Single-lined String''')`

Can be golfed down a lot more, which I will do whenever I get the chance.

Repl.it with All Test Cases!

## Explanation:

Uses the immense power of Python's regular expression built-ins to decipher the input. This is the fundamental process the function goes through for each input:

1. Firstly, all `--` are replaced with a single space, and every apostrophe is removed. Then, all words containing italicized components and the word proceeding it are both matched in one string and replaced with `10 + len(second word)` number of consecutive `a`s if the length of the first word is `odd`, and `20 + len(second word)` consecutive `a`s otherwise. This makes use of the following regular expression:

`[^\w\s*]*\w*\*\w+\*.*?(?=\s) \w+`

For example, if we have the sentence `Perpendicular l*ou*nging calms.`, `l*ou*nging calms` will be replaced with `aaaaaaaaaaaaaaaaaaaaaaaaa`, or 25 `a`s, since `l*ou*nging` has an even number of characters and `calms` has 5. `20+5=25`.
2. Now, the newly modified input is split at each punctuation mark followed by a newline (`\n`) to get the paragraphs, then each paragraph is split at each punctuation followed by 2 spaces to get the sentences, and finally, each sentence is split into words along any punctuation including a space. Then, for each word (including the runs of consecutive `a`s), we add on to a string `W` the letter corresponding to the unicode code point `64` (the unicode code point of the character before `A`, which is `@`) plus `len(word)`. We then add a single space to `W` once all the words of a sentence have been exhausted, and when all the sentences in a paragraph are exhausted, we add a `.` followed by a single space.
3. Finally, after the entire input has been gone through, `W` is output to `stdout` as the deciphered message.
> 1 votes

# Answer
# PHP, 196 Bytes

```
<?preg_match_all("#[\w*']+|  |$#m",$_GET[s],$m);foreach($m[0]as$s){if(!$s||$s=="  ")echo!$s?". ":" ";else{$l=$p+64+strlen(str_replace("'","",$s));if(!$p=strstr($s,"*")?20-$l%2*10:0)echo chr($l);}}

```

If I could assume that there is only one Apostrophe in the middle of a word 194 Bytes

```
<?preg_match_all("#[\w*]+(<?=')[\w*]+|[\w*]+|  |$#m",$_GET[s],$m);foreach($m[0]as$s){if(!$s||$s=="  ")echo!$s?". ":" ";else{$l=$p+64+strlen($s);if(!$p=strstr($s,"*")?20-$l%2*10:0)echo chr($l);}}

```
> 1 votes

---
Tags: code-golf, string, cryptography
---