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
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"
*)
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.
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…