How can I make this MiniZinc output statement compile? - output

How do I revise this to compile in MiniZinc:
output [[show (P[j,p]) ++ "\n" | p in 1 .. 4] | j in 1 .. 4];
I tried several ways.

It depends on what you want to do. Here are some different approaches that will write P as a matrix. The first one write the matrix as lists ([...]), the second one just outputs the values.
output [
show([P[j,p] | p in 1 .. 4]) ++ "\n"
| j in 1 .. 4
];
output [
if p = 1 then "\n" else " " endif ++
show(P[j,p])
| j in 1 .. 4, p in 1 .. 4
];
Update: In MiniZinc 2.0 (at least in a fairly recent Git version), there is now a show2d predicate:
output [ show2d(P)];

Related

Spread number equally across elements of array (and add remainder to beginning of ring)

Let's say I have some JSON array, we'll call it A:
["foo", "bar", "baz"]
And I have some number X, let's say 5 in this case.
I want to produce the following object in jq:
{
"foo": 2,
"bar": 2,
"baz": 1,
}
This is the number 5 divided up equally across the elements of the array, with the remainder being distributed to the elements at the beginning of the ring. You could maybe think of it this way, the value for element N should be ceil(X / length(A)) if index(N) < (X % length(A)), otherwise it should be floor(X / length(A)).
Assuming A is my file input to jq, and I have X defined as a variable, how can I express this in jq?
I have tried 'length as $len | .[] | if index(.) < (5 % $len) then (5 / $len) + 1 else 5 / $len end' | 5 as a starting point but I get 2 for each element.
You can use the transpose function to help build this. It's simpler with a ceil function, which we have to define ourselves. The mapping you are looking for from index to allocation is ceil($count - $i)/$n), where $count is the amount you are distributing, $i is the index in the original list, and $n is the length of the list.
Comments show how each piece works on your sample input of ["foo", "bar", "baz"].
def ceil(v): -(-v | floor);
def objectify(n): {key: .[0], value: ceil(($count - .[1])/n)};
# ["foo", 0] | objectify(3) -> {"key": "foo", "value", 2}
length as $n | # n == 3
[., keys] | # [["foo", "bar", "baz"], [0,1,2]]
[transpose[] | # [["foo", 0], ["bar", 1], ["baz", 2]]
objectify($n)
] |
from_entries # {"foo": 2, "bar": 2, "baz": 1}
Without the comments...
def ceil(v): -(-v | floor);
def objectify(n): {key: .[0], value: ceil(($count - .[1])/n)};
length as $n | [., keys] | [transpose[] | objectify($n)] | from_entries
An example of its use, assuming you saved it to file named distribute.jq:
jq --argjson count 5 -f distribute.jq tmp.json
I found a solution by saving the original input as a variable so that I can continue to reference it while operating on its values.
. as $arr
| length as $len
| [
.[]
| . as $i
| {
$(i): (
if ($arr | index($i)) < ($x % $len) then
($x / $len) + 1
else
$x / $len
end
| floor
)
}
]
| add
The following worked for me with passing --argjson count $X and feeding the array as my input.

error and output issues for python matrix?

I am building a function that takes a list made up of lists (ex: [['a'],['b'],['c']]) and outputs it as a table. I cannot use pretty table because I need a specific output (ex | a | b | ) with the lines and the spaces exactly alike.
Here is my function:
def show_table(table):
if table is None:
table=[]
new_table=""
for row in range(table):
for val in row:
new_table+= ("| "+val+" ")
new_table+= "|\n"
return new_table.strip("\n")
I keep getting the error:
show_table([['a'],['b'],['c']])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in show_table
TypeError: 'list' object cannot be interpreted as an integer
I'm not sure why there is an issue. I've also gotten an output error where it only outputs the first item in the first list and nothing more. Could someone explain how to use the format function to get rid of this error and output what I want correctly?
Fixed error but still failing tests:
FAIL: test_show_table_12 (main.AllTests)
Traceback (most recent call last):
File "testerl7.py", line 116, in test_show_table_12
def test_show_table_12 (self): self.assertEqual (show_table([['10','2','300'],['4000','50','60'],['7','800','90000']]),'| 10 | 2 | 300 |\n| 4000 | 50 | 60 |\n| 7 | 800 | 90000 |\n')
AssertionError: '| 10| 2| 300|\n| 4000| 50| 60|\n| 7| 800| 90000|' != '| 10 | 2 | 300 |\n| 4000 | 50 | 60 |\n| 7 | 800 | 90000 |\n'
- | 10| 2| 300|
+ | 10 | 2 | 300 |
? +++ +++ +++
- | 4000| 50| 60|
+ | 4000 | 50 | 60 |
? + ++ ++++
- | 7| 800| 90000|+ | 7 | 800 | 90000 |
? ++++ + + +
The problem is here:
for row in range(table):
range takes 1, 2, or 3 integers as arguments. It does not take a list.
You want to use:
for row in table:
Also, check your indents; it looks like the newline addition should be indented more.
Your traceback tells you that the problem occurs on line 5:
for row in range(table):
… so something on that line is trying, without success, to interpret something else as an integer. If we take a look at the docs for range(), we see this:
The arguments to the range constructor must be integers (either built-in int or any object that implements the __index__ special method).
… but table is not an integer; it's a list. If you want to iterate over a list (or something similar), you don't need a special function – simply
for row in range:
will work just fine.
There's another problem with your function apart from the misuse of range(), which is that you've indented too much of your code. This:
if table is None:
table=[]
new_table=""
for row in range(table):
for val in row:
new_table+= ("| "+val+" ")
new_table+= "|\n"
… will only execute any of the indented code if table is None, whereas what you really want is just to set table=[] if that is the case. Fixing up both those problems gives you this:
def show_table(table):
if table is None:
table=[]
new_table = ""
for row in table:
for val in row:
new_table += ("| " + val + " ")
new_table += "|\n"
return new_table.strip("\n")
(I've also changed all your indents to four spaces, and added spaces here and there, to improve the style).

Output Error for Matrix in Python?

I am trying to create a function that outputs a matrix that contains each item in a list on a separate line with lines in between. The only output I'm getting is quotations (''). I do not understand why. I think I set it all up correctly to output what is needed but there has to be something missing?
I included examples below my code.
def show_table(table):
table=[]
s=[[str(e) for e in row] for row in table]
lens= [max(map(len, col)) for col in zip(*s)]
fmt= '\t'.join('{{:{}}}'.format(x) for x in lens)
table= [fmt.format(*row) for row in s]
return '\n'.join(table)
show_table([['A','BB'],['C','DD']])
output:
'| A | BB |\n| C | DD |\n'
print(show_table([['A','BB'],['C','DD']]))
output:
| A | BB |
| C | DD |
The issue is on the second line where you are initialising your list to an empty list. Instead try:
if table is None:
table = []
Perhaps a better way to accomplish this could be:
def show_table(table):
if table is None:
table = []
data = ""
for row in table:
for val in row:
data += "| " + val + " "
data += "|\n"
return data.strip("\n")
print show_table([['a','bb'],['c','dd']])
Output:
| a | bb |
| c | dd |

Print multiple tcl lists in a uniform manner

I have a group of lists some with strings, some with numbers and some with both. All these lists have variable lengths. I would like to know what would be the best way to print it to a file so that they all have equal spacing between them.
For example, I use,
set numbers {0 1 2 3 4}
set type {dog reallybigbaddog thisisaevenlargersentence cat bird}
set paths {aaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ccc ddddddddddddddddd efgh}
puts $fid "NUMBERS\t\tTYPE\tPATHS"
foreach numbersval $numbers typeval $type pathsval $paths {
puts $fid "$numbersval\t\t$typeval\t$pathsval"
}
The result was,
NUMBERS TYPE PATHS
0 dog AAA
1 reallybigbaddog bbbbbbbbbbbbbbbbbbbbbbbb
2 thisisaevenlargersentence ccc
3 cat ddddddddddddddddd
4 bird efgh
I Tried using "format" based on one of the suggestions on this site but that resulted in a similar output, I guess we need a way to determining what the longest string is and cant arbitrarily use "\t"? Would appreciate any better suggestions.
For reference, this is how you could do it with struct::matrix and report:
package require struct::matrix
package require report
set nrows 5
set ncols 3
set npads [expr {$ncols + 1}]
struct::matrix m
m add rows $nrows
m add column {0 1 2 3 4}
m add column {dog reallybigbaddog thisisaevenlargersentence cat bird}
m add column {aaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ccc ddddddddddddddddd efgh}
m insert row 0 {NUMBERS TYPE PATHS}
report::report r $ncols
r data set [lrepeat $npads \t]
m format 2string r
(This uses only a fraction of the formatting power of report.) This method can handle values with spaces in them.
Result (there is a tab character to the left of the first column on each row, but it's lost in the formatting here.):
NUMBERS TYPE PATHS
0 dog aaa
1 reallybigbaddog bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
2 thisisaevenlargersentence ccc
3 cat ddddddddddddddddd
4 bird efgh
Documentation: expr, lrepeat, package, report package, set, struct::matrix package
In this case, I'd call out to column -t to do the work for me:
set all "NUMBERS TYPE PATHS\n"
foreach n $numbers t $type p $paths {
append all "$n $t $p\n"
}
set formatted [exec column -t << $all]
puts $formatted
NUMBERS TYPE PATHS
0 dog aaa
1 reallybigbaddog bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
2 thisisaevenlargersentence ccc
3 cat ddddddddddddddddd
4 bird efgh
A pure Tcl way to do this:
array set maxl {numbers 0 type 0 paths 0}
foreach l {numbers type paths} {
foreach e [concat $l [set $l]] {
if {[set len [string length $e]] > $maxl($l)} {
set maxl($l) $len
}
}
}
puts [format "%-*s %-*s %-*s" $maxl(numbers) NUMBERS $maxl(type) TYPE $maxl(paths) "PATH LISTS"]
foreach n $numbers t $type p $paths {
puts [format "%-*s %-*s %-*s" $maxl(numbers) $n $maxl(type) $t $maxl(paths) $p]
}

Code Golf: recognize ascii art boxes

Came up with this a while ago while doing some data structure work, though it'd make a good code golf: Given a two dimensional array of characters containing ascii art rectangles, produce a list of coordinates and sizes for the rectangles.
Any trivially convertable input or output format is fine (eg: char**, list of strings, lines on standard input; list of four ints, struct, fixed amount +/- for the size; etc).
Similarly, output need not be in any particular order.
You dont have to anything useful for invalid input or malformed rectangles, but you shouldnt to produce valid-looking coordinates for a rectangle that isnt in the input.
No two valid rectangles share a + (though + may appear not only as part of rectangle)
You can assume that all rectangles are at least 3x3: each side has a - or | in it.
Examples:
" "
" +-+ | "
" | | \-"
" +-+ "
(2,1;3,3)
"+--+ +--+"
"| | | |"
"+--+ +--+"
(0,0;4,3), (6,0;4,3)
" +---+ "
"->|...| "
" +---+ "
(2,0;5,3)
"+-+ +--+ +--+"
"| | | | | |"
"+-+ | | + -+"
" | | "
" +--+ +-+ "
" +--+ | "
" +--+ +-+ "
(0,0;3,3), (4,0;4,5) # (2,5;4,2) is fine, but not needed
Perl, 167 165 159 chars
(156 chars if you don't count slurping stdin to #a, just remove the last 3 chars and assign a list of strings representing your input to #a)
Gets input from stdin. Newlines not significant, added for readability. Notice the use of the +++ operator ;P
map{$l=$i++;while($c=/\+-+\+/g){$w=$+[0]-2-($x=$-[0]);
$c++while$a[$l+$c]=~/^.{$x}\|.{$w}\|/;
print"($x,$l;",$w+2,",$c)\n"if$a[$c+++$l]=~/^.{$x}\+-{$w}\+/}}#a=<>
Be liberal in what you accept version, 170 chars
map{$l=$i++;while($c=/\+-*\+/g){pos=-1+pos;$w=$+[0]-2-($x=$-[0]);
$c++while$a[$l+$c]=~/^.{$x}\|.{$w}\|/;
print"($x,$l;",$w+2,",$c)\n"if$a[$c+++$l]=~/^.{$x}\+-{$w}\+/}}#a=<>
Be conservative in what you accept version, 177 chars
map{$l=$i++;while($c=/\+-+\+/g){$w=$+[0]-2-($x=$-[0]);
$c++while$a[$l+$c]=~/^.{$x}\|.{$w}\|/;print
"($x,$l;",$w+2,",$c)\n"if$c>1&&$a[$c+++$l]=~s/^(.{$x})\+(-{$w})\+/$1v$2v/}}#a=<>
Commented version:
#a=<>; # slurp stdin into an array of lines
$l=0; # start counting lines from zero
map{ # for each line
while(/\+-+\+/g){ # match all box tops
$c=1; # initialize height
# x coordinate, width of box - sides
$w=$+[0]-2-($x=$-[0]);
# increment height while there are inner parts
# of a box with x and w coinciding with last top
# (look into next lines of array)
$c++ while $a[$l+$c]=~/^.{$x}\|.{$w}\|/;
# if there is a box bottom on line + height
# with coinciding x and w, print coords
# (after incrementing height)
print "($x,$l;",$w+2,",$c)\n"
if $a[$c+++$l]=~/^.{$x}\+-{$w}\+/
}
$l++ # line++
}#a
Mega test case:
+--+ +-+ +-+ +++ +---+ +-+ +-+-+ +-++-+
|SO| | | | | +++ |+-+| | | | | | | || |
+--+ +-+-+-+ +++ ||+|| +-+ +-+-+ +-++-+
| | |+-+| | |
+-+-+-+ +---+ +-+
| | | |
+-+ +-+
++ +-+ ++ +-+ +- + +--+ +--+ +--+
|| +-+ ++ +-+-+ | | | | | | |
++ | | | | | | | | |
+-+ +--+ + -+ +--+ +--+
Perl - 223 222 216
Golfed version (newlines not significant):
$y=0;sub k{$s=$-[0];"($s,%i;".($+[0]-$s).",%i)"}while(<>){while(/\+-+\+/g){
if(exists$h{&k}){push#o,sprintf k,#{$h{&k}};delete$h{&k}}else{$h{&k}=[$y,2]}}
while(/\|.+?\|/g){++${$h{&k}}[1]if exists$h{&k}}++$y}print"#o\n"
Older de-golfed version:
# y starts at line zero.
$y = 0;
# Abuse Perl's dynamic scoping rules
# to get a key for the hash of current rectangles,
# which indexes rectangles by x and width,
# and is also used as a format string.
sub k {
# The start of the current match.
$s = $-[0];
# $+[0] is the end of the current match,
# so subtract the beginning to get the width.
"($s,%i;" . ($+[0] - $s) . ",%i)"
}
# Read lines from STDIN.
while (<>) {
# Get all rectangle tops and bottoms in this line.
while (/\+-+\+/g) {
# If line is a bottom:
if (exists $h{&k}) {
# Add to output list and remove from current.
push #o, sprintf k, #{$h{&k}};
delete $h{&k}
# If line is a top:
} else {
# Add rectangle to current.
$h{&k} = [$y, 2]
}
}
# Get all rectangle sides in this line.
while (/\|.+?\|/g) {
# Increment the height of the corresponding
# rectangle, if one exists.
++${$h{&k}}[1] if exists $h{&k}
}
# Keep track of the current line.
++$y
}
# Print output.
print join", ",#o
Note that this does not handle junk vertical bars to the left of the rectangles, that is:
+--+ +--+
| | | | |
+--+ +--+
Will incorrectly yield a height of 2 for both. This is because the /\|.+?\|/g pattern starts searching from the beginning of the line. Anyone have a suggestion for how to fix this?
Ruby — 306 260 245 228 168
# 228 chars
g=->(s,u='-'){o=[];s.scan(/\+#{u}+\+/){o<<[$`,$`+$&].map(&:size)};o}
b=t.map{|i|i.split''}.transpose.map{|s|g[s*'','\|']}
(1...t.size).map{|i|i.times{|j|(g[t[i]]&g[t[j]]).map{|x,y|p [x,j,y-x,i-j+1]if(b[x]&b[y-1]&[[j,i+1]])[0]}}}
produces
[0, 0, 3, 3]
[4, 1, 4, 3]
[10, 3, 3, 3]
for t=
["+-+ +--+",
"| | +--+ | |",
"+-+ | | + -+",
" +--+ +-+ ",
" +--+ | | ",
" +--+ +-+ "]
Explanation:
# function returns info about all inclusions of "+---+" in string
# " +--+ +-+" -> [[2,5],[7,9]]
g=->(s,u='-'){o=[];s.scan(/\+#{u}+\+/){o<<[$`,$`+$&].map(&:size)};o}
# mapping transposed input with this function
b=t.map{|i|i.split''}.transpose.map{|s|g[s*'','\|']}
# earlier here was also mapping original input, but later was merged with "analyse"
# "analyse"
# take each pair of lines
(1...t.size).map{|i|i.times{|j|
# find horizontal sides of the same length on the same positions
(g[t[i]]&g[t[j]]).map{|x,y|
# make output if there are correct vertical sides
p [x,j,y-x,i-j+1]if(b[x]&b[y-1]&[[j,i+1]])[0]
}
}}
# yeah, some strange +/-1 magick included ,.)
And more straight-forward 168-chars solution!
t.size.times{|i|t[0].size.times{|j|i.times{|k|j.times{|l|p [l,k,j-l+1,i-k+1]if
t[k..i].map{|m|m[j]+m[l]}*''=~/^\+\+\|+\+\+$/&&t[i][l..j]+t[k][l..j]=~/^(\+-+\+){2}$/}}}}
JavaScript — 156 characters*
Also at http://jsfiddle.net/eR5ee/4/ (only click the link if using Firefox or Chrome) or http://jsfiddle.net/eR5ee/5/ (adapted to Safari and Opera):
var A = [
"+-+ +--+ +--+",
"| | | | | |",
"+-+ | | + -+",
" | | ",
" +--+ +-+ ",
" +--+ | ",
" +--+ +-+ "
]; // not counted
for(y=A.length;--y;)for(;m=/\+-*\+/g(A[y]);){
for(w=m[0].length,z=y;A[--z][x=m.index]+A[z][x+w-1]=="||";);
/^\+-*\+$/(A[z].substr(x,w))&&alert([x,z,w,y-z+1])}
Excluding newlines and whitespace characters, which are completely unnecessary.
Apparently, Firefox and Chrome retain the lastIndex of the first regex. It takes four more characters to keep Safari and Opera out of an infinite loop. To get Internet Explorer working, fourteen more characters would be needed to fix both the above and the error "Function expected." Apparently, "... a regular expression's exec method can be called... indirectly (with regexp(str))" (quoted from Mozilla documentation) does not apply to IE.
The code detects all rectangles 2x2 and larger if no rectangle's bottom touches any other rectangle's top or bottom or a plus or minus sign and none overlap.
The order of the numbers in each alert box (which corresponds to a rectangle) is left, top, width, height. The code does error out if a rectangle extends off the top, but all the coordinates needed have already been output (from specification: "You dont have to (sic) anything useful for invalid input or malformed rectangles...")
Since most major web browsers implement the canvas tag, in several more lines of code, drawing the detected rectangles on screen is possible. http://jsfiddle.net/MquqM/6/ works on all browsers except Internet Explorer and Opera.
Edit: eliminated an unnecessary variable assignment
Edit 2: avoid throwing errors with completely valid input (--y instead of y--), clarify the specific cases the code handles
C (204 186 Characters)
#include<stdio.h>
char H=7,W=14,*S =
"+-+ +--+ +--+"
"| | | | | |"
"+-+ | | + -+"
" | | "
" +--+ +-+ "
" +--+ | "
" +--+ +-+ ";
void main(){
#define F(a,r,t)if(*c==43){while(*(c+=a)==r);t}
char*c,*o,*e=S;while(*(c=e++))
F(1,45,F(W,'|',o=c;F(-1,45,F(-W,'|',c==e-1?
printf("%i,%i %i,%i\n",(c-S)%W,(c-S)/W,(o-c)%W+1,(o-c)/W+1):0;))))
}
The character count is the body of main(). This code will walk the string with e until it reaches the top-left corner of a potential rectangle. It will then check the edges with c and using o to keep track of the bottom-right corner.
Output of the program is:
0,0 3,3
4,0 4,5
2,5 4,2
Python 2.6 - 287 263 254
a = [
"+-+ +--+ +--+",
"| | | | | |",
"+-+ | | + -+",
" | | ",
" +--+ +-+ ",
" +--+ | ",
" +--+ +-+ "
]
l=len
r=range
w,h=l(a[0]),l(a)
[(x,y,u,v)for x in r(0,w)for y in r(0,h)for u in r(x+2,w)for v in r(y+2,h)if a[y][x]==a[v][x]==a[y][u]==a[v][u]=='+' and a[y][x+1:u]+a[v][x+1:u]=="-"*2*(u-x-1)and l([c for c in r(y+1,v-y)if a[c][x]==a[c][u]=='|'])==v-y-1]
evaluated to:
[(0, 0, 3, 3), (4, 0, 4, 5)]
Scala 2.8 - 283 273 269 257
val a = Seq(
"+-+ +--+ +--+",
"| | | | | |",
"+-+ | | + -+",
" | | ",
" +--+ +-+ ",
" +--+ | ",
" +--+ +-+ "
)
// begin golf count
val (w,h) = (a(0).size-1,a.size-1)
for (
x <- 0 to w;
y <- 0 to h;
u <- x+2 to w;
v <- y+2 to h;
if Set(a(y)(x),a(v)(x),a(y)(u),a(v)(u)) == Set(43)
&& (x+1 to u-1).forall(t => (a(y)(t)<<8|a(v)(t)) == 11565)
&& (y+1 to v-1).forall(t => (a(t)(x)<<8|a(t)(u)) == 31868)
) yield (x,y,u-x+1,v-y+1)
// end golf count
evaluates to :
Vector((0,0,3,3), (4,0,4,5))
The for expression evaluates to the answer (the Vector object), that is why I counted only this part (whitespaces removed). Let me know if this is the correct way to count.
How it works
The coordinates of all possible rectangles (actually, only >= 3x3) are generated by the for expression. These coordinates are filtered by looking for the +, - and | at the edges and corners of all rectangles (the if part of the for expression).
Python 2.6 (251 characters)
I come in a bit late, anyway, some fun. Python, using regular expressions. To save a print statement and stay shorter than Fredb219's this won't print anything if you run it as a script, but typing one line at a time in the interpreter it's gonna show the result. Not really solid, it won't handle nested boxes nor most cases more complex than the ones given by DavidX. Haven't done testing, but I think it's likely to show results in a wrong order if something "strange" occurs.
import re
l,a,o=s.index("\n")+1,re.finditer,sorted
o(o(set((m.start(),m.end())for m in a(r'\+-* *-*\+',s)for n in a(r'\|.+\|',s)if(m.start()%l,m.end()%l)==(n.start()%l,n.end()%l)if m.start()+l==n.start()or m.start()-l==n.start())),key=lambda x:x[0]%l)
Input is a single string, lines (all same length) separated by a newline character. Results are the string slices of the top and the bottom for every "good" box, starting top left. It also allows "broken" boxes (i.e. with some space in the middle of one side, not without one entire side). This was just a way to fix an unwanted behavior creating many brand new side effects! :-)
input:
>>>s = """+-+ +--+ +--+
| | | | | |
+-+ | | + -+
| |
+--+ +-+
+--+ |
+--+ +-+ """
or:
>>>s = "+-+ +--+ +--+\n| | | | | |\n+-+ | | + -+\n | | \n +--+ +-+ \n +--+ | \n +--+ +-+ "
then:
>>>import re
>>>l,a,o=s.index("\n")+1,re.finditer,sorted
>>>o(o(set((m.start(),m.end())for m in a(r'\+-* *-*\+',s)for n in a(r'\|.+?\|',s)if(m.start()%l,m.end()%l)==(n.start()%l,n.end()%l)if m.start()+l==n.start()or m.start()-l==n.start())),key=lambda x:x[0]%l)
output:
[(0, 3), (30, 33), (4, 8), (64, 68), (10, 14), (40, 44)]
so (0,3) top of 1st box (30,33) bottom of same box, (4,8) top of 2nd box and so on.
F#, 297 chars
Kinda lame, but simple.
let F a=
for x=0 to Array2D.length1 a-1 do
for y=0 to Array2D.length2 a-1 do
if a.[x,y]='+' then
let mutable i,j=x+1,y+1
while a.[i,y]<>'+' do i<-i+1
while a.[x,j]<>'+' do j<-j+1
printfn"(%d,%d;%d,%d)"x y (i-x+1)(j-y+1)
a.[i,y]<-' '
a.[x,j]<-' '
a.[i,j]<-' '
Look for a plus. Find the one to the right of it. Find the one below it. Print out this rectangle's info, and 'null out' the pluses we already used. Since each plus is only a part of one valid rectangle, that's all we need to do.
XQuery (304 characters)
Here is my solution:
declare variable $i external;let$w:=string-length($i[1]),$h:=count($i)for$y in 1 to$h,$x in 1 to$w,$w in 2 to$w+1 -$x,$h in 1 to$h where min(for$r in (0,$h),$s in 1 to$h return (matches(substring($i[$y+$r],$x,$w),'^\+-*\+$'),matches(substring($i[$y+$s],$x,$w),'^|.*|$')))return ($x -1,$y -1,$w,$h+1,'')
You can run this (with XQSharp) by setting the variable $i to be the lines of the input
>XQuery boxes.xq "i=(' +-+','+-+-+','| | ','+-+ ')" !method=text
2 0 3 2 0 1 3 3
I suppose one could argue that declare variable $i external; is just setting up the input and so doesn't add to the count, in which case 275 characters