This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

Logic Error - Replacing Characters in a String

Help for those learning Tcl or writing their own scripts.
Post Reply
d
dokueki
Voice
Posts: 31
Joined: Sat Apr 28, 2007 8:42 am
Location: Bat Yam, Israel
Contact:

Logic Error - Replacing Characters in a String

Post by dokueki »

Code: Select all

bind pub - "+cumulan"  spidey:cumulan

#  a  b    c    d   e  f  g   h  i    j  k   l   m   n  o    p    q   r   s   t  u   v  w   x   y   z
# aym mi korao hra ku zu gli ti gura bu upa yai gia tu kan guum yipa rur lia do zor qi wu omyr kil airu
proc spidey:cumulan { nick host hand chan text } {
	if { [lindex [split $text] 0] == "-r" } {
		
	} else {
		set i 0
		set output ""
		foreach item [string range $text 0 end] { 
			set newchar [string map { "a" "aym" } [string index $text $i]]
			set newchar [string map { "b" "mi" } [string index $text $i]]
			set newchar [string map { "c" "korao" } [string index $text $i]]
			set newchar [string map { "d" "hra" } [string index $text $i]]
			set newchar [string map { "e" "ku" } [string index $text $i]]
			set newchar [string map { "f" "zu" } [string index $text $i]]
			set newchar [string map { "g" "gli" } [string index $text $i]]
			set newchar [string map { "h" "ti" } [string index $text $i]]
			set newchar [string map { "i" "gura" } [string index $text $i]]
			set newchar [string map { "j" "bu" } [string index $text $i]]
			set newchar [string map { "k" "upa" } [string index $text $i]]
			set newchar [string map { "l" "yai" } [string index $text $i]]
			set newchar [string map { "m" "gia" } [string index $text $i]]
			set newchar [string map { "n" "tu" } [string index $text $i]]
			set newchar [string map { "o" "kan" } [string index $text $i]]
			set newchar [string map { "p" "guum" } [string index $text $i]]
			set newchar [string map { "q" "yipa" } [string index $text $i]]
			set newchar [string map { "r" "rur" } [string index $text $i]]
			set newchar [string map { "s" "lia" } [string index $text $i]]
			set newchar [string map { "t" "do" } [string index $text $i]]
			set newchar [string map { "u" "zor" } [string index $text $i]]
			set newchar [string map { "v" "qi" } [string index $text $i]]
			set newchar [string map { "w" "wu" } [string index $text $i]]
			set newchar [string map { "x" "omyr" } [string index $text $i]]
			set newchar [string map { "y" "kil" } [string index $text $i]]
			set newchar [string map { "z" "airu" } [string index $text $i]]
			set output "$output$newchar"
			incr i
		}
	}
	putserv "NOTICE $nick :$text = $output"
}
What I'm trying to do here, is make it replace each letter with several other letters, creating a fake, code language.
But all it does is just delete some chars and only keeping the first several/one char in there. I dunno what's happening, so I came to the forums as a last result. Any help on this would be greatly appreciated!
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

First off, foreach expects a list, not a string. Big difference!

Secondly, why do you use the foreach-loop there anyway? You never try to use $item anywhere within the loop. Don't use foreach as a normal for-loop, but use "for" for this (or "while").

Third, all you seem to do is alot of string map's, why not simply create one large map-list, and allow "string map" to work on the whole string at once?

Such as something like this...

Code: Select all

...
 puthelp "NOTICE $nick :$text = [string map [list a aym b mi c korao d hra e ku ...] $text]"
...
Fourth, the only string map that will have any effect in the end of your code is the last (string map { "z" "airu" }), as the output stored in $newchar from previous string map's will be overwritten by this...
NML_375
d
dokueki
Voice
Posts: 31
Joined: Sat Apr 28, 2007 8:42 am
Location: Bat Yam, Israel
Contact:

Post by dokueki »

Woo, that was great help. I didn't know you could use string map with a list like that. Anyways, I tried it, and it works fine, until it stops replacing characters after the fifth time. I mean, +cumulan abcde works, but beyond that, it'll only replace upto e and then start outputting the following chars without replacing them.

[02:12:35 PM] <Spidey> +cumulan abcdefghijklmnopqrstuvwxyz
[02:12:38 PM] [Notice] -Venom- abcdefghijklmnopqrstuvwxyz = aymmikoraohrakufghijklmnopqrstuvwxyz
[02:17:49 PM] <Spidey> +cumulan this is a test
[02:17:52 PM] [Notice] -Venom- this is a test = this is aym tkust

Code: Select all

bind msg - "+cumulan"  spidey:cumulan

#  a  b    c    d   e  f  g   h  i    j  k   l   m   n  o    p    q   r   s   t  u   v  w   x   y   z
# aym mi korao hra ku zu gli ti gura bu upa yai gia tu kan guum yipa rur lia do zor qi wu omyr kil airu
proc spidey:cumulan { nick host hand text } {
	if { [lindex [split $text] 0] == "-r" } {
		
	} else {
		set output [string map [list a aym b mi c korao d hra e ku f zu g gli h ti i gura j bu k upa l yai m gia n tu o kan p guum q yipa r rur s lia t do u zor v qi w wu x omyr y kil z airu] $text]
	}
	putserv "NOTICE $nick :$text = $output"
}
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

That's usually an indication that your list is not properly ordered.

One more intuitive way of creating the substitution-list is by doing it something like this:

Code: Select all

set substitute(a) aym
set substitute(b) mi
set substitute(c) korao
...

...[string map [array get ::substitute] $text]...
Also, the list you provided in your post works just fine for me, double-check that you don't have any unexpected spaces or characters within your list (somewhere between "ku" and "f", as it seems this is the location where your list seems to be "offset'd")

edit:
Clumsy me, should've learned to know when to use $ and not by now :p
Last edited by nml375 on Tue Nov 06, 2007 10:33 am, edited 1 time in total.
NML_375
d
dokueki
Voice
Posts: 31
Joined: Sat Apr 28, 2007 8:42 am
Location: Bat Yam, Israel
Contact:

Post by dokueki »

Well, it says it can't read the variable cause it's an array:
(cumulan = substitute)
[16:26] Tcl error [spidey:cumulan]: can't read "::cumulan": variable is array

This is after I used global to make it accessible. Without using global, it says it doesn't exist, and without referring to it as global (::), it gives the same error as the one above D:

Thanks again for the help, btw.
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Ahh... my bad, should've been ::substitute rather than $::substitute

Updating my previous post aswell..
NML_375
d
dokueki
Voice
Posts: 31
Joined: Sat Apr 28, 2007 8:42 am
Location: Bat Yam, Israel
Contact:

Post by dokueki »

Alright! Works like a charm :D
Thanks again ^_^
Just shows I still have alot to learn :P
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Np, to see what further you can do using the "string" command, and others, have a look at the manual
NML_375
d
dokueki
Voice
Posts: 31
Joined: Sat Apr 28, 2007 8:42 am
Location: Bat Yam, Israel
Contact:

Post by dokueki »

Alright, thanks :3
Unfortunately, I have another problem D:

Code: Select all

bind msg - "+cumulan"  spidey:cumulan

#  a  b    c    d   e  f  g   h  i    j  k   l   m   n  o    p    q   r   s   t  u   v  w   x   y   z
# aym mi korao hra ku zu gli ti gura bu upa yai gia tu kan guum yipa rur lia do zor qi wu omyr kil airu
proc spidey:cumulan { nick host hand text } {
	global cumulan
	set reverse 0
	set verbose 0
	set chan ""
	set target ""
	if { [lindex [split $text] 0] == "-r" } {
		set reverse 1
	} else {
		set reverse 0
	}
	if { [lindex [split $text] 0] == "-v" } {
		set verbose 1
		set chan [lindex [split $text] 1]
	} else {
		set verbose 0
	}
	if { ([lindex [split $text] 0] == "-rv") || ([lindex [split $text] 0] == "-vr") } {
		set reverse 1
		set verbose 1
		set chan [lindex [split $text] 1]
	}
	if { !$reverse } {
		set cumulan(a) aym
		set cumulan(b) mi
		set cumulan(c) korao
		set cumulan(d) hra
		set cumulan(e) ku
		set cumulan(f) zu
		set cumulan(g) gli
		set cumulan(h) ti
		set cumulan(i) gura
		set cumulan(j) bu
		set cumulan(k) upa
		set cumulan(l) yai
		set cumulan(m) gia
		set cumulan(n) tu
		set cumulan(o) kan
		set cumulan(p) guum
		set cumulan(q) yipa
		set cumulan(r) rur
		set cumulan(s) lia
		set cumulan(t) do
		set cumulan(u) zor
		set cumulan(v) qi
		set cumulan(w) wu
		set cumulan(x) omyr
		set cumulan(y) kil
		set cumulan(z) airu
	} else {
		set cumulan(aym) a
		set cumulan(mi) b
		set cumulan(korao) c
		set cumulan(hra) d
		set cumulan(ku) e
		set cumulan(zu) f
		set cumulan(gli) g
		set cumulan(ti) h
		set cumulan(gura) i
		set cumulan(bu) j
		set cumulan(upa) k
		set cumulan(yai) l
		set cumulan(gia) m
		set cumulan(tu) n
		set cumulan(kan) o
		set cumulan(guum) p
		set cumulan(yipa) q
		set cumulan(rur) r
		set cumulan(lia) s
		set cumulan(do) t
		set cumulan(zor) u
		set cumulan(qi) v
		set cumulan(wu) w
		set cumulan(omyr) x
		set cumulan(kil) y
		set cumulan(airu) z
	}
	set output [string map [array get ::cumulan] $text]
	if { $verbose } {
		set output [lrange [split $output] 2 end]
	} elseif { $reverse } {
		set output [lrange [split $output] 1 end]
	}
	if { $verbose } {
		set method "PRIVMSG"
		set target $chan
	} else {
		set method "NOTICE"
		set target $nick
	}
	if { [catch { putserv "$method $target :$output" } errmsg] } {
		putserv "NOTICE $nick :\002Error:\002 $errmsg"
	}
}

putlog "Cumulan Translator 1.0 by Hen Asraf: Loaded"
I need to code it to work both ways -- translate from one language to another. English to Cumulan works fine, but vice-versa doesn't work D: Any clue?
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

First thing, prefixing a variable with :: means addressing it with a full namespace path, in this case the global namespace :: (instead of using global cumulan).

I'd suggest you use two different variables, ::cumulan and ::cumulanreverse, define these in globalspace, and then use something like this:

Code: Select all

if {$reverse} {
 set map ::cumulanreverse
} {
 set map ::cumulan
}
set output [string map [array get $map] $text]
In this case, I use $map intentionally to hold the name of the array with the map, rather than entering the different array-names directly.
NML_375
d
dokueki
Voice
Posts: 31
Joined: Sat Apr 28, 2007 8:42 am
Location: Bat Yam, Israel
Contact:

Post by dokueki »

Again, works like a charm, thanks again!
Post Reply