Mombu the Programming Forum sponsored links

Go Back   Mombu the Programming Forum > Programming > trying to write a permutation procedure
User Name
Password
REGISTER NOW! Mark Forums Read

sponsored links


Reply
 
1 10th April 05:11
aoi
External User
 
Posts: 1
Default trying to write a permutation procedure



hello all!

i have just started learning logo: it is a wonderful language. i tried
learning lisp some months ago but just couldn't get into it. logo is
different: when you get bored, you always have turtle graphics!

ok, so i've got one thing i'd like to do, but logo is basically my
first programming language so i do not a very good idea as to how to
go about it. all i want to do is to define some kind of procedure
which will permute the elements of a list in a specified manner. more
specifically, i'd like to take the 7-element list

[C D E F G A B]

(which represents the C-major scale) and permute it by "going through
it" at various intervals, viz.

3rds: [C E G B D F A]
5ths: [C G D A E B F]
....etc...

however, i'd also like the procedure to be open to other sorts of
permutations. it seems to me that the best way to accomplish this
would be to do the whole thing macro-style; unfortunately i do not
understand how to write those yet though i am seeing the gist of what
they do.

....

working on this, i managed to write an elementary "second" function,

to 2nd :list
output first (butfirst :list)
end

but could not manage a working "kth" function, which is what would
seem to be most handy:

to kth :list :k
if k=0 [output []]
if k=1 [output first :list]
repeat :k-1 [first (butfirst :list)]
end

also, is there a primitive which returns the order (number of
elements) of a list?

thanks! any help/thoughts are appreciated!

tanya
  Reply With Quote


  sponsored links


2 10th April 05:11
hrvoje blazevic
External User
 
Posts: 1
Default trying to write a permutation procedure



Seeing that the "first" problem you come up with is permutations, maybe
you should have stayed with Lisp :-).

Uff... confusing iteration for recursion. You should read a good book
(like CSLS) before attempting this again.

Anyway kth exists in Logo as ITEM.

I do not feel like dwelling into your particular problem here, but
here's the standard permutations solution:

to perm :lst
if emptyp :lst [op [[]]]
op map.se [[x] [op map [[y] [op fput :x :y]] perm remove :x :lst]] :lst
end

BTW: If you need to use repeating elements (not in your examples), then
use remove1 instead of remove.

to remove1 :e :lst
if emptyp :lst [op :lst]
if .eq :e first :lst [op bf :lst]
op fput first :lst remove1 :e bf :lst
end

-- Hrvoje
  Reply With Quote


  sponsored links


3 10th April 05:11
bh
External User
 
Posts: 1
Default trying to write a permutation procedure


aoi@nm.ru (Allecs Chime-Ingrae) writes:


Although there is a Logo primitive operation, ITEM, that does
exactly what you're after here, it'll be worthwhile for you to
learn how to write it yourself.

First of all, you don't really want to do FIRST (BUTFIRST :LIST)
k-1 times; you just want to BUTFIRST that many times.

Secondly, if you are writing an operation (something that has an
OUTPUT), then it has to OUTPUT in every case. Your procedure calls
OUTPUT in the base case
IF :K=1 [OUTPUT ...]
but not in the non-base case.

So, what you wanted to write (but this still isn't right; we're
working toward a correct solution and this is the first step) was
OUTPUT FIRST (REPEAT :K-1 [BUTFIRST :LIST]) ; WRONG!
This is better, because your procedure always outputs, and
because you are calling FIRST only once. But it's still wrong
because FIRST needs an input, and REPEAT doesn't output. REPEAT
is used for commands, such as moving the turtle or printing
something, not for operations.

You *could* use REPEAT in a correct, but ugly, solution:

TO KTH :K :LIST
REPEAT :K-1 [MAKE "LIST BUTFIRST :LIST]
OUTPUT FIRST :LIST
END

This works because the second input to REPEAT is a complete instruction, using
the MAKE command, not an expression that produces a value and doesn't use it
for anything. But it's considered ugly Logo style. The standard solution
looks like this:

TO KTH :K :LIST
IF :K=1 [OUTPUT FIRST :LIST]
OUTPUT KTH :K-1 (BUTFIRST :LIST)
END

This is a recursive solution; KTH calls itself as a helper procedure.

If your dialect of Logo provides the Berkeley Logo procedure library,
you can also say

TO KTH :K :LIST
OUTPUT FIRST (CASCADE :K-1 "BUTFIRST :LIST)
END

But to solve your original problem you need more than KTH because
you can't just forget about the notes that you skip over; you have
to come back to them later somehow. (This is left as an exercise
for the reader. :-)


Yes, COUNT.

P.S. I don't see why you think you need macros for this!
  Reply With Quote
4 10th April 05:11
pavel boytchev
External User
 
Posts: 1
Default trying to write a permutation procedure


Hi (Zdrastvui) Tanya,

Have a look at the ITEM function. However, if you want to "manually"
take
the K-th element of a list, you should do (K-1) BUTFIRST-s (to skip K-1
elements), and then to use one single FIRST to take the next, the K-th
one. Alternatively, if you want to do this recursively, you may use that
usually

KTH :LIST :K is the same as KTH (BUTFIRST :LIST) :K-1

and when K becomes 1:

KTH :LIST :K is equivalent to FIRST :LIST


This is what COUNT is used for.

Pavel


LogoForum messages are archived at:
http://groups.yahoo.com/group/LogoForum
  Reply With Quote
5 10th April 05:11
aoi
External User
 
Posts: 1
Default trying to write a permutation procedure


i like your thinking.


ah, ok! that makes sense. thank you.

i ended up doing this several hours after i posted... but i was still
doing the (first (butfirst :list) business.


yes! i was really going for this after i did it with repeat, but just
ended up getting frustrated. i have not quite learned how to fit my
brain around writing functions recursively, though i am getting better
at spotting where that sort of thing should be used. can you recommend
a good way to learn this?

yes, i use ucblogo! =)

i realize the difficulty of this. but it appears the solution
shouldn't *actually* require "skipping" each element at a specified
interval, because i realized tonight that

2nds = [C D E F G A B C] <-- is the inverse of 7ths
3rds = [C E G B D F A C] <-- is the inverse of 6ths
4ths = [C F B E A D G C] <-- is the inverse of 5ths
5ths = [C G D A E B F C] <-- is the inverse of 4ths
6ths = [C A F D B G E C] <-- is the inverse of 3rds
7ths = [C B A G F E D C] <-- is the inverse of 2nds
<tangent>

.... which is curious, because if you've played around with what
buckminster fuller calls "indigs," eg adding the digits of a number
across, you may have seen that, when you consider the indigs of the
multiplication table (going vertically for each integer)

2 = 2 3 =3 4 = 4 5 =5 6 =6 7 =7
4 = 4 6 =6 8 = 8 10=1 12=3 14=5
6 = 6 9 =9 12=3 15= 6 18=9 21=3
8 = 8 12=3 16=7 20= 2 24=6 28=1
10=1 15=6 20= 2 25=7 30=3 35= 8
12=3 18=9 24= 6 30=3 36=9 42= 6
14=5 21=3 28=1 35= 8 42=6 49= 4
16=7 24=6 32=5 40= 4 48=3 56= 2
18=9 27=9 36=9 45=9 54=9 63=9
20= 2 30=3 40= 4 50=5 60=6 70=7

the indigs of two and seven are the reverses of each other; similarly
three and six, and four and five... but anyway.
</tangent>

ok -- this is where i may be confused; a macro is the only sort of
procedure in logo which will accept functions as arguments, correct?
or is there a way to pass a function to to -- and if there is, how do
i go about it? my thinking *was* that i would need to do this; i can't
quite explain it... perhaps i am just anxious to learn macros... but
it would be a handy thing to be able to pass functions to functions in
any case... especially for drawing neat graphics!

pax
tanya
  Reply With Quote
6 10th April 05:11
bh
External User
 
Posts: 1
Default trying to write a permutation procedure


aoi@nm.ru (Allecs Chime-Ingrae) writes:

Yeah, read _Computer Science Logo Style_. :-)
http://www.cs.berkeley.edu/~bh/logo.html

There's also a book called _Thinking Recursively_ by Eric Roberts.


Adding the digits of a number is the same as taking its remainder
on division by 9. [The remainder function distributes over
addition and multiplication, so
(\Sum_{i=0}^k d_i 10^i) mod 9 =
\Sum_{i=0}^k ((d_i 10^i) mod 9) =
\Sum_{i=0}^k ((d_i mod 9)(10^i mod 9)) =
\Sum_{i=0}^k d_i
because d_i <= 9 (you have to worry a little about 9 and 0,
but these details you can work out for yourself :-) and
10 mod 9 = 1, so 10^i mod 9 = 1 for all i.] So this explains
why there is a sum-of-digits relationship between k and 9-k.


Strictly speaking, no Logo procedure, including macros, can take
functions as arguments, because procedures aren't first-class data.
But Logo has an equivalent feature, which is that any Logo procedure
can take the *name* of a procedure, or the *text* of a procedure,
as an argument, and can then APPLY or INVOKE those things with arguments,
like this:

to map :func :data
if emptyp :data [output []]
output fput (invoke :func first :data) (map :func bf :data)
end

? show map "first [the rain in spain]
[t r i s]

? show map [word ? ?] [j p g r]
[jj pp gg rr]

The UCBLogo library version of MAP is more complicated than this
in various ways, but this is the essential idea.

Really the only situation in which you need macros is if you want
the called procedure (the macro) to be able to do a STOP, OUTPUT,
or LOCAL on behalf of its caller. If the called procedure is an
ordinary procedure, it can STOP itself, but it can't STOP its
caller. What macros do is let the called procedure generate an
instruction which is then carried out *by the caller* after the
macro outputs it.
  Reply With Quote
Reply


Thread Tools
Display Modes




Copyright © 2006 SmartyDevil.com - Dies Mies Jeschet Boenedoesef Douvema Enitemaus -
666