#!/bin/sh
#\
exec tclsh "$0" "${1+$@}"
# See Wikit page [Exec Magic] for an explanation of the above.
# Added 2 Jun 01-- Program information.
# Comments are generally good, especially when someone might look
# at your code and wonder what you were smoking/thinking when you
# wrote that.
# This is called vector.tcl, and takes two arguments. Each argument
# is a comma divided set of 3 numbers, in the form of 12,34,56.
# It does some error checking, and then calculates the angle of
# difference between the pair of coordinated, and calls that the
# vector. Finally, it figures the distance between the two coordinates.
# Output looks like:
# $ ./vector.tcl 12,23,34 54,43,32
# To get from 12,23,34 to 54,43,32 you vector 42,20,-2 for 46.5617869073
# The plan, and I do have one, is to make this modular, and then put
# it into Tk. This is just one part of the Space Game.
# Check for the right number of arguments, and have at least one error
# message.
set errorMsg "Please use the right number of arguments and coordinates\
in the form of:
$argv0 aa,bb,cc xx,yy,zz"
if { $argc != 2 } {
puts $errorMsg
exit
}
# This gave a more detailed error message.
proc coordError { badCoord } {
puts "$badCoord is not a valid coordinate in this universe."
exit
}
# I'm rather fond of this one, it took me hours to figure out.
# The first version had a second argument of the variable name
# that was to be used. However, I could not get it to work. This
# one does two tests for the if, and then returns the proper
# list of 3 numbers if everything is right.
proc validateCoord { coord } {
set coordName [ split $coord , ]
if {([ llength $coordName ] != "3") || \
([regexp -- {[^0-9 ]} "$coordName"])
} {
# The more detailed error message
coordError $coord
}
return $coordName
}
set hereNow [ lindex $argv 0 ]
set thereThen [ lindex $argv 1 ]
set hereCoord [ validateCoord $hereNow ]
set thereCoord [ validateCoord $thereThen ]
# Foreach #1
# here is the first improvement, it replaces the while loop below:
# '''why replace the other loop? What makes this better?'''
foreach x1 $hereCoord x2 $thereCoord {
lappend vector [expr {$x2 - $x1}]
}
# This replaced by Foreach #1
#set labelCoord [ list X Y Z ]
#set counter 0
#while { $counter < [ llength $hereCoord ] } {
# set v [ lindex $labelCoord $counter ]
# set vector$v [ expr [ lindex $hereCoord $counter ] \
# - [ lindex $thereCoord $counter ] ]
## set type vector
# set V [ expr [ lindex $hereCoord $counter ] \
# - [ lindex $thereCoord $counter ] ]
# set sqrAbsVector${v} [ expr abs($V) * abs($V) ]
# incr counter
#}
# These were early drops, though they go the script working.
# Such repetative lines should be automated.
#set sqrAbsVectorX [ expr abs($vectorX) * abs($vectorX) ]
#set sqrAbsVectorY [ expr abs($vectorY) * abs($vectorY) ]
#set sqrAbsVectorZ [ expr abs($vectorZ) * abs($vectorZ) ]
# Foreach #2, to replace the distance math.
# I had to read up on foreach to get this.
# '''what is this foreach doing?'''
foreach {X Y Z} $vector break
# It was giving me errors about vector, so a temporary "puts"
#puts " After: $vector "
#The first set was given to better do the math, however, it had an
# error-- the sqrAbs${vector} would set the variable to:
# "sqrAbs-11 -22 9"
#set sqrAbs${vector} [expr {hypot($X, [expr hypot($Y,$Z)])}]
set distance [expr {hypot($X, hypot($Y,$Z))}]
# {end of Foreach #2}
# Replaced by Foreach #2
#set distance [ expr sqrt($sqrAbsVectorX + $sqrAbsVectorY + \
$sqrAbsVectorZ) ]
puts "To get from $hereNow to $thereThen you vector \
${X},${Y},${Z} for $distance"Why not use regexp for the checking and variable assigment part? Maybe something like:
set coordset [join $argv]
if {![regexp {([0-9]{2}),([0-9]{2}),([0-9]{2}) ([0-9]{2}),([0-9]{2}),([0-9]{2})} $coordset -> x1 x2 x3 y1 y2 y3]} {
error "$coordset is not a valid set of coordinates.\n Use: x1,y1,z1 x2,y2,z2"
}this would either throw an error if the given arguments are not right coordinates or let use us $x1,2 , $y1,2 and $z1,2 for your calculations.MG offers this alternative:
proc validateCoordMG {coord} {
set num [scan $coord "%d,%d,%d%n" a b c size]
if { $num != 4 || $size != [string length $coord] } {
coordError $coord
}
return [list $a $b $c]
};# validateCoordMGThis one takes 4ms to run on a valid coordinate set, as opposed to 6ms for the original code, and 40ms for the regexp above (which I edited slightly, to only work on a single coord. set and to run in a proc, using coordError instead of error to report mistakes, so I could get a more accurate comparison).Category Games
