tcl error "expected floating point number but got" - tcl

I am using tcl with the OpenSees program (see this question). One command offered by OpenSees in TCL is block2D and its syntax is as follows:
block2d $nx $ny $e1 $n1 element elementArgs {
1 $x1 $y1 <$z1>
2 $x2 $y2 <$z2>
3 $x3 $y3 <$z3>
4 $x4 $y4 <$z4>
}
In my specific case I am doing the following:
#geometric parameters
set nx 4
set ny 2
set elwidth 1.0
set elheight 1.0
set blockwidth [expr $nx*$elwidth]
set blockheight [expr $ny*$elheight]
block2D $nx $ny 1 1 quad "1 PlaneStrain2D 1" {
1 0.0 0.0
2 $blockwidth 0.0
3 4.0 2.0
4 0.0 2.0
}
Where the variables used in the block2D command are set in the beginning. Unfortunately when I run this script I get the following error:
WARNING block2D numX? numY? startNode? startEle? eleType? eleArgs?: invalid node coordinate for node: 1
expected floating-point number but got "$blockwidth"
I don't understand why this is happening. Other OpenSees commands allow for passing in variables. Why would this one be any different?
I have already tried different variants and nesting of the expr and eval commands on the blockwidth variable... All to no avail ...

The problem is that you've asked for an unsubstituted literal in this command:
block2D $nx $ny 1 1 quad "1 PlaneStrain2D 1" {
1 0.0 0.0
2 $blockwidth 0.0
3 4.0 2.0
4 0.0 2.0
}
That's what being in {braces} actually means. Which would be fine except you want a substitution in it. There are several sensible ways to do this:
Use a "double-quoted" word
block2D $nx $ny 1 1 quad "1 PlaneStrain2D 1" "
1 0.0 0.0
2 $blockwidth 0.0
3 4.0 2.0
4 0.0 2.0
"
Use the subst command
block2D $nx $ny 1 1 quad "1 PlaneStrain2D 1" [subst {
1 0.0 0.0
2 $blockwidth 0.0
3 4.0 2.0
4 0.0 2.0
}]
Use list to build the list
block2D $nx $ny 1 1 quad "1 PlaneStrain2D 1" [list \
1 0.0 0.0 \
2 $blockwidth 0.0 \
3 4.0 2.0 \
4 0.0 2.0 \
]
This third option is probably the best in terms of performance, but the second is probably more readable (despite being slowest), especially if you don't like using multi-line “strings” like the first option.

Related

how drop near zero terms in Octave symbolic

In this post I describe a symbolic computation I'm doing in Matlab that results in some terms remarkably small, near zero. I can run the same code in Octave (after loading the symbolic engine with pkg load symbolic in command window) and get the same results.
syms Zaa Zab Zac Zba Zbb Zbc Zca Zcb Zcc;
Z = [Zaa Zab Zac; Zba Zbb Zbc; Zca Zcb Zcc]
a = -1/2+sqrt(3)/2*1i;
A = [1 1 1; 1 a^2 a; 1 a a^2];
Z012 = inv(A)*Z*A
Is there a way to tell Octave to make those near-zero values actually zero?
Sample result: Zaa*(1/3 + i/36028797018963968)
Would like rounded to: Zaa*(1/3)
Update 1: My other post on this issue in Matlab has been answered - the solution being to use sqrt(sym(3)) in the a equation instead of just sqrt(3). That solution doesn't work in Octave however. If I run the code below in Octave I get the error blurb shown at bottom.
Code:
syms Zaa Zab Zac Zba Zbb Zbc Zca Zcb Zcc;
Z = [Zaa Zab Zac; Zba Zbb Zbc; Zca Zcb Zcc]
a = -1/2+sqrt(sym(3))/2*1i; % the sym(3) helps as
A = [1 1 1; 1 a^2 a; 1 a a^2];
Z012 = inv(A)*Z*A
vpa(3*Z012,2) % to clean up the display (remember to put a 1/3 factor in front of result)
Here is the resulting error blurb:
Symbolic pkg v3.0.0: Python communication link active, SymPy v1.10.1.
Z = (sym 3x3 matrix)
[Zaa Zab Zac]
[ ]
[Zba Zbb Zbc]
[ ]
[Zca Zcb Zcc]
warning: passing floating-point values to sym is dangerous, see "help sym"
warning: called from
double_to_sym_heuristic at line 50 column 7
sym at line 379 column 13
plus at line 53 column 5
symbolic_similarity_transformation at line 11 column 3
error: octave_base_value::map_value(): wrong type argument 'scalar'
Final update: This code runs in both Octave and Matlab and gives identical results.
syms Zaa Zab Zac Zba Zbb Zbc Zca Zcb Zcc;
Z = [Zaa Zab Zac; Zba Zbb Zbc; Zca Zcb Zcc]
a = -1/2+sqrt(sym(3))/2*1i;
A = [[1 1 1]; 1 a^2 a; 1 a a^2];
Z012 = inv(A)*Z*A
vpa(3*Z012,2) % to clean up the display (remember to put a 1/3 factor in front of result)
If a row contains all non-sym entries then you need to define such a row as a row vector to concatenate it with sym rows. i.e. A should be this:
A = [[1 1 1]; 1 a^2 a; 1 a a^2]; %works in both Octave and MATLAB
% ↑ ↑

Creating a list of first elements from a list of lists in tcl

Say I have a list like this: {{1 2 3} {4 5 6} {7 8 9}} and I'd like to create a new list made of the first element of each of the nested list: {1 4 7}. I Know how to do that in a couple of lines using 'foreach', but is that a more elegant way or, better yet, a built-in function that does that?
If you're using Tcl 8.6 then there's lmap command which does mapping of a list and can be used for your task:
%set a {{1 2 3} {4 5 6} {7 8 9}}
{1 2 3} {4 5 6} {7 8 9}
%lmap x $a {lindex $x 0}
1 4 7
The lmap command iterates through the list $a, assigns the currently processing list item to a given variable (x in the example) and calls a command (lindex $x 0 in te example).
As you know that you want to search the first element , so that is optimum solution for you to use foreach. The Complexity will be in your case O(1). As you just need to access the first value on index which is fixed.
As an alternative to using [lmap]/[lindex], re-formulate the problem to one on a flattened, but regular list. That is, accessing the nth (1st, 2nd, ...) element after having flattened the input list of lists:
set a {{1 2 3} {4 5 6} {7 8 9}}
set A [concat {*}$a]; # flattened list: {1 2 3 4 5 6 7 8 9}
lmap {pick drop drop} $A {set pick}
Depending on the layout of the input list, however, the [lmap]/[lindex] tactic is likely to outrun the above.

How to get the nodes in red color with tcl script in NS2

I want to get which of the nodes are in red , so i have this script that do not execute.
for {set i 0} { $i < $14 } {incr i } {
if {$ns at 0.0 "$n($i) color red"}{
return $n($i)
}
}
I am get this error:
Error: missing close-blace: possible unbalanced brace in comment while executing.
How can I solve the problem?
This line has two syntactic problems, one of which is causing the problem you currently have and one which will crop up as soon as you fix it. You need a space after the close brace in order to separate the expression word from the body word — Tcl cares about having spaces in critical places — and calls to commands inside if conditions need to be enclosed in square brackets.
if {$ns at 0.0 "$n($i) color red"}{
The minimal fix that might work is:
if {[$ns at 0.0 "$n($i) color red"]} {
I suspect that this won't work because the command doesn't give a boolean value, but until you add the brackets and a space it definitely won't work.
Lots of color settings to experiment with in e.g. ns-2.35/tcl/ex/wpan/wpan_demo5.tcl
Finding examples : cd [folder-with-examples.tcl] && grep -n "color red" *
AODV examples with red nodes: { aodv10ms.tcl, aodv10nodes.tcl, SoniaLamba-aodv.tcl } → aodv-examples-06.17.tar.gz .... aodv10nodes.tcl snippet :
# Provide initial location of mobile nodes
$node_(0) set X_ 50.0
$node_(0) set Y_ 1.0
$node_(0) set Z_ 0.0
$node_(0) shape box
$node_(0) color red
$ns_ at 0.0 "$node_(0) shape box"
$ns_ at 0.0 "$node_(0) color red"
$ns_ at 0.5 "$node_(0) setdest 50.0 499.0 10.0"
All ~2000 examples are here.

Octave leasqr only doing one iteration

As I'm trying to fit a function to some experimental data, I've written a function with three inputs, three parameters and one output:
qrfunc = #(x, p) exp(-1*p(1)*x(:,1) - p(2)*x(:,2))+p(3)*x(:,3)+20;
When I generate some input and output values:
pS = [0.5; 0.3; 0.3];
x1 = [1 1 1; 1 1.1 1; 1 1.1 1.1; 2 1.2 2];
y1 = qrfunc(x1, pS);
And call the leasqr function:
pin =[1; 1; 1];
[f1, p1, kvg1, iter1, corp1, covp1, covr1, stdresid1, Z1, r21] = leasqr(x1, y1, pin, qrfunc, 0.0001);
This works correct, the function makes 7 iterations and provides the right outputs.
But when I load x1 from my experimental data (a text file with three columns, about 1500 lines) as well as my y1 (a text file with the same amount of lines) and run the same function, it only makes one iteration, and does not change the parameters.
It even shows that the error margins are very high:
sqrt(diag(covp1))
ans =
3.0281e+004
3.7614e+005
1.9477e-002
What am I doing wrong? There are no error messages, no 'Convergence not achieved' or anything like that...
Edit:
The data is loaded with the command:
load "input.txt"
load "output.txt"
Proof of loading:
size(input)
ans =
1540 3
The first few lines from my input file:
10 0.4 5
20 0.4 5
30 0.4 5
40 0.4 5
50 0.4 5
The second and third parameters have different values further down the line.

Code Golf: Spider webs

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
The challenge
The shortest code by character count to output a spider web with rings equal to user's input.
A spider web is started by reconstructing the center ring:
\_|_/
_/ \_
\___/
/ | \
Then adding rings equal to the amount entered by the user. A ring is another level of a "spider circles" made from \ / | and _, and wraps the center circle.
Input is always guaranteed to be a single positive integer.
Test cases
Input
1
Output
\__|__/
/\_|_/\
_/_/ \_\_
\ \___/ /
\/_|_\/
/ | \
Input
4
Output
\_____|_____/
/\____|____/\
/ /\___|___/\ \
/ / /\__|__/\ \ \
/ / / /\_|_/\ \ \ \
_/_/_/_/_/ \_\_\_\_\_
\ \ \ \ \___/ / / / /
\ \ \ \/_|_\/ / / /
\ \ \/__|__\/ / /
\ \/___|___\/ /
\/____|____\/
/ | \
Input:
7
Output:
\________|________/
/\_______|_______/\
/ /\______|______/\ \
/ / /\_____|_____/\ \ \
/ / / /\____|____/\ \ \ \
/ / / / /\___|___/\ \ \ \ \
/ / / / / /\__|__/\ \ \ \ \ \
/ / / / / / /\_|_/\ \ \ \ \ \ \
_/_/_/_/_/_/_/_/ \_\_\_\_\_\_\_\_
\ \ \ \ \ \ \ \___/ / / / / / / /
\ \ \ \ \ \ \/_|_\/ / / / / / /
\ \ \ \ \ \/__|__\/ / / / / /
\ \ \ \ \/___|___\/ / / / /
\ \ \ \/____|____\/ / / /
\ \ \/_____|_____\/ / /
\ \/______|______\/ /
\/_______|_______\/
/ | \
Code count includes input/output (i.e full program).
Perl, 164 chars
195 184 171 167 164
print#o=((map{$z=_ x($x=1+$N-$_);$"x$x." /"x$_."\\$z|$z/".'\ 'x$_.$/}0..($N=<>)),
"_/"x++$N." ".'\_'x$N.$/);
y'/\\'\/',#o||y#_# #,$t++||y#_ # _#,print while$_=pop#o
First statement prints out the top half of the spider web. Second statement uses transliteration operations to create a reflection of the top half.
This next one weighs in closer to 314 chars (of productive code), but is more in the spirit of the season.
; "
Tr Ic
K| |t
Re aT
", "H
av e
A: -
)H AL LO W
ee N" ," En
jo y_ Yo ur
_ C&& y"; ##
&I (); $N= 1+
<>; $,= $/;#O =(( map
$" x($ X=$N-$_). ${ f}x$_.$
B.${U}x$X.$P.${U}x$X.$
F.${b}x$_,0..$N-1),${g}x$N.(${S}
x3).${c}x$N);sub I{($F,$B,$U, $P)
=qw (/ \\ _ |);; ${
S}= " ";$f=$S.$F;$g=$ U.
$F ;$b=$B.$S;$c=$B.${U};}#{ P}=
#{ O}; while($_=pop#{P} ){ #{
P} || y:_: :;$spooky++ || 0|
0 || y#_ # _#;y:/:8:; ; ;
; ;; y:\\:/:;y:8:\\:; #O =
( #O ,$_);}print#O; q{
Do !Discuss:Rel ig
io n,Politi cs
,& &T
heG rea
tP ump
ki n}
Hat tip to http://www.ascii-art.de/ascii/s/spider.txt
I constructed the spider shaped code by hand, but see the Acme::AsciiArtinator module on CPAN for help with automating (or at least semi-automating) the task.
Golfscript - 124 chars
All whitespace is significant! If you accidently add a newline to the end there will be an extra _ at the end of the output
~):#,{#\:&-:0' ': *& '/':/+*'\\':~'_':
0*.'|':|\/~ +&*n}%
/+#* ~
+#*n ~+#*
#/ +*n#,{):& *#&-:( ~+*/[
](!=&*.|\~/ +(*n}%
Golfscript - 129 chars
~):#,{#\:&-:0' ': *&' /'*'\\':~'_':
0*.'|'\'/'~ +&*n}%'_/'#* '\_'#*n ~+#*
#'/ '*n#,{):& *#&-:( ~+*'/'[
](!=&*.'|'\~'/ '(*n}%
Golfscript - 133 chars
~):#,{#\:&-:0' ': *&' /'*'\\':~'_':
0*.'|'\'/'~ +&*n}%'_/'#*3 *'\_'#*n' \\'#*3
*#'/ '*n#,{):& *#&-:( ~+*'/''_ '1/(!=&*.'|'\~'/ '(*n}%
Python - 212 chars
n=input()+1;b,f,p,u,s='\/|_ '
a=[s*(n-i)+' /'*i+b+u*(n-i)+p+u*(n-i)+f+'\ '*i+s*(n-i)for
i in range(n)]
print"\n".join(a+['_/'*n+s*3+'\_'*n,' \\'*n+u*3+'/ '*n]+[x[::-1]for
x in a[:0:-1]]+[a[0][::-1].replace(u,s)])
Perl: 161 characters
Note that this code includes the starting web in the source. (The doubled backslash at the end is a shame. An earlier version didn't have that.)
$_='
\_|_/
_/ \_
\___/
/_|_\\';
for$x(1..<>){
s|(.\S).*([/\\].)|$1$&$2|g;
s|\\(.*)/| \\_$1_/$` /$&\\ |;
s|(\s+)\K/(.*).$| \\$&/$1 /_$2_\\|
}
s|_(?=.*$)| |g;
print
The whitespace within $_ is significant (of course), but none of the rest is. If you have a minor suggestion that improves this, please feel free to just edit my code. For example, Kinopiko has nicely shaved off 6 characters!
Depending on how you count command-line switches, this might be shorter (154 by usual Perl golf rules if I can count correctly):
#!perl -ap
$_='
\_|_/
_/ \_
\___/
/_|_\\';
s|(.\S).*([/\\].)|$1$&$2|g,
s|\S(.*).| \\_$1_/$` /$&\\ |,
s|(\s+)\K/(.*).$| \\$&/$1 /_$2_\\|while$F[0]--;
s|_(?=.*$)| |g
Vb.net, windows console, Infer, Strict, Explicit ON.
Microsoft word is saying 442 characters without space
It might be possible to reduce it more but this is my last update(try #2)
Module z
Sub Main()
Dim i = CInt(Console.ReadLine), j = i + 1, h = j * 2 + 1, w = h * 2, z = "_", b = " "
For y = 0 To h
For x = 0 To w
Dim l = (x + y Mod 2 + i Mod 2) Mod 2, u = j + y, e = j - y, k = h + e, o = x = h Or x = h - 1
Console.Write(If(x = h, If(y = j, b, If(y = j + 1, z, "|")), "") & If(x = w, vbLf, If(y = j, If(x Mod 2 = 0 = (x < h), If(o, b, z), If(x < h, "/", "\")), If(x < k And x > u Or (x < u And x > k Or o) And y < h, z, If(x = k Or (x < u And y < j And x > e Or x > u And y > j And x < w + e) And l = 0, "/", If(x = u Or (x > k And y < j And x < h + u Or x < k And y > j And x > y - j - 1) And l = 1, "\", b))))))
Next
Next
End Sub
End Module
Python: 240 Characters
Nothing too tricky here; just printing line by line - 298 280 271 266 265 261 260 254 240 characters (ignore the last 2 line breaks)
u,b,f,s,a='_\/ |'
m=input()+1
print'\n'.join([(m-x)*s+x*' /'+b+(m-x)*u+a+(m-x)*u+f+x*'\ 'for x in
range(0,m)]+['_/'*m+s*3+'\_'*m+'\n'+(s+b)*m+u*3+'/ '*m]+[x*s+(m-x)*
' \\'+f+x*u+a+x*u+b+(m-x)*'/ 'for x in range(1,m)] + [s*m+f+s*m+a+s*m+b])
Lua, 290
n=...s=string r=s.reverse g=s.gsub a="\\|/"j=(" /"):rep(n+1)..a..("\\ "):rep(n+1) k=j o=k
l=n*4+7 for i=1,n+1 do k=g(k,"^(.- )/(.-)|(.*)\\(.-)$","%1%2_|_%3%4")o=k..o end
o=o..r(o)print((g(g(g(g(r(g(o:sub(1,l),"_"," ")..o:sub(l+1)),j,g(j," ","_")),("."):rep(l),"%1\n"),a," "),r(a),"___")))
Ruby1.9 - 181 chars
n=gets.to_i+1;s=' '
a=0.upto(n-1).map{|i|s*(j=n-i)+' /'*i+?\\+?_*j+'|'+?_*j+?/+'\ '*i+s*j}
d=a.reverse.map{|x|x.reverse};d[-1].tr!?_,s
puts a,'_/'*n+s*3+'\_'*n,' \\'*n+?_*3+'/ '*n,d
Ruby1.8 - 185 chars
Some improvements from JRL
n=gets.to_i+1;s=' '
u='_';a=0.upto(n-1).map{|i|s*(j=n-i)+' /'*i+'\\'+u*j+'|'+u*j+'/'+'\ '*i+s*j}
d=a.reverse.map{|x|x.reverse}
d[-1].tr!u,s;puts a,'_/'*n+s*3+'\_'*n,' \\'*n+u*3+'/ '*n,d
Ruby - 207 chars
Ruby seems to have some peculiar rules about the "\"
n=eval(gets)+1
b,f,p,u,s='\/|_ '.split""
a=0.upto(n-1).map{|i|s*(j=n-i)+' /'*i+b+u*j+"|"+u*j+f+"\\ "*i+s*j}
puts a,'_/'*n+s*3+'\_'*n,' \\'*n+u*3+'/ '*n,a[1..-1].reverse.map{
|x|x.reverse},a[0].reverse.tr(u,s)
Ruby1.8, 179
Run with ruby -n
n=$_.to_i+1
u,s,c=%w{_ \ \ \\}
z=(1..n).map{|i|k=n-i
s*i+c*k+'/'+u*i+'|'+u*i+"\\"+'/ '*k+s*i}
y=z.reverse.map{|a|a.reverse}
z[-1].tr!u,s
puts y,'_/'*n+s*3+'\_'*n,c*n+u*3+'/ '*n,z
In the first attempt below it seemed like a good idea to just generate one quadrant (I chose lower left), and then mirror twice to get the whole web. But gnibbler got better results generating both quadrants (of the top half) and then generating rather than patching up the inner area. So I revised mine to initially generate the other lower quadrant also, mirror only once, and also to leave the innermost row out of the mirror, which kind of converges with the other entry.
Ruby, 241
n=$_.to_i+1
m=2*n+1
u,s,b,f=%w{_ \ \\ /}
z=(0..n).map{|i|s*i+(s+b)*(n-i)+(i==0?u:f)+u*i}
q=z.reverse.map{|a|a.tr f+b,b+b+f}
q[n].gsub!' ','_'
q[n][m-1]=s
z=(q+z).map{|a|a+'|'+a.reverse.tr(f+b,b+b+f)}
z[n][m]=z[n+1][m]=s
z[m].gsub!u,s
puts z
C, 573 chars
Obviously it isn't even in the running w/regard to the character count. The 573 number is just the file size on my windows machine, so that probably counts a few ctrl-M's. On the other hand, maybe 573 is under-counting it, since I incurred the wrath of the compiler by jettisoning all the #include's to save space, warnings be damned!
But hey, this is my first time attempting one of these, and it will undoubtedly be good practice to try to re-express it in something more compact.
#define B puts("");
#define K '\\'+'/'
#define F '_'+' '
#define P(s) putchar(s);
#define I int
c(I s,I f){if(s){P(f)c(s-1,f);P(f)}else P('|')}
w(I lw,I s,I k,I f){if(s){P(' ')P(k)w(lw,s-1,k,f);P(K-k)P(' ')}else{P(K-k)c(1+lw,f);P(k)}}
h(I g,I s,I k,I f){I i;for(i=-1;i<g;++i)P(' ')w(g,s,k,f);}
t(I g,I s){if(s)t(g+1,s-1);h(g,s,'/','_');B}
b(I g,I s){h(g,s,'\\',s?'_':' ');B;if(s)b(g+1,s-1);}
m(I s,I k,I f){if(s){P(f)P(k)m(s-1,k,f);P(K-k)P(f)}else{P(F-f)P(F-f)P(F-f)}}
main(I ac,char*av[]){I s;s=atoi(av[1]);t(0,s);m(1+s,'/','_');B;m(1+s,'\\',' ');B;b(0,s);}
Python, 340 - 309 - 269 - 250 characters
Still room for improvement I think.
s=input()+1
f,b="/ ","\\"
r=range(s)
for i in r:w="_"*(s-i);print" "*(s+(i>=1)-i)+(f*i)[:-1]+b+w+"|"+w+"/"+"\ "*i
print"_/"*s+" "*3+"\_"*s+"\n"+" \\"*s+"_"*3+f*s
for i in r[::-1]:u="_ "[i<1]*(s-i);print" "*(s-i+(i>=1))+("\ "*i)[:-1]+"/"+u+"|"+u+b+f*i
-
Python (alternative version), 250 - 246 characters
s=input()+1;r=range(s);c="/","\\";y="/ ","\\ "
def o(i,r):u="_ "[i<1 and r]*(s-i);print" "*(s+(i>=1)-i)+(y[r]*i)[:-1]+c[r<1]+u+"|"+u+c[r]+(y[r<1]*i)[:-1]
for i in r:o(i,0)
print"_/"*s+" "*3+"\_"*s+"\n"+" \\"*s+"_"*3+"/ "*s
for i in r[::-1]:o(i,1)
Python and Ruby just about even*
I would rather have continued the comment thread above that briefly mentioned Python vs Ruby, but I need formatting to do this. Smashery is certainly classy but doesn't need to worry: it turns out that Python and Ruby are in a pretty close race by one measure. I went back and compared Python to Ruby in the eight code-golf's that I have entered.
Challenge Best Python Best Ruby
The Wave 161 99
PEMDAS no python entry (default victory?)
Seven Segs 160 175
Banknotes 83 (beat Perl!) 87
Beehive 144 164
RPN (no eval) 111 (157) 80 (107)
Cubes 249 233
Webs 212 181
Victories 3 4 (5?)
So the issue definitely isn't settled and got more interesting recently when gnibbler started entering on both sides. :-)
*I only counted fully functional entries.
dc - 262
A "straightforward" solution in dc (OpenBSD). Not a contender, but it is always fun. Line breaks for "readability"
[lcP1-d0<A]sA?sN[lK32sclAxRlNlK-l1scd0!=ARl3PlKl0sclAxRl9PlKlAxRl4PlNlK-
l2scd0!=AAPR]sW95s0124s9[ /]s1[\\ ]s292s347s4lN[dsKlWx1-d0<L]dsLx
[\\_][ ][_/][lN[rdPr1-d0<L]dsLxRRPlNlLxRR]dsBxAP[/ ][_ _][ \\]lBxAP[ \\]s1
[/ ]s247s392s41[dsKlWx1+dlN>L]dsLx32s032s9lNsKlWx
sample output
$ dc web.dc
3
\___|___/
/\__|__/\
/ /\_|_/\ \
_/_/_/ \_\_\_
\ \ \_ _/ / /
\ \/_|_\/ /
\/__|__\/
/ \
Perl 264 chars
shortened by in-lining the subroutines.
perl -E'$"="";($i=<>)++;#r=map{$p=$i-$_;#d=(" "x$_,(" ","\\")x$p,"/","_"x$_);($d="#d")=~y:\\/:/\\:;#d=reverse#d;$d.="|#d"}1..$i;say for reverse#r;$_=$r[0];y: _|:_ :;s:.(.*)\\.*/(.*).:$1_/ \\_$2:;say;y: _\\/:_ /\\:;say;$r[-1]=~y:_: :;say for grep{y:\\/:/\\:}#r;'
Expanded to improve readability.
perl -E'
$"="";
($i=<>)++;
#r=map{
$p=$i-$_;
#d=(
" "x$_,
(" ","\\")x$p,
"/",
"_"x$_
);
($d="#d")=~y:\\/:/\\:;
#d=reverse#d;
$d.="|#d"
}1..$i;
say for reverse#r;
$_=$r[0];
y: _|:_ :;
s:.(.*)\\.*/(.*).:$1_/ \\_$2:;
say;
y: _\\/:_ /\\:;
say;
$r[-1]=~y:_: :;
say for grep{y:\\/:/\\:}#r;
'
This is the code before I minimized it:
#! /opt/perl/bin/perl
use 5.10.1;
($i=<>)++;
$"=""; #" # This is to remove the extra spaces for "#d"
sub d(){
$p=$i-$_;
" "x$_,(" ","\\")x$p,"/","_"x$_
}
sub D(){
#d=d;
($d="#d")=~y:\\/:/\\:; # swap '\' for '/'
#d=reverse#d;
$d.="|#d"
}
#r = map{D}1..$i;
say for reverse#r; # print preceding lines
# this section prints the middle two lines
$_=$r[0];
y: _|:_ :;
s:.(.*)\\.*/(.*).:$1_/ \\_$2:;
say;
y: _\\/:_ /\\:;
say;
$r[-1]=~y:_: :; # remove '_' from last line
say for grep{y:\\/:/\\:}#r; # print following lines
(&)=(++) --9
f 0=[" \\_|_/","_/ \\_"," \\___/"," / | \\"] --52
f(n+1)=[s&h&u&"|"&u&g]&w(f n)&[s&g&s&"|"&s&h]where[a,b,c,d,e]=" _/\\|";[g,h]=["/","\\"];y=n+2;[u,s]=[r y b,r y a];p f s n x=let(a,b)=span(/=s)x in a&f b;i=dropWhile(==a);w[]=[];w[x]=[s&h&i(p(map(\x->if x==a then b else x))c d x)&g];w(l:e)|n==y*2-1=x%h:z|n>y=x&" "%" \\":z|n==y="_/"%"\\_":z|n<y=r(y-n)a&"\\ "%" /":z where n=length e;z=w e;x=r(n+1-y)a&g;(%)=(&).(&i l) --367
r=replicate --12
main=interact$unlines.f.read --29
Haskell entry weighing in at 469 characters. I'm sure there is a lot of room for improvement.
good luck trying to read it :)
here is a more readable version. Although there have been some changes since this version
spider 0=[" \\_|_/","_/ \\_"," \\___/"," / | \\"]
spider n=(s++"\\"++u++"|"++u++"/"):w m(spider(n-1))++[s++"/"++s++"|"++s++"\\"]
where
[a,b,c,d,e]=" _/\\|"
[m,y]=[y*2,n+1]
x=r y
[u,s]=[x b,x a]
t a b=map(\x->if x==a then b else x)
p f s n x=let(a,b)=span(/=s)x;(c,d)=span(/=n)b in a++f c++d
i=dropWhile(==a)
w _[]=[]
w _[x]=[s++"\\"++i(p(t a b)c d x)++"/"]
w(a+1)(l:e) |a==m-1=wrapline x l"\\":z
|a>y=wrapline(x++" ")l" \\":z
|a==y=wrapline"_/"l"\\_":z
|a<y=wrapline(r(y-a)' '++"\\ ")l" /":z
where
z=w a e
x=r(a+1-y)' '++"/"
wrapline b l a=b++i l++a
r=replicate
main=interact$unlines.spider.read