newLISP Fan Club

Forum => newLISP in the real world => Topic started by: _ex_ on August 26, 2006, 02:09:52 PM

Title: I'm missing my foreach keys %hash... :(
Post by: _ex_ on August 26, 2006, 02:09:52 PM
Hi there, I want to use hash tables in newLisp,

Take for example this code (Python challenge ;)

;* http://www.pythonchallenge.com/pc/def/map.html                                          
(setq input
(string
"g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp.n"
"bmgle gr gl zw fylb gq glcddgagclr ylb rfyr'q ufw rfgq rcvr gq qm jmle.n"
"sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj."))

; Create table for decryption
(for (k 0 25)
(setq key (char (+ k (char "a"))))
(setq value (char (+ (% (+ k 2) 26) (char "a"))))
(context 'dic key value)
;;(println key " - " value)
)

(define (decrypt input table)
(setq len (length input))
(setq output "")
(for (k 0 (- len 1))
(setq key (char (char input k)))
(if (context? table key)
(setq output (string output (context table key)))
(setq output (string output key))
)
)
(setq return output)
)

(println (decrypt input dic))
(println (decrypt "map" dic))


This way I decoded the string, using a hash table for lookup, we have "context?" for checking existence, that's nice, but what about length or foreach operations?, I guess I'm missing something... :(

I have read the docs about the "context" thing, by the way.



Is not this a *weird* way to add hashes to the language? I read some posts than says earlier implementations of newLisp didn't have context before.

But I want to believe that I'm still trying to program "the perl, ruby, python way". Please tell me how is the newLip way to do this kind of simple things. Please.



(ex)
Title:
Post by: cormullion on August 27, 2006, 01:50:53 AM
Hi _ex_. I don't know what "foreach keys %hash..." is, so I can't help you with contexts and hashes much. There are probably others who know Python here.



But you asked how do others do tasks like this, and this would be my approach:


(map (fn (c)
(if   (and  (LT c (char "y"))
               (>= c (char "a")))
              (print (char (+ 2 c)))
         (>= c (char "y"))
              (print (char (- c 24)))
         (LT c (char "a"))
              (print (char c))))
(map char (explode input)))


(for some reason I couldn't get the angle brackets to work - replace LT with an opening one)



Actually at first i just did a map to see what was what:

(map (fn (f) (print (char (+ 2 (char f))))) (explode input))


but that revealed that the puntuation hadn't been encrypted, so more logic was needed.



If you want more cryptic puzzles to solve, there's still the Da Vinci Code newLISP puzzle //http://newlisper.blogspot.com  ;-(((((
Title:
Post by: Lutz on August 27, 2006, 05:02:19 AM
There are two ways to iterate through a hash, which are better called dictionaries or namespaces in newLISP. Even scripting languages using hashes tend to talk about them as dictionaries lately ;)


; make a dictionary
(context 'foo "sdfg" 111)
(context 'foo "yete" 222)
(context 'foo "asdf" 333)

; display all key value pairs in alphabetical order

(dotree (s foo)
    (println s "->" (eval s)))

; or an alternative method

(dolist (s (symbols foo))
    (println s "->" (eval s)))

; generates the output

foo:asdf->333
foo:sdfg->111
foo:yete->222


Instead of 'context' you also can use 'sym' for creating/testing/modifying symbols. Sometimes its more convenient, it depends on the situation.



Lutz



ps: the docoument  http://newlisp.org/DesignPatterns.html has been updated with the previous explanations in chapter 11
Title:
Post by: _ex_ on August 27, 2006, 09:04:46 PM
Thank you guys.

I'm learning new things with newLisp, what is good, and I'm havng a nice time in the way :). map seems an interesting function and so dotree and dolist.

cormullion:

the idea was to use a dictionary for this problem, but your function helpme to undestand the *map* concept, I refined a little using regex, I loved perl just by its regex support...

(define (decrypt input , output)
(setq output "")
(map
(fn (c)
(if (regex "[a-z]+" (char c))
(print (char (+ (% (+ (- c (char "a")) 2) 26) (char "a"))))
(print (char c))
)
)
(map char (explode input))
)
(setq return output)
)


Lutz: nice to read that docu :)

How about sorting a dictionary? I can't find an example on how to use sort to sort contexts, something like this in perl:



foreach $value (sort {$coins{$a} cmp $coins{$b} } keys %coins)
{
     print "$value $coins{$value}<br>";
}

[/code]
Title:
Post by: cormullion on August 28, 2006, 02:42:49 AM
Quote from: "_ex_"
How about sorting a dictionary? I can't find an example on how to use sort to sort contexts


:-) I remember asking that question too (//http://www.alh.net/newlisp/phpbb/viewtopic.php?t=892&highlight=sort+hash and I don't think I've got the hang of this area of newLISP yet enough. Somehow I feel I should be able to reverse-sort a dictionary, but I've managed to cope without one so far. But...



As an example, is there a better way to do this:



(context 'english-german "please" "bitte")
(context 'english-german "thanks" "danke schone")
(context 'english-german "excuse me" "entschuldigen sie")
(context 'english-german "beer" "bier")
(context 'english-german "coffee" "kaffee")

(println "English-German dictionary")
(dotree (s  english-german)
    (println " " s "->" (context english-german (name s))))

; reverse 'sort' to create German-English dictionary...
(dotree (s english-german)
(context 'german-english (context english-german (name s)) s))
(println "German-English dictionary")
(dotree (s german-english)
    (println " " s "->" (eval s)))


Which creates a new context with the entries reversed:



English-German dictionary
 english-german:beer->bier
 english-german:coffee->kaffee
 english-german:excuse me->entschuldigen sie
 english-german:please->bitte
 english-german:thanks->danke schone
German-English dictionary
 german-english:bier->english-german:beer
 german-english:bitte->english-german:please
 german-english:danke schone->english-german:thanks
 german-english:entschuldigen sie->english-german:excuse me
 german-english:kaffee->english-german:coffee


- as you see, it went a bit wrong here.



I've noticed that sometimes newLISP requires us to 'unlearn' things as well as 'learn' things...
Title:
Post by: Lutz on August 28, 2006, 05:33:34 AM
your code for inverting the dictionary is fine, just use 'name' once more when assigning the value:


(dotree (s english-german)
    (context 'german-english (context english-german (name s)) (name s)))

(dotree (s german-english)
    (println " " s "->" (eval s)))
=>
 german-english:bier->beer
 german-english:bitte->please
 german-english:danke schone->thanks
 german-english:entschuldigen sie->excuse me
 german-english:kaffee->coffee


Lutz



Ps: 'name' supresses the context part of a symbol when converting to a string.
Title: Now I'm REALLY missing my hashes... :(
Post by: _ex_ on August 28, 2006, 04:07:01 PM
ouch! this hurts...

All that I was trying to do was sort my map in order to decrypt a message, this map has the form:

map frequency { "char" => freq }

where freq is the number of repetitions of the character "char" in one string:

But the dotree function sorts them (seems) as they were strings.. :(



Consider the next problem: you got an *encrytpted* message and the frequency info of characters in that language in one string from more frequent to less frequent. *decrypt* that message...

This was very easy to do in ruby (and I'm learning it at the side of newLisp):

# Decrypt
text = "Uid nx, aex jcdjipx iu wzux zp, ta wxtpa jtdaws, ai etkx vis."

freqLang = "TEOIARNSHLMYUCWDGPFBVKJ"

len = text.length
frequency = Hash.new

for k in 0..( len - 1 )
c = text[ k, 1 ].upcase
if c =~ /[A-Z]/
if frequency.has_key?( c )
frequency[ c ] = frequency[ c ] + 1;
else
frequency[ c ] = 1;
end
end
end

dic = Hash.new
freqText = ""
index = 0

frequency.sort{ |a,b| b[1]<=>a[1] }.collect{ |a|
#puts( a[0] + " - " + a[1].to_s )
freqText += a[0]
dic[ a[0].upcase ] = freqLang[ index, 1 ]
index += 1
}

puts( freqLang )
puts( freqText )

decrypted = "";
len = text.length;

for k in 0..( len - 1 )
uper = false
c = text[ k, 1 ]

if c =~ /[A-Z]/ then uper = true
else c = c.upcase end

if dic.has_key?( c )
if uper then decrypted += dic[ c ]
else decrypted += dic[ c ].downcase end
else decrypted += c end
end

puts( decrypted )

I don't want to past the perl code here but is equally suscint.

Now when I tryed the newLips version I got stuck...

(setq text
(string "Uid nx, aex jcdjipx iu wzux zp, ta wxtpa jtdaws, ai etkx vis."))

(setq freqLang "TEOIARNSHLMYUCWDGPFBVKJ")

(context 'frequency) ;; Here we are ~creating~ a hash...
(context 'MAIN)  ;; THIS IS UGLY!!! but sadly necessary.. guess why?
(context 'inverse)
(context 'MAIN)

(for (k 0 (- (length text) 1))
(setq c (upper-case (char (char text k))))
(if (regex "[A-Z]" c)
(if (context? frequency c)
(context 'frequency c (+ 1 (context 'frequency c)))
(context 'frequency c 1)
)
)
)

(dotree (s 'frequency)
(println (name s) " - " (eval s))
(context 'inverse (string (eval s)) (name s))
)

(dotree (s 'inverse)
(println s)
)


Lutz you are a kind person, and newLips is REALLY cool but...

newLisp is using context for two totally different kind of things

- context as a perl package

- context as a perl hash

I think seriously in the second form only as a hack (and not of the nice ones)

My friends are going to laugh if I tell them this...

We live in the *regex* world and here perl is KING, but so much Paul Graham is affecting my brain, some neurons on my head are  spiking "hey maybe it's true" but when I see CLisp I don't know where to start, Where are my regex?, Where are my arrays? Where are my hashes? How can I open/write files?  That all that I can think, excuse my rudeness. Sure thing they must be there or maybe a superior version of these, but I don't have the time (years I suspect) to master it.

Now newLisp is cool because it can be run from the console, has regex, has arrays, open/write files, has hashes, errr... no it doesn't have hashes.

And you know dictionaries are hell useful.

Any ~modern~ language has them,  the faty snake python has them, the prima-donna ruby has them, even the minuscule lua has them...

So I hope newlisp.



(ex)
Title:
Post by: Lutz on August 28, 2006, 04:40:14 PM
A namespace/context for implementing dictionaries is a very efficient way to implement a dictionary. newLISP namespaces/contexts are implemented using red-black binary trees, a very speedy and memory efficient method to implement dictionaries and more scalable than implementations using hashing techniques, which need allocate overflow spaces and take care of ties produced by the hashing algorithms.



Here is a short little module to implement dictionaries which feel more like what you are used in Ruby or Python:


;; module hash.lsp
(context 'HASH)

(define (HASH:HASH this)
    (new 'MAIN:HASH this))

(define (put key value)
        (context this key value))

(define (get key)
        (context this key))

(define (keys)
    (map name (difference (symbols this)
                (append '(this put get key keys value)
                         (list (sym (name this) this))))))
(context MAIN)


and its called HASH to make everybody feel more familiar ;). This is how to use it:


(load "hash.lsp")

; create a new HASH
(HASH 'myhash)                            

; put some values
(myhash:put "abc" 123)                
(myhash:put "xyz" 456)

; retrieve values
(myhash:get "abc")     => 123      
(myhash:get "xyz")     => 456

; retrieve all keys
(myhash:keys)   => ("abc" "xyz")  


Myself I prefer to use the form (context ctx key value) directly because it is directer and faster. But this HASH module gives you a very readable syntax familiar in other scripting languages.



Lutz
Title:
Post by: _ex_ on August 28, 2006, 07:18:26 PM
Lutz my friend, seems I still have lots to walk in the newLisp way :)

In your example:
; create a new HASH
(HASH 'myhash)

; put some values
(myhash:put "a" 123)
(myhash:put "x" 456)
(myhash:put "d" 5)


How do you sort the dictionary by value?, I mean I wan't to get
(println myhash:sort-by-value-descend)
=> 456 "x"
=> 123 "a"
=> 5 "d"

This is the hard part for me.

Regards.

(ex)
Title:
Post by: frontera000 on August 28, 2006, 09:20:38 PM

(sort (map (lambda (x) (list (myhash:get x) x)) (myhash:keys))  (lambda (x y) (< y x)))
Title:
Post by: _ex_ on August 28, 2006, 09:46:00 PM
Thank you very much frontera000!
(println (sort (map (lambda (x) (list (myhash:get x) x)) (myhash:keys))  (lambda (x y) (< y x))))
(println (sort (map (lambda (x) (list (myhash:get x) x)) (myhash:keys))  (lambda (x y) (> y x))))
Title: finally...
Post by: _ex_ on August 29, 2006, 04:54:44 PM
Finally... but you must to agree:

It takes more code (and more neurons) :)

(context 'DIC)

(define (DIC:DIC this)
(new 'MAIN:DIC this))

(define (put key value)
(context this key value))

(define (get key)
(context this key))

(define (has_key key)
(context? this key))

(define (echo)
(map (fn (key) (println key " - " (DIC:get key))) (DIC:keys)))

(define (vsort func)
(sort (map (fn (key) (list (DIC:get key) key)) (DIC:keys)) func))

(define (keys)
(map name (difference (symbols this)
(append '(this put get key keys value has_key echo vsort func)
(list (sym (name this) this))))))

(context MAIN)

; Decrypt
(setq text (string
"Uid nx, aex jcdjipx iu wzux zp, ta wxtpa jtdaws, ai etkx vis.n"
"Scfzezdi Ntapcniai. (hhh.tdaznt.qin/zyak/dcos)"))

(setq freqLang "TEOIARNSHLMYUCWDGPFBVKJ")

(DIC 'frequency)

(for (k 0 (- (length text) 1))
(setq c (upper-case (char (char text k))))
(if (regex "[A-Z]" c)
(if (frequency:has_key c)
(frequency:put c (+ 1 (frequency:get c)))
(frequency:put c 1))))

(setq freqText "")
(DIC 'dic)
(setq ind 0)

(map
(fn (x)
;;(println (x 1) " - " (x 0))
(setq freqText (string freqText (x 1)))
(dic:put (upper-case (string (x 1))) (char (char freqLang ind)))
(inc 'ind))
(frequency:vsort (fn (x y) (< y x))))

(println freqLang)
(println freqText)

(setq decrypted "")

(for (k 0 (- (length text) 1))
(setq uper 0)
(setq c (char (char text k)))
(if (regex "[A-Z]" c)
(setq uper 1)
(setq c (upper-case c)))
(if (dic:has_key c)
(if (= uper 1)
(setq decrypted (string decrypted (dic:get c)))
(setq decrypted (string decrypted (lower-case (dic:get c)))))
(setq decrypted (string decrypted c))))

(println decrypted)


If you feel something is wrong or can be improved, please bring it on! (pedantic-mode-encorauged)
Title:
Post by: HPW on August 29, 2006, 10:41:29 PM
A little minor thing from pedantic-mode. ;-)

Since (setq ..) can take multiple arguments you can make one of them here.

In big loops it could be a bit faster.


(for (k 0 (- (length text) 1))
   (setq uper 0
         c (char (char text k)))
   (if (regex "[A-Z]" c)
      (setq uper 1)
      (setq c (upper-case c)))
   (if (dic:has_key c)
      (if (= uper   1)
         (setq decrypted (string decrypted (dic:get c)))
         (setq decrypted (string decrypted (lower-case (dic:get c)))))
      (setq decrypted (string decrypted c))))
Title:
Post by: _ex_ on August 30, 2006, 07:08:52 AM
nice to know :)
Title:
Post by: cormullion on August 30, 2006, 10:58:54 AM
Hi _ex_! Good code! I hope you continue with newLISP, despite your contextual reservations!



I was interested in your first Ruby script for decryption, and tried to translate it to a newLISP version, sticking to my own programming style :-)



(set
  'text "Uid nx, aex jcdjipx iu wzux zp, ta wxtpa jtdaws, ai etkx vis. Scfzezdi Ntapcniai. (hhh.tdaznt.qin/zyak/dcos"
  'freq-lang "TEOIARNSHLMYUCWDGPFBVKJ"
  'freq-table '())

(map (fn (ch)
  (if (regex "[A-Z]" ch)
    (begin
      (set 'found (lookup ch freq-table))
      (if found
          (replace-assoc ch freq-table (list ch (+ 1 found)))
        (push (list ch 1) freq-table)))))
  (map upper-case (explode text)))

; sort
(sort freq-table (fn (x y) (> (last x) (last y))))

; build dictionary
(map (fn (d e)
  (push (list (first d) (last d) e) dict))  
  freq-table (explode freq-lang))

; decode text
(map (fn (c)
  (set 'a (lookup (upper-case c) dict))
  (set 'upper-case? (= c (upper-case c)))
  (if a
    (if upper-case? (print a) (print (lower-case a)))
    (if upper-case? (print c) (print (lower-case c)))))
  (explode text))


As you see, I tend to not use hash/dictionary/contexts automatically, but stick with my favourite list-based structures. To be honest I'm still not confident in my use of contexts other than for building modules. And with only the alphabet to store...



I was puzzled for a while as to why none of these scripts actually generates the right answer...;-) But it must be because there aren't enough letters in the text for the statistics to work. Also, the answers of my script and yours differ: again, I think this is because the letters with similar frequencies are sorted differently, and assigned differently as a result - not enough coded text to get some differences.



Or I have I misread your code?



Anyway, good stuff.
Title: Where Is Everybody
Post by: m i c h a e l on August 30, 2006, 11:09:06 AM
Hi cormullion :-)


Quote from: "cormullion"If you want more cryptic puzzles to solve, there's

still the Da Vinci Code newLISP puzzle http://newlisper.blogspot.com ;-(((((


I have honestly tried and tried and tried to figure this out, and frankly, it's beginning to make me feel stupid and resentful about the lack of response to your hard work. Why hasn't anyone answered this, yet!?



m i c h a e l



P.S. I even wrote an email to Lutz asking him to help me figure this out, but I didn't end up sending it as I didn't want to bother him (not to mention humiliate myself ;-)
Title:
Post by: cormullion on August 30, 2006, 11:14:38 AM
:-) If only the decrypted solution was interesting enough when you finally manage to decode it... Perhaps Dan Brown has the same problem...
Title:
Post by: m i c h a e l on August 30, 2006, 11:22:41 AM
This isn't something like, "Be sure to drink your Ovaltine!"[1] or anything, is it?



m i c h a e l





[1] Christmas Story
Title:
Post by: Lutz on August 30, 2006, 11:25:16 AM
Her is a way to generate the freq-table with much less code:


(set 'text "Uid nx, aex jcdjipx iu wzux zp, ta wxtpa jtdaws, ai etkx vis. Scfzezdi Ntapcniai. (hhh.tdaznt.qin/zyak/dcos")

(set 'letters (unique (sort (explode text))))

=>
(" " "(" "," "." "/" "N" "S" "U" "a" "c" "d" "e" "f" "h" "i" "j"
 "k" "n" "o" "p" "q" "s" "t" "u" "v" "w" "x" "y" "z")

(map list letters (count letters (explode text)))

=> (
 (" " 15)
 ("(" 1)
 ("," 3)
 ("." 4)
 ("/" 2)
 ("N" 1)
 ("S" 1)
 ("U" 1)
 ("a" 9)
 ("c" 4)
 ("d" 6)
 ("e" 3)
 ("f" 1)
 ("h" 3)
 ("i" 9)
 ("j" 3)
 ("k" 2)
 ("n" 4)
 ("o" 1)
 ("p" 4)
 ("q" 1)
 ("s" 3)
 ("t" 7)
 ("u" 2)
 ("v" 1)
 ("w" 3)
 ("x" 6)
 ("y" 1)
 ("z" 6))


Lutz
Title:
Post by: cormullion on August 30, 2006, 11:28:27 AM
Very nice! Good to see a craftsman at work!
Title:
Post by: Lutz on August 30, 2006, 11:38:03 AM
... continuing from previous post



and here is an even faster and shorter method using 'bayes-train' to automatically count into a context:



(set 'text "Uid nx, aex jcdjipx iu wzux zp, ta wxtpa jtdaws, ai etkx vis. Scfzezdi Ntapcniai. (hhh.tdaznt.qin/zyak/dcos")

(bayes-train (explode text) '() 'freq-tab)

(dotree (c freq-tab)
    (println (last (name c)) "=>" (first (eval c))))

 =>15
(=>1
,=>3
.=>4
/=>2
N=>1
S=>1
U=>1
a=>9
c=>4
d=>6
e=>3
f=>1

... etc

Each letter symbol contains a list, i.e:
freq-tab:_a => (9 0)

the empty list in:


(bayes-train (explode text) '() 'freq-tab)

provided a place for the 0 position, which you could use to store another letter instead.



Lutz
Title:
Post by: _ex_ on August 30, 2006, 09:44:37 PM
cormullion, I think I'll follow with my newLisp endeavours :) because is the *only* lisp I can afford now (and that with a lot of struggling by my part)



About the message I didn't want to post the text complete



Uid nx, aex jcdjipx iu wzux zp, ta wxtpa jtdaws, ai etkx vis.          

Dcos zyexdzaxr aex Jxdw jezwipijes iu etkzyg nidx aety iyx hts          

ai ri aex ptnx aezyg. Z zyexdzaxr aeta jezwipijes udin Wtdds Htww,      

hei zp ns exdi tqactwws. Z htya ai ntfx Dcos cpxdp udxx. Z htya ai      

gzkx aexn aex udxxrin ai qeiipx. Jxijwx tdx rzuuxdxya. Jxijwx qeiipx    

rzuuxdxya qdzaxdzt. Oca zu aexdx zp t oxaaxd hts tniyg ntys            

twaxdytazkxp, Z htya ai xyqicdtgx aeta hts os ntfzyg za qinuidatowx.    

Pi aeta'p heta Z'kx adzxr ai ri.                                        

Z htya ai piwkx jdiowxnp Z nxxa zy aex rtzws wzux os cpzyg qinjcaxdp,  

pi Z yxxr ai hdzax jdigdtnp. Os cpzyg Dcos, Z htya ai qiyqxyadtax aex  

aezygp Z ri, yia aex ntgzqtw dcwxp iu aex wtygctgx, wzfx patdazyg hzae  

jcowzq kizr  pinxaezyg pinxaezyg pinxaezyg ai pts, "jdzya exwwi hidwr."

Z vcpa htya ai pts, "jdzya aezp!" Z riy'a htya tww aex pcddicyrzyg      

ntgzq fxshidrp. Z vcpa htya ai qiyqxyadtax iy aex atpf. Aeta'p aex otpzq

zrxt. Pi Z etkx adzxr ai ntfx Dcos qirx qiyqzpx tyr pcqqzyqa.          

Scfzezdi Ntapcniai. (hhh.tdaznt.qin/zyak/dcos)                          



I hope nobody gets offended if I post words of another master I admire here.



About: Da Vinci Code newLISP puzzle http://newlisper.blogspot.com

What it is? I went before (nice blog by the way) but searching with firefox I can't find anything about da vinci code, I'm missing something desho?

EDIT: I've searched wikipedia and found that the da vinci code could mean that you've hidden text in your blog as a secret message... LOL sorry I never read that book. And yes I like puzzles ;)
Title:
Post by: m i c h a e l on August 31, 2006, 08:25:26 AM
Hi (ex) :-)



Here is the url for cormullion's  Da Vinci Code (//http) post.



m i c h a e l
Title:
Post by: cormullion on September 03, 2006, 02:43:00 AM
Another attempt to produce a succint yet readable solution...



(for some reason I found myself writing as if it was Forth... ;-))





(set

  'atext [text]os zyexdzaxr aex  ... as previous post ...  

    apcniai. (hhh.tdaznt.qin/zyak/dcos) [/text]

  'freq-lang "TEOAINRHSLMCYUDWGQFBPVKZXJ")



(define (in-range? x low high) (and (>= x low) (<= x high)))



(define (letter? c) (or

(in-range? (char c) (char "a") (char "z"))

(in-range? (char c) (char "A") (char "Z"))))



(set 'letters-used (unique (sort (filter letter? (explode  atext)))))

(set 'letter-freq-table (map list letters-used (count letters-used (explode atext))))

(sort letter-freq-table (fn (x y) (> (last x) (last y))))

(set 'dict (map (fn (e f) (list (first e) (last e) f)) letter-freq-table (explode freq-lang)))



(map (fn (chr)

  (set 'letter (lookup (lower-case chr) dict))

  (set 'upper-case? (in-range? (char chr) (char "A") (char "Z")))

  (if letter

    (if upper-case? (print letter) (print (lower-case letter)))

    (if upper-case? (print chr) (print (lower-case chr)))

    ))

 (explode atext))

(exit)




;->

"by inherited the Perl philosophy of having more than one way

to do the same thing. I inherited that philosophy from Larry Wall,

who is my hero actually. I want to make Ruby users free. I want to

give them the freedom to choose. People are different. People choose

different criteria. But if there is a better way among many

alternatives, I want to encourage that way by making it comfortable.

So that's what I've tried to do.

I want to solve problems I meet in the daily life by using computers,

so I need to write programs. By using Ruby, I want to concentrate the

things I do, not the magical rules of the language, like starting with

public void something something something to say, "print hello world."

I just want to say, "print this!" I don't want all the surrounding

magic keywords. I just want to concentrate on the task. That's the basic

idea. So I have tried to make Ruby code concise and succinct."

Yukihiro Matsumoto. (www.artima.com/intv/ruby)





We like Ruby too (though not quite as much as newLISP :-))



Here's a quote from a language whose designer's

name also ends with *tz (Lutz not Matz):





"newLISP relies on a minimum of theoretical concepts. It

does not implement many paradigms or principles

discovered or invented in Computers Science and used in

other computer languages. The LISP list is the basic

paradigm for data and program structure and  is enough to

capture, represent and process the highest degree of

complexity.



newLISP is very small and has built-in most of the

technologies needed in today's networked and

distributed applications. Tomorrow's software systems

are not constituted by big monolithic systems but small

agile agents running and cooperating on distributed

architectures. newLISP is small enough to run on

embedded systems or distributed server farms built from

thousands of small simple computer nodes.



newLISP recognizes the changing nature of progressing

technology and constantly tries to adapt to it. Over

the years the functionality found in newLISP has

undergone many changes adapting to what is necessary at

the time.



The newLISP Philosophy can be expressed with the few

words simple, small, agile, cooperative, adapting."
Title:
Post by: _ex_ on September 03, 2006, 04:28:52 PM
hmm.. nice to see cormullion... ;)

BTW your code doesn't work for me... I've done the changes:

(setq freqLang "TEOIARNSHLMYUCWDGPFBVKJ")

(define (in-range? x low high) (and (>= x low) (<= x high)))

(define (letter? c) (or
(in-range? (char c) (char "a") (char "z"))
(in-range? (char c) (char "A") (char "Z"))))

(set 'letters-used
(unique (sort (map upper-case (filter letter? (explode text))))))

(set 'letter-freq-table
(map list letters-used (count letters-used (map upper-case (explode text)))))

(sort letter-freq-table
(fn (x y) (> (last x) (last y))))

(set 'dict
(map (fn (e f) (list (first e) (last e) f)) letter-freq-table (explode freqLang)))

(map (fn (chr)
(set 'letter (lookup (upper-case chr) dict))
(set 'upper-case? (in-range? (char chr) (char "A") (char "Z")))
(if letter
(if upper-case? (print letter) (print (lower-case letter)))
(print chr)))
(explode text))

Yeah Lu(tz) ... Ma(tz) nice catch :)