I'm missing my foreach keys %hash... :(

Q&A's, tips, howto's
Locked
_ex_
Posts: 23
Joined: Wed Aug 23, 2006 3:17 pm
Location: Peru

I'm missing my foreach keys %hash... :(

Post by _ex_ »

Hi there, I want to use hash tables in newLisp,
Take for example this code (Python challenge ;)

Code: Select all

;* 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)

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

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:

Code: Select all

(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:

Code: Select all

(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 ;-(((((

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

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 ;)

Code: Select all

; 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

_ex_
Posts: 23
Joined: Wed Aug 23, 2006 3:17 pm
Location: Peru

Post by _ex_ »

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...

Code: Select all

(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:

Code: Select all

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

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

_ex_ wrote: 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/viewto ... =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:

Code: Select all

(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:

Code: Select all

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...

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

your code for inverting the dictionary is fine, just use 'name' once more when assigning the value:

Code: Select all

(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.

_ex_
Posts: 23
Joined: Wed Aug 23, 2006 3:17 pm
Location: Peru

Now I'm REALLY missing my hashes... :(

Post by _ex_ »

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):

Code: Select all

# 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...

Code: Select all

(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)

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

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:

Code: Select all

;; 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:

Code: Select all

(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

_ex_
Posts: 23
Joined: Wed Aug 23, 2006 3:17 pm
Location: Peru

Post by _ex_ »

Lutz my friend, seems I still have lots to walk in the newLisp way :)
In your example:

Code: Select all

; 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

Code: Select all

(println myhash:sort-by-value-descend)
=> 456 "x"
=> 123 "a"
=> 5 "d"
This is the hard part for me.
Regards.
(ex)

frontera000
Posts: 72
Joined: Sun Jun 11, 2006 8:02 pm
Location: berkeley, california
Contact:

Post by frontera000 »

Code: Select all

(sort (map (lambda (x) (list (myhash:get x) x)) (myhash:keys))  (lambda (x y) (< y x)))

_ex_
Posts: 23
Joined: Wed Aug 23, 2006 3:17 pm
Location: Peru

Post by _ex_ »

Thank you very much frontera000!

Code: Select all

(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))))

_ex_
Posts: 23
Joined: Wed Aug 23, 2006 3:17 pm
Location: Peru

finally...

Post by _ex_ »

Finally... but you must to agree:
It takes more code (and more neurons) :)

Code: Select all

(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)

HPW
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Post by HPW »

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.

Code: Select all

(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)))) 
Hans-Peter

_ex_
Posts: 23
Joined: Wed Aug 23, 2006 3:17 pm
Location: Peru

Post by _ex_ »

nice to know :)

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

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 :-)

Code: Select all

(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.

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Where Is Everybody

Post by m i c h a e l »

Hi cormullion :-)
cormullion wrote: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 ;-)

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

:-) If only the decrypted solution was interesting enough when you finally manage to decode it... Perhaps Dan Brown has the same problem...

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Post by m i c h a e l »

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

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Her is a way to generate the freq-table with much less code:

Code: Select all

(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

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Very nice! Good to see a craftsman at work!

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

... continuing from previous post

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

Code: Select all

(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:

Code: Select all

freq-tab:_a => (9 0)
the empty list in:

Code: Select all

(bayes-train (explode text) '() 'freq-tab)
provided a place for the 0 position, which you could use to store another letter instead.

Lutz

_ex_
Posts: 23
Joined: Wed Aug 23, 2006 3:17 pm
Location: Peru

Post by _ex_ »

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 ;)

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Post by m i c h a e l »

Hi (ex) :-)

Here is the url for cormullion's Da Vinci Code post.

m i c h a e l

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Another attempt to produce a succint yet readable solution...

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

<pre>
(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)</pre>

;->
"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."

_ex_
Posts: 23
Joined: Wed Aug 23, 2006 3:17 pm
Location: Peru

Post by _ex_ »

hmm.. nice to see cormullion... ;)
BTW your code doesn't work for me... I've done the changes:

Code: Select all

(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 :)

Locked