Text manipulation

I am new to Applescript and maybe this question has come up before. Here is what I’m trying to do:

  • Have the user enter a simple ASCII text string no longer than say 200 characters
  • Count the number of characters in the string; eg. a=20, b=5, c=18, etc
  • Present this to the user in a decending list with the most frequent chars at the top
  • Allow the user to substitute his/her guess character and put that character into the string on the screen.
  • They can then undo that and try another character and display the string again.
  • Save the manipulated text string at any time if they choose to quit.

As you can see this is a simple “decode” tool to let someone try and decypher a coded string. (Which may or may not include the space character) I realise this is a program in itself, but any tips regarding the text searching and manipulation would be great.
Thx!

Browser: Safari 312
Operating System: Mac OS X (10.4)

set ts to "a"
set tsl to text items of ts
set a to 0
set b to 0
set c to 0
set d to 0
set e to 0
set f to 0
set g to 0
set h to 0
set i to 0
set j to 0
set k to 0
set l to 0
set m to 0
set n to 0
set o to 0
set p to 0
set q to 0
set r to 0
set s to 0
set t to 0
set u to 0
set v to 0
set w to 0
set x to 0
set y to 0
set z to 0

repeat with ti from 1 to number of items in tsl
	set this_item to item ti of tsl
	if this_item is "a" then
		set a to a + 1
	else if this_item is "b" then
		set b to b + 1
	else if this_item is "c" then
		set c to c + 1
	else if this_item is "d" then
		set d to d + 1
	else if this_item is "e" then
		set e to e + 1
	else if this_item is "f" then
		set f to f + 1
	else if this_item is "g" then
		set g to g + 1
	else if this_item is "h" then
		set h to h + 1
	else if this_item is "i" then
		set i to i + 1
	else if this_item is "j" then
		set j to j + 1
	else if this_item is "k" then
		set k to k + 1
	else if this_item is "l" then
		set l to l + 1
	else if this_item is "m" then
		set m to m + 1
	else if this_item is "n" then
		set n to n + 1
	else if this_item is "o" then
		set o to o + 1
	else if this_item is "p" then
		set p to p + 1
	else if this_item is "q" then
		set q to q + 1
	else if this_item is "r" then
		set r to r + 1
	else if this_item is "s" then
		set s to s + 1
	else if this_item is "t" then
		set t to t + 1
	else if this_item is "u" then
		set u to u + 1
	else if this_item is "v" then
		set v to v + 1
	else if this_item is "w" then
		set w to w + 1
	else if this_item is "x" then
		set x to x + 1
	else if this_item is "y" then
		set y to y + 1
	else if this_item is "z" then
		set z to z + 1
	end if
end repeat
set theend to ("a = " & a & return & "b = " & b & return & "c = " & c & return & "d = " & d & return & "e = " & e & return & "f = " & f & return & "g = " & g & return & "h = " & h & return & "i = " & i & return & "j = " & j & return & "k = " & k & return & "l = " & l & return & "m = " & m & return & "n = " & n & return & "o = " & o & return & "p = " & p & return & "q = " & q & return & "r = " & r & return & "s = " & s & return & "t = " & t & return & "u = " & u & return & "v = " & v & return & "w = " & w & return & "x = " & x & return & "y = " & y & return & "z = " & z) as text
return theend

List of characters:

property the_alphabet : {"abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"}

on count_letters(the_text, the_alphabet)
	set old_delimiters to text item delimiters
	set alpha_list to {}
	repeat with i from 1 to count of beginning of the_alphabet
		set this_char to item i of beginning of the_alphabet
		set text item delimiters to this_char
		set this_count to (count of text items of the_text) - 1
		set this_char to item i of end of the_alphabet
		set text item delimiters to this_char
		set this_count to this_count + (count of text items of the_text) - 1
		repeat this_count - (count of alpha_list) + 1 times
			set beginning of alpha_list to {}
		end repeat
		set end of item ((count of items of alpha_list) - this_count) of alpha_list to this_char & " = " & this_count
	end repeat
	-- get rid of any blank items: {}
	set the_result to {}
	repeat with this_item in alpha_list
		set the_result to the_result & this_item
	end repeat
	set text item delimiters to return
	set the_result to the_result as string
	set text item delimiters to old_delimiters
	return the_result
end count_letters

count_letters("The quick brown fox jumps over a lazy dog.", the_alphabet)
-->
(*
"O = 4
A = 2
E = 2
R = 2
U = 2
B = 1
C = 1
D = 1
F = 1
G = 1
H = 1
I = 1
J = 1
K = 1
L = 1
M = 1
N = 1
P = 1
Q = 1
S = 1
T = 1
V = 1
W = 1
X = 1
Y = 1
Z = 1"
*)

How would this be presented to the user? Like “___ __ ______ __ _____.” ?

Thx to Qwerty Denzel and themacgeek for their code. This has got me off-the-ground with this project. To answer the point made by Qwerty Denzel, I visualise the the UI as shown:

A window showing the coded text as typed in. eg. sdf bhser t hgr sdkrl etc…
Another window showing the decode substitutions. eg. (assume the caps are the guesses) Tdf WIser A etc…)
A third window showing the original coded message character frequency by count and bar representation as below:
h = 43 ---------------------------
k = 32 -----------------------
f = 25 -----------------
etc, etc

As you can see, the “guess” window will be the working window and will allow the user to try and save various combos until the message is fully decoded.

Thanks!

It sounds like you want your final product to be an applescript studio application.

Anyway, what do you think? :

TODO:
There is no undo, only reset.
The intructions are not user friendly (I’ll need your help).
The window takes up the whole screen.

property lower_alphabet : "abcdefghijklmnopqrstuvwxyz"
property upper_alphabet : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
global cipher_text, clear_text, char_freq

on run
	set old_delimiters to text item delimiters
	set cipher_text to text returned of (display dialog "Please enter your cipher text:" default answer "")
	reset()
	count_freq()
	
	repeat
		try
			set {text_returned, button_returned} to (display dialog cipher_text & return & return & ¬
				clear_text & return & return & char_freq & return & return & "Please enter your guess:" & return & "(In the format 'original letter(s) *space* your guess')" default answer "" buttons {"Cancel", "Reset", "OK"} default button "OK") as list
		on error number error_number
			if error_number is -128 and clear_text is not cipher_text then -- User cancelled and actually did something
				set this_file to choose file name default name "Untitled.txt" with prompt "Do you want to save the text?"
				try
					open for access this_file with write permission
				end try
				write clear_text to this_file
				close access this_file
			end if
			set text item delimiters to old_delimiters
			return
		end try
		if button_returned is "Reset" then
			reset()
		else
			text_input(text_returned)
		end if
	end repeat
end run

on reset()
	set cipher_text to change_case(cipher_text, "lower")
	set clear_text to cipher_text
end reset

on count_freq()
	set freq_list to {}
	repeat with i from 1 to count of lower_alphabet
		set this_char to character i of lower_alphabet
		set text item delimiters to this_char
		set this_count to (count of text items of cipher_text) - 1
		repeat this_count - (count of freq_list) + 1 times
			set beginning of freq_list to {}
		end repeat
		set bar_rep to space
		repeat this_count times
			set bar_rep to bar_rep & "-"
		end repeat
		set end of item ((count of items of freq_list) - this_count) of freq_list to this_char & " = " & this_count & bar_rep
	end repeat
	-- get rid of any blank items: {}
	set char_freq to {}
	repeat with this_item in freq_list
		set char_freq to char_freq & this_item
	end repeat
	set text item delimiters to return
	set char_freq to char_freq as string
end count_freq

on text_input(text_returned)
	if (count of words of text_returned) is 2 and (count of word 1 of text_returned) is (count of word 2 of text_returned) then
		set input_cipher to change_case(word 1 of text_returned, "lower")
		set input_clear to change_case(word 2 of text_returned, "upper")
		repeat with i from 1 to count of input_cipher
			set text item delimiters to character i of input_cipher
			set clear_text to text items of clear_text
			set text item delimiters to character i of input_clear
			set clear_text to clear_text as string
		end repeat
	end if
end text_input

on change_case(this_text, this_case)
	if this_case is "UPPER" then
		set case_alphabet to lower_alphabet & upper_alphabet
	else
		set case_alphabet to upper_alphabet & lower_alphabet
	end if
	repeat with i from 1 to (count of lower_alphabet)
		set text item delimiters to item i of case_alphabet
		set this_text to text items of this_text
		set text item delimiters to item (i + (count of lower_alphabet)) of case_alphabet
		set this_text to this_text as string
	end repeat
	return this_text
end change_case

Thx Qwerty Denzel. This has now got me on the right track. You are also correct to assume that this is more of an Applescript Studio app, but I thought I’d cut my teeth on the scripting first… The reasoning behind this project is that the American Cryptogram Assn (www.cryptogram.org) solve these text puzzles for fun. But getting to the answer needs a lot of pencils, paper and erasers. My thought was to build a “Tool Bench” on the Apple so that a decoder can use the computer to try various decodes on the crypto text and see the results of each try. The reason for the char count is that this is one of the clues used to break the code…

Thx again for your coding.